feat: add workspace security setting definition

This commit is contained in:
johnnyjoy
2024-08-17 13:11:53 +08:00
parent faa6fcf31c
commit a5bc443db9
21 changed files with 488 additions and 650 deletions

View File

@ -28,7 +28,7 @@ function App() {
}, [workspaceStore.setting.customStyle]);
useEffect(() => {
const hasCustomBranding = workspaceStore.profile.plan === PlanType.PRO;
const hasCustomBranding = workspaceStore.profile.subscription?.plan === PlanType.PRO;
if (!hasCustomBranding || !workspaceStore.setting.branding) {
return;
}

View File

@ -35,10 +35,10 @@ const Header: React.FC = () => {
<Logo className="mr-2" />
Slash
</Link>
{[PlanType.PRO, PlanType.ENTERPRISE].includes(profile.plan) && (
{profile.subscription?.plan && [PlanType.PRO, PlanType.ENTERPRISE].includes(profile.subscription.plan) && (
<span className="ml-1 text-xs px-1.5 leading-5 border rounded-full bg-blue-600 border-blue-700 text-white shadow dark:opacity-70">
{/* PRO or ENT */}
{profile.plan.substring(0, 3)}
{profile.subscription.plan.substring(0, 3)}
</span>
)}
{shouldShowRouterSwitch && (

View File

@ -9,7 +9,7 @@ interface Props {
const Logo = ({ className }: Props) => {
const workspaceStore = useWorkspaceStore();
const hasCustomBranding = workspaceStore.profile.plan === PlanType.PRO;
const hasCustomBranding = workspaceStore.profile.subscription?.plan === PlanType.PRO;
const branding = hasCustomBranding && workspaceStore.setting.branding ? new TextDecoder().decode(workspaceStore.setting.branding) : "";
return (
<div className={classNames("w-8 h-auto dark:text-gray-500 rounded-lg overflow-hidden", className)}>

View File

@ -35,7 +35,7 @@ const WorkspaceSection = () => {
const [workspaceSetting, setWorkspaceSetting] = useState<WorkspaceSetting>(workspaceStore.setting);
const originalWorkspaceSetting = useRef<WorkspaceSetting>(workspaceStore.setting);
const allowSave = !isEqual(originalWorkspaceSetting.current, workspaceSetting);
const hasCustomBranding = workspaceStore.profile.plan === PlanType.PRO;
const hasCustomBranding = workspaceStore.profile.subscription?.plan === PlanType.PRO;
const branding = hasCustomBranding && workspaceSetting.branding ? new TextDecoder().decode(workspaceSetting.branding) : "";
const onBrandingChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
@ -80,12 +80,10 @@ const WorkspaceSection = () => {
}
try {
const setting = (
await workspaceServiceClient.updateWorkspaceSetting({
setting: workspaceSetting,
updateMask: updateMask,
})
).setting as WorkspaceSetting;
const setting = await workspaceServiceClient.updateWorkspaceSetting({
setting: workspaceSetting,
updateMask: updateMask,
});
setWorkspaceSetting(setting);
await workspaceStore.fetchWorkspaceSetting();
originalWorkspaceSetting.current = setting;

View File

@ -58,7 +58,7 @@ const SubscriptionSetting: React.FC = () => {
<p className="text-2xl shrink-0 font-semibold text-gray-900 dark:text-gray-500">Subscription</p>
<div className="mt-2">
<span className="text-gray-500 mr-2">Current plan:</span>
<span className="text-2xl mr-4 dark:text-gray-400">{stringifyPlanType(profile.plan)}</span>
<span className="text-2xl mr-4 dark:text-gray-400">{stringifyPlanType(profile.subscription?.plan)}</span>
</div>
<Textarea
className="w-full mt-2"
@ -70,7 +70,7 @@ const SubscriptionSetting: React.FC = () => {
/>
<div className="w-full flex justify-between items-center mt-4">
<div>
{profile.plan === PlanType.FREE && (
{profile.subscription?.plan === PlanType.FREE && (
<Link href="https://yourselfhosted.lemonsqueezy.com/checkout/buy/947e9a56-c93a-4294-8d71-2ea4b0f3ec51" target="_blank">
Buy a license key
<Icon.ExternalLink className="w-4 h-auto ml-1" />
@ -78,7 +78,7 @@ const SubscriptionSetting: React.FC = () => {
)}
</div>
<div className="flex justify-end items-center gap-2">
{profile.plan !== PlanType.FREE && (
{profile.subscription?.plan !== PlanType.FREE && (
<Button color="neutral" variant="plain" onClick={handleDeleteLicenseKey}>
Reset
</Button>

View File

@ -33,7 +33,7 @@ const WorkspaceSetting = () => {
<p className="text-2xl shrink-0 font-semibold text-gray-900 dark:text-gray-500">Subscription</p>
<div className="mt-2">
<span className="text-gray-500 mr-2">Current plan:</span>
<span className="text-2xl mr-4 dark:text-gray-400">{stringifyPlanType(profile.plan)}</span>
<span className="text-2xl mr-4 dark:text-gray-400">{stringifyPlanType(profile.subscription?.plan)}</span>
<Link to="/setting/subscription" unstable_viewTransition>
<Button size="sm" variant="outlined" startDecorator={<Icon.Settings className="w-4 h-auto" />}>
Manage

View File

@ -1,6 +1,6 @@
import { PlanType } from "@/types/proto/api/v1/subscription_service";
export const stringifyPlanType = (planType: PlanType) => {
export const stringifyPlanType = (planType: PlanType = PlanType.FREE) => {
if (planType === PlanType.FREE) {
return "Free";
} else if (planType === PlanType.PRO) {

View File

@ -24,17 +24,17 @@ const useWorkspaceStore = create<WorkspaceState>()((set, get) => ({
profile: WorkspaceProfile.fromPartial({}),
setting: WorkspaceSetting.fromPartial({}),
fetchWorkspaceProfile: async () => {
const workspaceProfile = (await workspaceServiceClient.getWorkspaceProfile({})).profile as WorkspaceProfile;
const workspaceProfile = await workspaceServiceClient.getWorkspaceProfile({});
set({ ...get(), profile: workspaceProfile });
return workspaceProfile;
},
fetchWorkspaceSetting: async () => {
const workspaceSetting = (await workspaceServiceClient.getWorkspaceSetting({})).setting as WorkspaceSetting;
const workspaceSetting = await workspaceServiceClient.getWorkspaceSetting({});
set({ ...get(), setting: workspaceSetting });
return workspaceSetting;
},
checkFeatureAvailable: (feature: FeatureType): boolean => {
return get().profile.features.includes(feature);
return get().profile.subscription?.features.includes(feature) || false;
},
}));