From 4427c70087e48932a28c2f8552730bd026e5b8c0 Mon Sep 17 00:00:00 2001 From: chenos Date: Sun, 19 Mar 2023 23:40:11 +0800 Subject: [PATCH] feat: compact theme (#1574) * feat: compact theme * fix: theme * fix: styling * fix: margin * feat: improve * fix: remove console.log --- packages/app/client/src/pages/index.tsx | 1 + packages/app/client/src/theme.ts | 6 ++ .../src/appInfo/CurrentAppInfoProvider.tsx | 35 ++++++---- packages/core/client/src/index.tsx | 2 +- packages/core/client/src/locale/zh_CN.ts | 5 +- packages/core/client/src/pm/index.tsx | 4 +- .../src/schema-component/antd/index.less | 20 ++++++ .../src/schema-component/antd/page/Page.tsx | 2 +- .../schema-templates/BlockTemplateDetails.tsx | 2 +- .../schema-templates/BlockTemplatePage.tsx | 2 +- .../SystemSettingsProvider.tsx | 22 ++++++- .../SystemSettingsShortcut.tsx | 13 ++++ packages/core/client/src/user/CurrentUser.tsx | 2 + .../core/client/src/user/LanguageSettings.tsx | 65 +++++++++++-------- packages/core/client/src/user/SwitchRole.tsx | 43 +++++++----- .../core/client/src/user/ThemeSettings.tsx | 47 ++++++++++++++ packages/plugins/client/src/server.ts | 1 + .../src/collections/systemSettings.ts | 5 ++ .../plugins/users/src/collections/users.ts | 5 ++ 19 files changed, 214 insertions(+), 68 deletions(-) create mode 100644 packages/app/client/src/theme.ts create mode 100644 packages/core/client/src/user/ThemeSettings.tsx diff --git a/packages/app/client/src/pages/index.tsx b/packages/app/client/src/pages/index.tsx index edec62ec01..56a28e6cad 100644 --- a/packages/app/client/src/pages/index.tsx +++ b/packages/app/client/src/pages/index.tsx @@ -1,3 +1,4 @@ +import '@/theme'; import { Application } from '@nocobase/client'; export const app = new Application({ diff --git a/packages/app/client/src/theme.ts b/packages/app/client/src/theme.ts new file mode 100644 index 0000000000..3c45d31b32 --- /dev/null +++ b/packages/app/client/src/theme.ts @@ -0,0 +1,6 @@ +if (localStorage.getItem('NOCOBASE_THEME') === 'compact') { + import('antd/dist/antd.compact.css'); +} else { + import('antd/dist/antd.css'); +} +window.document.documentElement.classList.add('theme-' + (localStorage.getItem('NOCOBASE_THEME') || 'default')); diff --git a/packages/core/client/src/appInfo/CurrentAppInfoProvider.tsx b/packages/core/client/src/appInfo/CurrentAppInfoProvider.tsx index 8c6aa024af..fb434249df 100644 --- a/packages/core/client/src/appInfo/CurrentAppInfoProvider.tsx +++ b/packages/core/client/src/appInfo/CurrentAppInfoProvider.tsx @@ -1,5 +1,5 @@ -import React, { createContext, useContext } from 'react'; import { Spin } from 'antd'; +import React, { createContext, useContext } from 'react'; import { useRequest } from '../api-client'; export const CurrentAppInfoContext = createContext(null); @@ -8,17 +8,26 @@ export const useCurrentAppInfo = () => { return useContext(CurrentAppInfoContext); }; export const CurrentAppInfoProvider = (props) => { - const result = useRequest({ - url: 'app:getInfo', - }); - if (result.loading) { - return ; - } - return ( - - {props.children} - + const result = useRequest( + { + url: 'app:getInfo', + }, + { + onSuccess(data) { + const localTheme = localStorage.getItem('NOCOBASE_THEME'); + if (localTheme !== data?.data?.theme) { + localStorage.setItem('NOCOBASE_THEME', data?.data?.theme); + window.location.reload(); + } + }, + }, ); + const localTheme = localStorage.getItem('NOCOBASE_THEME'); + if (localTheme && localTheme !== result?.data?.data?.theme) { + return ; + } + if (result.loading) { + return ; + } + return {props.children}; }; diff --git a/packages/core/client/src/index.tsx b/packages/core/client/src/index.tsx index 0eec7fb643..610193ba47 100644 --- a/packages/core/client/src/index.tsx +++ b/packages/core/client/src/index.tsx @@ -1,4 +1,3 @@ -import 'antd/dist/antd.css'; import './global.less'; export * from './acl'; @@ -27,3 +26,4 @@ export * from './schema-templates'; export * from './settings-form'; export * from './system-settings'; export * from './user'; + diff --git a/packages/core/client/src/locale/zh_CN.ts b/packages/core/client/src/locale/zh_CN.ts index 166ad19604..5d17f070e5 100644 --- a/packages/core/client/src/locale/zh_CN.ts +++ b/packages/core/client/src/locale/zh_CN.ts @@ -680,5 +680,8 @@ export default { 'Use variable': '使用变量', 'True': '真', 'False': '假', - 'Prettify': '格式化' + 'Prettify': '格式化', + 'Theme': '主题', + 'Default theme': '默认主题', + 'Compact theme': '紧凑主题', } diff --git a/packages/core/client/src/pm/index.tsx b/packages/core/client/src/pm/index.tsx index 11b9f6d782..14eb659340 100644 --- a/packages/core/client/src/pm/index.tsx +++ b/packages/core/client/src/pm/index.tsx @@ -219,7 +219,7 @@ const PluginList = (props) => { } /> -
+
{React.createElement( { local: LocalPlugins, @@ -399,7 +399,7 @@ const SettingsCenter = (props) => { } /> )} -
+
{aclPluginTabCheck ? ( component && React.createElement(component) ) : ( diff --git a/packages/core/client/src/schema-component/antd/index.less b/packages/core/client/src/schema-component/antd/index.less index 28bd4107dd..fa2dbbc1a3 100644 --- a/packages/core/client/src/schema-component/antd/index.less +++ b/packages/core/client/src/schema-component/antd/index.less @@ -2,3 +2,23 @@ color: #000000d9; font-weight:600; } + +.ant-table-pagination.ant-pagination { + margin-bottom: 0 !important; +} + +.ant-formily-item { + font-size: inherit !important; +} + +.theme-compact { + .ant-formily-item { + margin-bottom: 16px; + } + .ant-card { + margin-bottom: 16px !important; + } + .m24 { + margin: 16px !important; + } +} \ No newline at end of file diff --git a/packages/core/client/src/schema-component/antd/page/Page.tsx b/packages/core/client/src/schema-component/antd/page/Page.tsx index c85de87ef6..00a46c475b 100644 --- a/packages/core/client/src/schema-component/antd/page/Page.tsx +++ b/packages/core/client/src/schema-component/antd/page/Page.tsx @@ -253,7 +253,7 @@ export const Page = (props) => { /> )}
-
+
{loading ? ( ) : !disablePageHeader && enablePageTabs ? ( diff --git a/packages/core/client/src/schema-templates/BlockTemplateDetails.tsx b/packages/core/client/src/schema-templates/BlockTemplateDetails.tsx index 5929c4837a..9633314827 100644 --- a/packages/core/client/src/schema-templates/BlockTemplateDetails.tsx +++ b/packages/core/client/src/schema-templates/BlockTemplateDetails.tsx @@ -81,7 +81,7 @@ export const BlockTemplateDetails = () => { ghost={false} title={} /> -
+
diff --git a/packages/core/client/src/schema-templates/BlockTemplatePage.tsx b/packages/core/client/src/schema-templates/BlockTemplatePage.tsx index b7a5682801..c75026a082 100644 --- a/packages/core/client/src/schema-templates/BlockTemplatePage.tsx +++ b/packages/core/client/src/schema-templates/BlockTemplatePage.tsx @@ -11,7 +11,7 @@ export const BlockTemplatePage = () => { return (
-
+
diff --git a/packages/core/client/src/system-settings/SystemSettingsProvider.tsx b/packages/core/client/src/system-settings/SystemSettingsProvider.tsx index 6f735fd041..8a6af20a4a 100644 --- a/packages/core/client/src/system-settings/SystemSettingsProvider.tsx +++ b/packages/core/client/src/system-settings/SystemSettingsProvider.tsx @@ -10,9 +10,25 @@ export const useSystemSettings = () => { }; export const SystemSettingsProvider: React.FC = (props) => { - const result = useRequest({ - url: 'systemSettings:get/1?appends=logo', - }); + const result = useRequest( + { + url: 'systemSettings:get/1?appends=logo', + }, + { + onSuccess(data) { + const localTheme = localStorage.getItem('NOCOBASE_THEME'); + if (!localTheme) { + const theme = data?.data?.options?.theme; + localStorage.setItem('NOCOBASE_THEME', theme || 'default'); + window.location.reload(); + } + }, + }, + ); + const localTheme = localStorage.getItem('NOCOBASE_THEME'); + if (!localTheme) { + return ; + } if (result.loading) { return ; } diff --git a/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx b/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx index 5d5484b995..2a6172da01 100644 --- a/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx +++ b/packages/core/client/src/system-settings/SystemSettingsShortcut.tsx @@ -192,6 +192,19 @@ const schema2: ISchema = { // accept: 'jpg,png' }, }, + 'options.theme': { + type: 'string', + title: '{{t("Theme")}}', + 'x-component': 'Select', + 'x-component-props': { + // mode: 'multiple', + }, + 'x-decorator': 'FormItem', + enum: [ + { label: '{{t("Default theme")}}', value: 'default' }, + { label: '{{t("Compact theme")}}', value: 'compact' }, + ], + }, enabledLanguages: { type: 'array', title: '{{t("Enabled languages")}}', diff --git a/packages/core/client/src/user/CurrentUser.tsx b/packages/core/client/src/user/CurrentUser.tsx index c16045d9d1..6d55f5cad6 100644 --- a/packages/core/client/src/user/CurrentUser.tsx +++ b/packages/core/client/src/user/CurrentUser.tsx @@ -9,6 +9,7 @@ import { ChangePassword } from './ChangePassword'; import { EditProfile } from './EditProfile'; import { LanguageSettings } from './LanguageSettings'; import { SwitchRole } from './SwitchRole'; +import { ThemeSettings } from './ThemeSettings'; const ApplicationVersion = () => { const data = useCurrentAppInfo(); @@ -43,6 +44,7 @@ export const CurrentUser = () => { + { setOpen(true); }} > - {t('Language')}{' '} - { + setOpen(open); + }} + options={Object.keys(locale) + .filter((lang) => enabledLanguages.includes(lang)) + .map((lang) => { + return { + label: locale[lang].label, + value: lang, + }; + })} + value={i18n.language} + onChange={async (lang) => { + await api.resource('users').updateProfile({ + values: { + appLang: lang, + }, + }); + api.auth.setLocale(lang); + await i18n.changeLanguage(lang); + window.location.reload(); + }} + /> +
); }; diff --git a/packages/core/client/src/user/SwitchRole.tsx b/packages/core/client/src/user/SwitchRole.tsx index 48d1165ac3..a5d0c828ed 100644 --- a/packages/core/client/src/user/SwitchRole.tsx +++ b/packages/core/client/src/user/SwitchRole.tsx @@ -1,3 +1,4 @@ +import { css } from '@emotion/css'; import { Menu, Select } from 'antd'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -36,23 +37,31 @@ export const SwitchRole = () => { } return ( - {t('Switch role')}{' '} - { + api.auth.setRole(roleName); + await api.resource('users').setDefaultRole({ values: { roleName } }); + history.push('/'); + window.location.reload(); + }} + /> +
); }; diff --git a/packages/core/client/src/user/ThemeSettings.tsx b/packages/core/client/src/user/ThemeSettings.tsx new file mode 100644 index 0000000000..0bf6322e44 --- /dev/null +++ b/packages/core/client/src/user/ThemeSettings.tsx @@ -0,0 +1,47 @@ +import { css } from '@emotion/css'; +import { Menu, Select } from 'antd'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useAPIClient } from '../api-client'; +import { useCurrentUserContext } from './CurrentUserProvider'; + +export const ThemeSettings = () => { + const { t } = useTranslation(); + const ctx = useCurrentUserContext(); + const api = useAPIClient(); + return ( + +
+ {t('Theme')}{' '} +