Skip to content

Commit 630ac20

Browse files
author
dashuai
authored
Management Backend Menu and Function Adjustments (#1474)
…ent, regardless of functional split or reorganization
1 parent f3dddfe commit 630ac20

49 files changed

Lines changed: 1325 additions & 791 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

i18n/en_US.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,13 @@ ui:
18161816
plugins: Plugins
18171817
installed_plugins: Installed Plugins
18181818
apperance: Appearance
1819+
community: Community
1820+
advanced: Advanced
1821+
tags: Tags
1822+
rules: Rules
1823+
policies: Policies
1824+
security: Security
1825+
files: Files
18191826
website_welcome: Welcome to {{site_name}}
18201827
user_center:
18211828
login: Login
@@ -2128,7 +2135,7 @@ ui:
21282135
always_display: Always display external content
21292136
ask_before_display: Ask before displaying external content
21302137
write:
2131-
page_title: Write
2138+
page_title: Files
21322139
min_content:
21332140
label: Minimum question body length
21342141
text: Minimum allowed question body length in characters.

i18n/zh_CN.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,13 @@ ui:
17781778
plugins: 插件
17791779
installed_plugins: 已安装插件
17801780
apperance: 外观
1781+
community: 社区
1782+
advanced: 高级
1783+
tags: 标签
1784+
rules: 规则
1785+
policies: 政策
1786+
security: 安全
1787+
files: 文件
17811788
website_welcome: 欢迎来到 {{site_name}}
17821789
user_center:
17831790
login: 登录
@@ -2089,7 +2096,7 @@ ui:
20892096
always_display: 总是显示外部内容
20902097
ask_before_display: 在显示外部内容之前询问
20912098
write:
2092-
page_title: 编辑
2099+
page_title: 文件
20932100
min_content:
20942101
label: 最小问题长度
20952102
text: 最小允许的问题内容长度(字符)。

ui/src/common/constants.ts

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ export const ADMIN_LIST_STATUS = {
8383
},
8484
};
8585

