This is an automated email from the ASF dual-hosted git repository. shuai pushed a commit to branch test in repository https://gitbox.apache.org/repos/asf/answer.git
commit b5ae2d0351118a6274616987ce1d3c5283cf6d93 Author: shuai <[email protected]> AuthorDate: Fri Dec 19 14:09:38 2025 +0800 fix: admin/themes add layout config --- cmd/wire_gen.go | 24 ++----------------- docs/docs.go | 19 --------------- docs/swagger.yaml | 17 -------------- i18n/en_US.yaml | 4 ++++ internal/service/mock/siteinfo_repo_mock.go | 19 --------------- ui/src/common/interface.ts | 1 + ui/src/components/Customize/index.tsx | 36 +++++++++++++++++++++++++++++ ui/src/components/Header/index.tsx | 8 +++++-- ui/src/pages/{ => 404}/403/index.tsx | 0 ui/src/pages/Admin/Themes/index.tsx | 11 +++++++++ ui/src/pages/Layout/index.tsx | 11 +++++++-- ui/src/pages/SideNavLayout/index.tsx | 2 +- ui/src/stores/themeSetting.ts | 2 ++ 13 files changed, 72 insertions(+), 82 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index aae1c6af..dbfd640d 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -1,28 +1,8 @@ -//go:build !wireinject -// +build !wireinject - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire +//go:build !wireinject +// +build !wireinject package answercmd diff --git a/docs/docs.go b/docs/docs.go index 5e9d5b39..fc4d9909 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,22 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - // Package docs Code generated by swaggo/swag. DO NOT EDIT package docs diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e0244083..42df5cbf 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,20 +1,3 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - basePath: / definitions: constant.NotificationChannelKey: diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml index eac322da..4ab6b34b 100644 --- a/i18n/en_US.yaml +++ b/i18n/en_US.yaml @@ -2186,6 +2186,10 @@ ui: primary_color: label: Primary color text: Modify the colors used by your themes + layout: + label: Layout + full_width: Full-width + fixed_width: Fixed-width css_and_html: page_title: CSS and HTML custom_css: diff --git a/internal/service/mock/siteinfo_repo_mock.go b/internal/service/mock/siteinfo_repo_mock.go index a98ceb68..0a1b31e8 100644 --- a/internal/service/mock/siteinfo_repo_mock.go +++ b/internal/service/mock/siteinfo_repo_mock.go @@ -1,22 +1,3 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - // Code generated by MockGen. DO NOT EDIT. // Source: ./siteinfo_service.go // diff --git a/ui/src/common/interface.ts b/ui/src/common/interface.ts index f2901908..3a77047e 100644 --- a/ui/src/common/interface.ts +++ b/ui/src/common/interface.ts @@ -469,6 +469,7 @@ export type themeConfig = { export interface AdminSettingsTheme { theme: string; color_scheme: string; + layout: string; theme_options?: { label: string; value: string }[]; theme_config: Record<string, themeConfig>; } diff --git a/ui/src/components/Customize/index.tsx b/ui/src/components/Customize/index.tsx index c02db675..52cc651b 100644 --- a/ui/src/components/Customize/index.tsx +++ b/ui/src/components/Customize/index.tsx @@ -18,6 +18,7 @@ */ import { FC, memo, useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; import { customizeStore } from '@/stores'; @@ -117,6 +118,8 @@ const Index: FC = () => { const { custom_head, custom_header, custom_footer } = customizeStore( (state) => state, ); + const { pathname } = useLocation(); + useEffect(() => { const isSeo = document.querySelector('meta[name="go-template"]'); if (!isSeo) { @@ -125,8 +128,41 @@ const Index: FC = () => { }, 1000); handleCustomHeader(custom_header); handleCustomFooter(custom_footer); + } else { + isSeo.remove(); } }, [custom_head, custom_header, custom_footer]); + + useEffect(() => { + /** + * description: Activate scripts with data-client attribute when route changes + */ + const allScript = document.body.querySelectorAll('script[data-client]'); + console.log('allScript', allScript); + allScript.forEach((scriptNode) => { + const script = document.createElement('script'); + script.setAttribute('data-client', 'true'); + // If the script is already wrapped in an IIFE, use it directly; otherwise, wrap it in an IIFE + if ( + /^\s*\(\s*function\s*\(\s*\)\s*{/.test( + (scriptNode as HTMLScriptElement).text, + ) || + /^\s*\(\s*\(\s*\)\s*=>\s*{/.test((scriptNode as HTMLScriptElement).text) + ) { + script.text = (scriptNode as HTMLScriptElement).text; + } else { + script.text = `(() => {${(scriptNode as HTMLScriptElement).text}})();`; + } + for (let i = 0; i < scriptNode.attributes.length; i += 1) { + const attr = scriptNode.attributes[i]; + if (attr.name !== 'data-client') { + script.setAttribute(attr.name, attr.value); + } + } + scriptNode.parentElement?.replaceChild(script, scriptNode); + }); + }, [pathname]); + return null; }; diff --git a/ui/src/components/Header/index.tsx b/ui/src/components/Header/index.tsx index 2d151b88..4e9c8189 100644 --- a/ui/src/components/Header/index.tsx +++ b/ui/src/components/Header/index.tsx @@ -83,7 +83,7 @@ const Header: FC = () => { let navbarStyle = 'theme-light'; let themeMode = 'light'; - const { theme, theme_config } = themeSettingStore((_) => _); + const { theme, theme_config, layout } = themeSettingStore((_) => _); if (theme_config?.[theme]?.navbar_style) { // const color = theme_config[theme].navbar_style.startsWith('#') themeMode = isLight(theme_config[theme].navbar_style) ? 'light' : 'dark'; @@ -113,7 +113,11 @@ const Header: FC = () => { backgroundColor: theme_config[theme].navbar_style, }} id="header"> - <div className="w-100 d-flex align-items-center px-3"> + <div + className={classnames( + 'w-100 d-flex align-items-center px-3', + layout === 'Fixed-width' ? 'container-xxl' : '', + )}> <Navbar.Toggle className="answer-navBar me-2" onClick={() => { diff --git a/ui/src/pages/403/index.tsx b/ui/src/pages/404/403/index.tsx similarity index 100% rename from ui/src/pages/403/index.tsx rename to ui/src/pages/404/403/index.tsx diff --git a/ui/src/pages/Admin/Themes/index.tsx b/ui/src/pages/Admin/Themes/index.tsx index 94eccbca..db2a13da 100644 --- a/ui/src/pages/Admin/Themes/index.tsx +++ b/ui/src/pages/Admin/Themes/index.tsx @@ -46,6 +46,13 @@ const Index: FC = () => { enumNames: themeSetting?.theme_options?.map((_) => _.label), default: themeSetting?.theme_options?.[0]?.value, }, + layout: { + type: 'string', + title: t('layout.label'), + enum: ['Full-width', 'Fixed-width'], + enumNames: [t('layout.full_width'), t('layout.fixed_width')], + default: themeSetting?.layout, + }, color_scheme: { type: 'string', title: t('color_scheme.label'), @@ -77,6 +84,9 @@ const Index: FC = () => { color_scheme: { 'ui:widget': 'select', }, + layout: { + 'ui:widget': 'select', + }, navbar_style: { 'ui:widget': 'input_group', 'ui:options': { @@ -131,6 +141,7 @@ const Index: FC = () => { const reqParams: Type.AdminSettingsTheme = { theme: themeName, color_scheme: formData.color_scheme.value, + layout: formData.layout.value, theme_config: { [themeName]: { navbar_style: formData.navbar_style.value, diff --git a/ui/src/pages/Layout/index.tsx b/ui/src/pages/Layout/index.tsx index 984e13f4..bd229165 100644 --- a/ui/src/pages/Layout/index.tsx +++ b/ui/src/pages/Layout/index.tsx @@ -22,12 +22,14 @@ import { Outlet, useLocation, ScrollRestoration } from 'react-router-dom'; import { HelmetProvider } from 'react-helmet-async'; import { SWRConfig } from 'swr'; +import classnames from 'classnames'; import { toastStore, loginToContinueStore, errorCodeStore, siteLealStore, + themeSettingStore, } from '@/stores'; import { Header, @@ -56,7 +58,8 @@ const Layout: FC = () => { const { code: httpStatusCode, reset: httpStatusReset } = errorCodeStore(); const { show: showLoginToContinueModal } = loginToContinueStore(); const { data: notificationData } = useQueryNotificationStatus(); - + const layout = themeSettingStore((state) => state.layout); + console.log(layout); useEffect(() => { // handle footnote links const fixFootnoteLinks = () => { @@ -209,7 +212,11 @@ const Layout: FC = () => { revalidateOnFocus: false, }}> <Header /> - <div className="position-relative page-wrap d-flex flex-column flex-fill"> + <div + className={classnames( + 'position-relative page-wrap d-flex flex-column flex-fill', + layout === 'Fixed-width' ? 'container-xxl' : '', + )}> {httpStatusCode ? ( <HttpErrorContent httpCode={httpStatusCode} /> ) : ( diff --git a/ui/src/pages/SideNavLayout/index.tsx b/ui/src/pages/SideNavLayout/index.tsx index 907b9b28..b9bc38b9 100644 --- a/ui/src/pages/SideNavLayout/index.tsx +++ b/ui/src/pages/SideNavLayout/index.tsx @@ -38,7 +38,7 @@ const Index: FC = () => { <Outlet /> </div> </div> - <div className="d-flex justify-content-center"> + <div className="d-flex justify-content-center px-0 px-md-4"> <div className="main-mx-with"> <Footer /> </div> diff --git a/ui/src/stores/themeSetting.ts b/ui/src/stores/themeSetting.ts index 4b13d818..2f1b1edb 100644 --- a/ui/src/stores/themeSetting.ts +++ b/ui/src/stores/themeSetting.ts @@ -27,6 +27,7 @@ interface IType { theme_config: AdminSettingsTheme['theme_config']; theme_options: AdminSettingsTheme['theme_options']; color_scheme: AdminSettingsTheme['color_scheme']; + layout: AdminSettingsTheme['layout']; update: (params: AdminSettingsTheme) => void; } @@ -40,6 +41,7 @@ const store = create<IType>((set) => ({ primary_color: DEFAULT_THEME_COLOR, }, }, + layout: 'full', update: (params) => set((state) => { // Compatibility default value is colored or light before v1.5.1
