From 0af490365745a5d142eae3e7b1ea8df2e4c071cb Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 20 Sep 2023 23:13:30 +0800 Subject: [PATCH] feat: add custom style workspace setting --- api/v2/workspace_setting_service.go | 22 +++ .../components/setting/WorkspaceSection.tsx | 80 ++++++++-- frontend/web/src/helpers/api.ts | 14 +- proto/api/v2/workspace_setting_service.proto | 6 +- proto/buf.gen.yaml | 2 - proto/gen/api/v2/README.md | 2 + .../api/v2/workspace_setting_service.pb.go | 150 ++++++++++-------- proto/gen/store/README.md | 6 +- proto/gen/store/workspace_setting.pb.go | 135 +++++++++++----- proto/store/workspace_setting.proto | 10 +- store/workspace_setting.go | 11 +- 11 files changed, 292 insertions(+), 146 deletions(-) diff --git a/api/v2/workspace_setting_service.go b/api/v2/workspace_setting_service.go index d7ad2fa..fd0cc86 100644 --- a/api/v2/workspace_setting_service.go +++ b/api/v2/workspace_setting_service.go @@ -34,6 +34,10 @@ func (s *WorkspaceSettingService) GetWorkspaceSetting(ctx context.Context, _ *ap workspaceSetting.EnableSignup = v.GetEnableSignup() } else if v.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH { workspaceSetting.ResourceRelativePath = v.GetResourceRelativePath() + } else if v.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_CUSTOM_STYLE { + workspaceSetting.CustomStyle = v.GetCustomStyle() + } else if v.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_CUSTOM_SCRIPT { + workspaceSetting.CustomScript = v.GetCustomScript() } else { return nil, status.Errorf(codes.Internal, "invalid workspace setting key: %s", v.Key.String()) } @@ -67,6 +71,24 @@ func (s *WorkspaceSettingService) UpdateWorkspaceSetting(ctx context.Context, re }); err != nil { return nil, status.Errorf(codes.Internal, "failed to update workspace setting: %v", err) } + } else if path == "custom_style" { + if _, err := s.Store.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{ + Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_CUSTOM_STYLE, + Value: &storepb.WorkspaceSetting_CustomStyle{ + CustomStyle: request.Setting.CustomStyle, + }, + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to update workspace setting: %v", err) + } + } else if path == "custom_script" { + if _, err := s.Store.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{ + Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_CUSTOM_SCRIPT, + Value: &storepb.WorkspaceSetting_CustomScript{ + CustomScript: request.Setting.CustomScript, + }, + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to update workspace setting: %v", err) + } } else { return nil, status.Errorf(codes.InvalidArgument, "invalid path: %s", path) } diff --git a/frontend/web/src/components/setting/WorkspaceSection.tsx b/frontend/web/src/components/setting/WorkspaceSection.tsx index d2841df..2f23d92 100644 --- a/frontend/web/src/components/setting/WorkspaceSection.tsx +++ b/frontend/web/src/components/setting/WorkspaceSection.tsx @@ -1,41 +1,87 @@ -import { Checkbox } from "@mui/joy"; -import { useEffect, useState } from "react"; +import { Button, Checkbox, Textarea } from "@mui/joy"; +import { isEqual } from "lodash-es"; +import { useEffect, useRef, useState } from "react"; +import toast from "react-hot-toast"; +import { workspaceSettingServiceClient } from "@/grpcweb"; import { WorkspaceSetting } from "@/types/proto/api/v2/workspace_setting_service"; -import { getWorkspaceSetting, updateWorkspaceSetting } from "../../helpers/api"; const WorkspaceSection: React.FC = () => { - const [workspaceSetting, setWorkspaceSetting] = useState(); + const [workspaceSetting, setWorkspaceSetting] = useState(WorkspaceSetting.fromPartial({})); + const originalWorkspaceSetting = useRef(WorkspaceSetting.fromPartial({})); useEffect(() => { - getWorkspaceSetting().then(({ setting }) => { - setWorkspaceSetting(setting); + workspaceSettingServiceClient.getWorkspaceSetting({}).then(({ setting }) => { + if (setting) { + setWorkspaceSetting(setting); + originalWorkspaceSetting.current = setting; + } }); }, []); - const handleDisallowSignUpChange = async (value: boolean) => { - const { setting } = await updateWorkspaceSetting( - { - ...workspaceSetting, - enableSignup: value, - } as WorkspaceSetting, - ["enable_signup"] - ); - setWorkspaceSetting(setting); + const handleEnableSignUpChange = async (value: boolean) => { + setWorkspaceSetting({ + ...workspaceSetting, + enableSignup: value, + }); }; - if (!workspaceSetting) return <>; + const handleCustomStyleChange = async (value: string) => { + setWorkspaceSetting({ + ...workspaceSetting, + customStyle: value, + }); + }; + + const handleSaveWorkspaceSetting = async () => { + const updateMask: string[] = []; + if (!isEqual(originalWorkspaceSetting.current.enableSignup, workspaceSetting.enableSignup)) { + updateMask.push("enable_signup"); + } + if (!isEqual(originalWorkspaceSetting.current.customStyle, workspaceSetting.customStyle)) { + updateMask.push("custom_style"); + } + if (updateMask.length === 0) { + toast.error("No changes made"); + return; + } + + const { setting } = await workspaceSettingServiceClient.updateWorkspaceSetting({ + setting: workspaceSetting, + updateMask: updateMask, + }); + toast.success("Workspace setting saved successfully"); + if (setting) { + setWorkspaceSetting(setting); + originalWorkspaceSetting.current = setting; + } + }; return (

Workspace settings

+
+

Custom style

+