86+
/**
87+
* ADMIN_NAV_MENUS is the navigation menu for the admin panel.
88+
* pathPrefix is used to activate the menu item when the activeKey starts with the pathPrefix.
89+
*/
90+
8691
export const ADMIN_NAV_MENUS = [
8792
{
8893
name: 'dashboard',
@@ -92,15 +97,19 @@ export const ADMIN_NAV_MENUS = [
9297
{
9398
name: 'contents',
9499
icon: 'file-earmark-text-fill',
95-
children: [{ name: 'questions' }, { name: 'answers' }],
100+
children: [
101+
{ name: 'questions', path: 'qa/questions', pathPrefix: 'qa/' },
102+
{ name: 'tags', path: 'tags/settings', pathPrefix: 'tags/' },
103+
],
96104
},
97105
{
98-
name: 'users',
106+
name: 'community',
99107
icon: 'people-fill',
100-
},
101-
{
102-
name: 'badges',
103-
icon: 'award-fill',
108+
children: [
109+
{ name: 'users', pathPrefix: 'users/' },
110+
{ name: 'badges' },
111+
{ name: 'rules', path: 'rules/privileges', pathPrefix: 'rules/' },
112+
],
104113
},
105114
{
106115
name: 'apperance',
@@ -113,20 +122,19 @@ export const ADMIN_NAV_MENUS = [
113122
name: 'customize',
114123
},
115124
{ name: 'branding' },
125+
{ name: 'interface' },
116126
],
117127
},
118128
{
119-
name: 'settings',
129+
name: 'advanced',
120130
icon: 'gear-fill',
121131
children: [
122132
{ name: 'general' },
123-
{ name: 'interface' },
124-
{ name: 'smtp' },
125-
{ name: 'legal' },
126-
{ name: 'write' },
127-
{ name: 'seo' },
133+
{ name: 'security' },
134+
{ name: 'files' },
128135
{ name: 'login' },
129-
{ name: 'privileges' },
136+
{ name: 'seo' },
137+
{ name: 'smtp' },
130138
],
131139
},
132140
{
@@ -141,6 +149,30 @@ export const ADMIN_NAV_MENUS = [
141149
},
142150
];
143151

152+
export const ADMIN_QA_NAV_MENUS = [
153+
{ name: 'questions', path: '/admin/qa/questions' },
154+
{ name: 'answers', path: '/admin/qa/answers' },
155+
{ name: 'settings', path: '/admin/qa/settings' },
156+
];
157+
158+
export const ADMIN_TAGS_NAV_MENUS = [
159+
// { name: 'tags', path: '/admin/tags' },
160+
{
161+
name: 'settings',
162+
path: '/admin/tags/settings',
163+
},
164+
];
165+
166+
export const ADMIN_USERS_NAV_MENUS = [
167+
{ name: 'users', path: '/admin/users' },
168+
{ name: 'settings', path: '/admin/users/settings' },
169+
];
170+
171+
export const ADMIN_RULES_NAV_MENUS = [
172+
{ name: 'privileges', path: '/admin/rules/privileges' },
173+
{ name: 'policies', path: '/admin/rules/policies' },
174+
];
175+
144176
export const TIMEZONES = [
145177
{
146178
label: 'Africa',

ui/src/common/interface.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,6 @@ export interface AdminSettingsGeneral {
364364
description: string;
365365
site_url: string;
366366
contact_email: string;
367-
check_update: boolean;
368367
permalink?: number;
369368
}
370369

@@ -382,8 +381,6 @@ export interface HelmetUpdate extends Omit<HelmetBase, 'pageTitle'> {
382381
export interface AdminSettingsInterface {
383382
language: string;
384383
time_zone?: string;
385-
default_avatar: string;
386-
gravatar_base_url: string;
387384
}
388385

389386
export interface AdminSettingsSmtp {
@@ -405,6 +402,14 @@ export interface AdminSettingsUsers {
405402
allow_update_location: boolean;
406403
allow_update_username: boolean;
407404
allow_update_website: boolean;
405+
default_avatar: string;
406+
gravatar_base_url: string;
407+
}
408+
409+
export interface AdminSettingsSecurity {
410+
external_content_display: string;
411+
check_update: boolean;
412+
login_required: boolean;
408413
}
409414

410415
export interface SiteSettings {
@@ -416,10 +421,12 @@ export interface SiteSettings {
416421
theme: AdminSettingsTheme;
417422
site_seo: AdminSettingsSeo;
418423
site_users: AdminSettingsUsers;
419-
site_write: AdminSettingsWrite;
424+
site_advanced: AdminSettingsWrite;
425+
site_questions: AdminQuestionSetting;
426+
site_tags: AdminTagsSetting;
420427
version: string;
421428
revision: string;
422-
site_legal: AdminSettingsLegal;
429+
site_security: AdminSettingsSecurity;
423430
}
424431

425432
export interface AdminSettingBranding {
@@ -430,20 +437,13 @@ export interface AdminSettingBranding {
430437
}
431438

432439
export interface AdminSettingsLegal {
433-
external_content_display: string;
434440
privacy_policy_original_text?: string;
435441
privacy_policy_parsed_text?: string;
436442
terms_of_service_original_text?: string;
437443
terms_of_service_parsed_text?: string;
438444
}
439445

440446
export interface AdminSettingsWrite {
441-
restrict_answer?: boolean;
442-
min_tags?: number;
443-
min_content?: number;
444-
recommend_tags?: Tag[];
445-
required_tag?: boolean;
446-
reserved_tags?: Tag[];
447447
max_image_size?: number;
448448
max_attachment_size?: number;
449449
max_image_megapixel?: number;
@@ -484,7 +484,6 @@ export interface AdminSettingsCustom {
484484

485485
export interface AdminSettingsLogin {
486486
allow_new_registrations: boolean;
487-
login_required: boolean;
488487
allow_email_registrations: boolean;
489488
allow_email_domains: string[];
490489
allow_password_login: boolean;
@@ -809,3 +808,15 @@ export interface BadgeDetailListRes {
809808
count: number;
810809
list: BadgeDetailListItem[];
811810
}
811+
812+
export interface AdminQuestionSetting {
813+
min_tags: number;
814+
min_content: number;
815+
restrict_answer: boolean;
816+
}
817+
818+
export interface AdminTagsSetting {
819+
recommend_tags: Tag[];
820+
required_tag: boolean;
821+
reserved_tags: Tag[];
822+
}

ui/src/components/AccordionNav/index.tsx

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,32 @@ import { floppyNavigation } from '@/utils';
2828
import { Icon } from '@/components';
2929
import './index.css';
3030

31+
export interface MenuItem {
32+
name: string;
33+
path?: string;
34+
pathPrefix?: string;
35+
icon?: string;
36+
displayName?: string;
37+
badgeContent?: string | number;
38+
children?: MenuItem[];
39+
}
40+
3141
function MenuNode({
3242
menu,
3343
callback,
3444
activeKey,
3545
expanding = false,
3646
path = '/',
47+
}: {
48+
menu: MenuItem;
49+
callback: (evt: any, menu: MenuItem, href: string, isLeaf: boolean) => void;
50+
activeKey: string;
51+
expanding?: boolean;
52+
path?: string;
3753
}) {
3854
const { t } = useTranslation('translation', { keyPrefix: 'nav_menus' });
39-
const isLeaf = !menu.children.length;
40-
const href = isLeaf ? `${path}${menu.path}` : '#';
55+
const isLeaf = !menu.children || menu.children.length === 0;
56+
const href = isLeaf ? `${path}${menu.path || ''}` : '#';
4157

4258
return (
4359
<Nav.Item key={menu.path} className="w-100">
@@ -51,7 +67,14 @@ function MenuNode({
5167
}}
5268
className={classNames(
5369
'text-nowrap d-flex flex-nowrap align-items-center w-100',
54-
{ expanding, active: activeKey === menu.path },
70+
{
71+
expanding,
72+
active:
73+
activeKey === menu.path ||
74+
(menu.path && activeKey.startsWith(`${menu.path}/`)) ||
75+
// if pathPrefix is set, activate when activeKey starts with the pathPrefix
76+
(menu.pathPrefix && activeKey.startsWith(menu.pathPrefix)),
77+
},
5578
)}>
5679
{menu?.icon && <Icon name={menu.icon} className="me-2" />}
5780

@@ -75,7 +98,13 @@ function MenuNode({
7598
}}
7699
className={classNames(
77100
'text-nowrap d-flex flex-nowrap align-items-center w-100',
78-
{ expanding, active: activeKey === menu.path },
101+
{
102+
expanding,
103+
active:
104+
activeKey === menu.path ||
105+
(menu.path && activeKey.startsWith(`${menu.path}/`)) ||
106+
(menu.pathPrefix && activeKey.startsWith(menu.pathPrefix)),
107+
},
79108
)}>
80109
{menu?.icon && <Icon name={menu.icon} className="me-2" />}
81110
<span className="me-auto text-truncate">
@@ -90,8 +119,8 @@ function MenuNode({
90119
</Nav.Link>
91120
)}
92121

93-
{menu.children.length ? (
94-
<Accordion.Collapse eventKey={menu.path} className="ms-4">
122+
{menu.children && menu.children.length > 0 ? (
123+
<Accordion.Collapse eventKey={menu.path || menu.name} className="ms-4">
95124
<>
96125
{menu.children.map((leaf) => {
97126
return (
@@ -100,7 +129,7 @@ function MenuNode({
100129
callback={callback}
101130
activeKey={activeKey}
102131
path={path}
103-
key={leaf.path}
132+
key={leaf.path || leaf.name}
104133
/>
105134
);
106135
})}
@@ -112,7 +141,7 @@ function MenuNode({
112141
}
113142

114143
interface AccordionProps {
115-
menus: any[];
144+
menus: MenuItem[];
116145
path?: string;
117146
}
118147
const AccordionNav: FC<AccordionProps> = ({ menus = [], path = '/' }) => {
@@ -137,19 +166,27 @@ const AccordionNav: FC<AccordionProps> = ({ menus = [], path = '/' }) => {
137166
});
138167

139168
const splat = pathMatch && pathMatch.params['*'];
140-
let activeKey = menus[0].path;
169+
let activeKey: string = menus[0]?.path || menus[0]?.name || '';
170+
141171
if (splat) {
142172
activeKey = splat;
143173
}
174+
144175
const getOpenKey = () => {
145176
let openKey = '';
146177
menus.forEach((li) => {
147-
if (li.children.length) {
178+
if (li.children && li.children.length > 0) {
148179
const matchedChild = li.children.find((el) => {
149-
return el.path === activeKey;
180+
// exact match or path prefix match
181+
return (
182+
el.path === activeKey ||
183+
(el.path && activeKey.startsWith(`${el.path}/`)) ||
184+
// if pathPrefix is set, activate when activeKey starts with the pathPrefix
185+
(el.pathPrefix && activeKey.startsWith(el.pathPrefix))
186+
);
150187
});
151188
if (matchedChild) {
152-
openKey = li.path;
189+
openKey = li.path || li.name || '';
153190
}
154191
}
155192
});
@@ -181,8 +218,8 @@ const AccordionNav: FC<AccordionProps> = ({ menus = [], path = '/' }) => {
181218
path={path}
182219
callback={menuClick}
183220
activeKey={activeKey}
184-
expanding={openKey === li.path}
185-
key={li.path}
221+
expanding={openKey === (li.path || li.name)}
222+
key={li.path || li.name}
186223
/>
187224
);
188225
})}

0 commit comments

Comments
 (0)