feat: hide ask ai button when key is empty (#1515)

* Add option to hide Ask AI and update dev version

* Fix formatting according to eslint

* Replace option to hide Ask AI with auto hiding based on config

* Fix golangci-lint errors

* Remove showAskAI logic from OpenAPI
This commit is contained in:
João Nuno Mota 2023-04-15 17:54:33 +01:00 committed by GitHub
parent 648634d376
commit 2c328a4540
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 30 deletions

View File

@ -24,4 +24,6 @@ type SystemStatus struct {
StorageServiceID int `json:"storageServiceId"`
// Local storage path
LocalStoragePath string `json:"localStoragePath"`
// Local storage path
OpenAIConfig OpenAIConfig `json:"openAIConfig"`
}

View File

@ -56,6 +56,10 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
},
StorageServiceID: api.DatabaseStorage,
LocalStoragePath: "",
OpenAIConfig: api.OpenAIConfig{
Key: "",
Host: "",
},
}
systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
@ -95,6 +99,13 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
systemStatus.StorageServiceID = int(baseValue.(float64))
} else if systemSetting.Name == api.SystemSettingLocalStoragePathName {
systemStatus.LocalStoragePath = baseValue.(string)
} else if systemSetting.Name == api.SystemSettingOpenAIConfigName {
openAIConfig := api.OpenAIConfig{}
err := json.Unmarshal([]byte(systemSetting.Value), &openAIConfig)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal system setting open ai config value").SetInternal(err)
}
systemStatus.OpenAIConfig = openAIConfig
}
}

View File

@ -1,7 +1,7 @@
import { useEffect } from "react";
import { NavLink, useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useLayoutStore, useUserStore } from "@/store/module";
import { useGlobalStore, useLayoutStore, useUserStore } from "@/store/module";
import { resolution } from "@/utils/layout";
import Icon from "./Icon";
import showSettingDialog from "./SettingDialog";
@ -14,8 +14,10 @@ const Header = () => {
const { t } = useTranslation();
const location = useLocation();
const userStore = useUserStore();
const globalStore = useGlobalStore();
const layoutStore = useLayoutStore();
const showHeader = layoutStore.state.showHeader;
const showAskAI = globalStore.showAskAI();
const isVisitorMode = userStore.isVisitorMode() && !userStore.state.user;
useEffect(() => {
@ -107,13 +109,15 @@ const Header = () => {
</NavLink>
{!isVisitorMode && (
<>
<button
id="header-ask-ai"
className="px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick={() => showAskAIDialog()}
>
<Icon.Bot className="mr-3 w-6 h-auto opacity-70" /> {t("ask-ai.title")}
</button>
{showAskAI && (
<button
id="header-ask-ai"
className="px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick={() => showAskAIDialog()}
>
<Icon.Bot className="mr-3 w-6 h-auto opacity-70" /> {t("ask-ai.title")}
</button>
)}
<button
id="header-archived-memo"
className="px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg text-gray-800 dark:text-gray-300 hover:bg-white hover:shadow dark:hover:bg-zinc-700"

View File

@ -16,6 +16,7 @@ interface State {
disablePublicMemos: boolean;
additionalStyle: string;
additionalScript: string;
openAIConfig: OpenAIConfig;
}
const SystemSection = () => {
@ -29,10 +30,7 @@ const SystemSection = () => {
additionalStyle: systemStatus.additionalStyle,
additionalScript: systemStatus.additionalScript,
disablePublicMemos: systemStatus.disablePublicMemos,
});
const [openAIConfig, setOpenAIConfig] = useState<OpenAIConfig>({
key: "",
host: "",
openAIConfig: systemStatus.openAIConfig,
});
useEffect(() => {
@ -47,18 +45,10 @@ const SystemSection = () => {
additionalStyle: systemStatus.additionalStyle,
additionalScript: systemStatus.additionalScript,
disablePublicMemos: systemStatus.disablePublicMemos,
openAIConfig: systemStatus.openAIConfig,
});
}, [systemStatus]);
useEffect(() => {
api.getSystemSetting().then(({ data: { data: systemSettings } }) => {
const openAIConfigSetting = systemSettings.find((setting) => setting.name === "openai-config");
if (openAIConfigSetting) {
setOpenAIConfig(JSON.parse(openAIConfigSetting.value));
}
});
}, []);
const handleAllowSignUpChanged = async (value: boolean) => {
setState({
...state,
@ -97,9 +87,12 @@ const SystemSection = () => {
};
const handleOpenAIConfigKeyChanged = (value: string) => {
setOpenAIConfig({
...openAIConfig,
key: value,
setState({
...state,
openAIConfig: {
...state.openAIConfig,
key: value,
},
});
};
@ -107,8 +100,9 @@ const SystemSection = () => {
try {
await api.upsertSystemSetting({
name: "openai-config",
value: JSON.stringify(openAIConfig),
value: JSON.stringify(state.openAIConfig),
});
globalStore.setSystemStatus({ openAIConfig: state.openAIConfig });
} catch (error) {
console.error(error);
return;
@ -117,9 +111,12 @@ const SystemSection = () => {
};
const handleOpenAIConfigHostChanged = (value: string) => {
setOpenAIConfig({
...openAIConfig,
host: value,
setState({
...state,
openAIConfig: {
...state.openAIConfig,
host: value,
},
});
};
@ -225,7 +222,7 @@ const SystemSection = () => {
fontSize: "14px",
}}
placeholder={t("setting.system-section.openai-api-key-placeholder")}
value={openAIConfig.key}
value={state.openAIConfig.key}
onChange={(event) => handleOpenAIConfigKeyChanged(event.target.value)}
/>
<div className="form-label mt-2">
@ -238,7 +235,7 @@ const SystemSection = () => {
fontSize: "14px",
}}
placeholder={t("setting.system-section.openai-api-host-placeholder")}
value={openAIConfig.host}
value={state.openAIConfig.host}
onChange={(event) => handleOpenAIConfigHostChanged(event.target.value)}
/>
<Divider className="!mt-3 !my-4" />

View File

@ -23,6 +23,10 @@ export const initialGlobalState = async () => {
appearance: "system",
externalUrl: "",
},
openAIConfig: {
key: "",
host: "",
},
} as SystemStatus,
};
@ -65,6 +69,10 @@ export const useGlobalStore = () => {
isDev: () => {
return state.systemStatus.profile.mode !== "prod";
},
showAskAI: () => {
const openAIConfig = state.systemStatus.openAIConfig;
return Boolean(openAIConfig.key && openAIConfig.host);
},
fetchSystemStatus: async () => {
const { data: systemStatus } = (await api.getSystemStatus()).data;
store.dispatch(setGlobalState({ systemStatus: systemStatus }));

View File

@ -31,6 +31,10 @@ const globalSlice = createSlice({
appearance: "system",
externalUrl: "",
},
openAIConfig: {
key: "",
host: "",
},
},
} as State,
reducers: {

View File

@ -30,6 +30,7 @@ interface SystemStatus {
customizedProfile: CustomizedProfile;
storageServiceId: number;
localStoragePath: string;
openAIConfig: OpenAIConfig;
}
interface SystemSetting {