mirror of https://gitee.com/answerdev/answer.git
feat(ui): add installed plugins page
This commit is contained in:
parent
0529c10c54
commit
b8cfde0425
|
@ -1043,6 +1043,8 @@ ui:
|
||||||
themes: Themes
|
themes: Themes
|
||||||
css-html: CSS/HTML
|
css-html: CSS/HTML
|
||||||
login: Login
|
login: Login
|
||||||
|
plugins: Plugins
|
||||||
|
installed_plugins: Installed Plugins
|
||||||
admin:
|
admin:
|
||||||
admin_header:
|
admin_header:
|
||||||
title: Admin
|
title: Admin
|
||||||
|
@ -1362,6 +1364,23 @@ ui:
|
||||||
title: Private
|
title: Private
|
||||||
label: Login required
|
label: Login required
|
||||||
text: Only logged in users can access this community.
|
text: Only logged in users can access this community.
|
||||||
|
installed_plugins:
|
||||||
|
title: Installed Plugins
|
||||||
|
filter:
|
||||||
|
all: All
|
||||||
|
active: Active
|
||||||
|
inactive: Inactive
|
||||||
|
outdated: Outdated
|
||||||
|
plugins:
|
||||||
|
label: Plugins
|
||||||
|
text: Select an existing plugin.
|
||||||
|
name: Name
|
||||||
|
version: Version
|
||||||
|
status: Status
|
||||||
|
action: Action
|
||||||
|
deactivate: Deactivate
|
||||||
|
settings: Settings
|
||||||
|
|
||||||
|
|
||||||
form:
|
form:
|
||||||
empty: cannot be empty
|
empty: cannot be empty
|
||||||
|
|
|
@ -77,6 +77,14 @@ export const ADMIN_NAV_MENUS = [
|
||||||
{ name: 'login' },
|
{ name: 'login' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'plugins',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'installed_plugins',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ADMIN_LEGAL_MENUS = [{ name: 'tos' }, { name: 'privacy' }];
|
export const ADMIN_LEGAL_MENUS = [{ name: 'tos' }, { name: 'privacy' }];
|
||||||
|
|
|
@ -261,6 +261,11 @@ export type UserFilterBy =
|
||||||
| 'suspended'
|
| 'suspended'
|
||||||
| 'deleted';
|
| 'deleted';
|
||||||
|
|
||||||
|
export type InstalledPluginsFilterBy =
|
||||||
|
| 'all'
|
||||||
|
| 'active'
|
||||||
|
| 'inactive'
|
||||||
|
| 'outdated';
|
||||||
/**
|
/**
|
||||||
* @description interface for Flags
|
* @description interface for Flags
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { FC } from 'react';
|
||||||
|
import { Table, Dropdown, Stack } from 'react-bootstrap';
|
||||||
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { Pagination, Empty, QueryGroup, Icon } from '@/components';
|
||||||
|
import * as Type from '@/common/interface';
|
||||||
|
import { useQueryUsers } from '@/services';
|
||||||
|
|
||||||
|
const InstalledPluginsFilterKeys: Type.InstalledPluginsFilterBy[] = [
|
||||||
|
'all',
|
||||||
|
'active',
|
||||||
|
'inactive',
|
||||||
|
'outdated',
|
||||||
|
];
|
||||||
|
|
||||||
|
const bgMap = {
|
||||||
|
normal: 'text-bg-success',
|
||||||
|
suspended: 'text-bg-danger',
|
||||||
|
deleted: 'text-bg-danger',
|
||||||
|
inactive: 'text-bg-secondary',
|
||||||
|
};
|
||||||
|
|
||||||
|
const PAGE_SIZE = 10;
|
||||||
|
const Users: FC = () => {
|
||||||
|
const { t } = useTranslation('translation', {
|
||||||
|
keyPrefix: 'admin.installed_plugins',
|
||||||
|
});
|
||||||
|
|
||||||
|
const [urlSearchParams] = useSearchParams();
|
||||||
|
const curFilter =
|
||||||
|
urlSearchParams.get('filter') || InstalledPluginsFilterKeys[0];
|
||||||
|
const curPage = Number(urlSearchParams.get('page') || '1');
|
||||||
|
const curQuery = urlSearchParams.get('query') || '';
|
||||||
|
const { data, isLoading } = useQueryUsers({
|
||||||
|
page: curPage,
|
||||||
|
page_size: PAGE_SIZE,
|
||||||
|
query: curQuery,
|
||||||
|
...(curFilter === 'all'
|
||||||
|
? {}
|
||||||
|
: curFilter === 'staff'
|
||||||
|
? { staff: true }
|
||||||
|
: { status: curFilter }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleAction = (type, plugin) => {
|
||||||
|
console.log(type, plugin);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3 className="mb-4">{t('title')}</h3>
|
||||||
|
<div className="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<Stack direction="horizontal" gap={3}>
|
||||||
|
<QueryGroup
|
||||||
|
data={InstalledPluginsFilterKeys}
|
||||||
|
currentSort={curFilter}
|
||||||
|
sortKey="filter"
|
||||||
|
i18nKeyPrefix="admin.installed_plugins.filter"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
<Table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style={{ width: '12%' }}>{t('name')}</th>
|
||||||
|
<th style={{ width: '20%' }}>{t('version')}</th>
|
||||||
|
<th style={{ width: '12%' }}>{t('status')}</th>
|
||||||
|
{curFilter !== 'deleted' ? (
|
||||||
|
<th style={{ width: '8%' }} className="text-end">
|
||||||
|
{t('action')}
|
||||||
|
</th>
|
||||||
|
) : null}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="align-middle">
|
||||||
|
{data?.list.map((plugin) => {
|
||||||
|
return (
|
||||||
|
<tr key={plugin.user_id}>
|
||||||
|
<td>
|
||||||
|
<div>Twitter Logins</div>
|
||||||
|
<div className="text-muted text-small">
|
||||||
|
Enable login with Twitter
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-break">{plugin.version}</td>
|
||||||
|
<td>
|
||||||
|
<span className={classNames('badge', bgMap[plugin.status])}>
|
||||||
|
{t(`filter.${plugin.status}`)}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
{curFilter !== 'deleted' ? (
|
||||||
|
<td className="text-end">
|
||||||
|
<Dropdown>
|
||||||
|
<Dropdown.Toggle variant="link" className="no-toggle">
|
||||||
|
<Icon name="three-dots-vertical" />
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
<Dropdown.Menu>
|
||||||
|
<Dropdown.Item
|
||||||
|
onClick={() => handleAction('deactivate', plugin)}>
|
||||||
|
{t('deactivate')}
|
||||||
|
</Dropdown.Item>
|
||||||
|
<Dropdown.Item
|
||||||
|
onClick={() => handleAction('settings', plugin)}>
|
||||||
|
{t('settings')}
|
||||||
|
</Dropdown.Item>
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
</td>
|
||||||
|
) : null}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
{Number(data?.count) <= 0 && !isLoading && <Empty />}
|
||||||
|
<div className="mt-4 mb-2 d-flex justify-content-center">
|
||||||
|
<Pagination
|
||||||
|
currentPage={curPage}
|
||||||
|
totalSize={data?.count || 0}
|
||||||
|
pageSize={PAGE_SIZE}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Users;
|
|
@ -311,6 +311,10 @@ const routes: RouteNode[] = [
|
||||||
path: 'login',
|
path: 'login',
|
||||||
page: 'pages/Admin/Login',
|
page: 'pages/Admin/Login',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'installed_plugins',
|
||||||
|
page: 'pages/Admin/Plugins/Installed',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// for review
|
// for review
|
||||||
|
|
Loading…
Reference in New Issue