mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-02 03:02:19 +08:00
fix(plugin-workflow): optimize mobile style (#7040)
* fix(plugin-workflow): optimize mobile style * fix(plugin-workflow): fix mobile style * feat(plugin-workflow): add tasks to mobile menu initializer * refactor(plugin-workflow): adjust tasks center api * fix(ActionDrawer): apply zIndex style to ActionDrawer component * fix(plugin-workflow-manual): fix manual style under mobile * fix(plugin-workflow): fix styles * fix(plugin-workflow): fix mobile layout check * fix(plugin-workflow): adjust pagination footer style * fix(plugin-workflow): fix icon only props * fix(plugin-workflow-manual): fix todo item title * revert(plugin-field-sort): revert mistaken commit --------- Co-authored-by: Zeke Zhang <958414905@qq.com>
This commit is contained in:
parent
e527e4d6ba
commit
a9bd6f7844
@ -48,11 +48,11 @@ const useStyles = genStyleHook('nb-list', (token) => {
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
'&:not(:first-child)': {
|
'&:not(:first-child)': {
|
||||||
paddingTop: token.paddingContentVertical,
|
marginTop: token.paddingContentVertical,
|
||||||
},
|
},
|
||||||
|
|
||||||
'&:not(:last-child)': {
|
'&:not(:last-child)': {
|
||||||
paddingBottom: token.paddingContentVertical,
|
marginBottom: token.paddingContentVertical,
|
||||||
borderBottom: `1px solid ${token.colorBorderSecondary}`,
|
borderBottom: `1px solid ${token.colorBorderSecondary}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -244,7 +244,7 @@ function FinallyButton({
|
|||||||
inheritsCollections,
|
inheritsCollections,
|
||||||
linkageFromForm,
|
linkageFromForm,
|
||||||
allowAddToCurrent,
|
allowAddToCurrent,
|
||||||
props,
|
props: { onlyIcon, ...props },
|
||||||
componentType,
|
componentType,
|
||||||
menu,
|
menu,
|
||||||
onClick,
|
onClick,
|
||||||
@ -362,7 +362,7 @@ function FinallyButton({
|
|||||||
...buttonStyle,
|
...buttonStyle,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.onlyIcon ? props?.children?.[1] : props?.children}
|
{onlyIcon ? props?.children?.[1] : props?.children}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,11 @@ const useLocalVariables = (props?: Props) => {
|
|||||||
dataSource: parentPopupDataSource,
|
dataSource: parentPopupDataSource,
|
||||||
defaultValue: defaultValueOfParentPopupRecord,
|
defaultValue: defaultValueOfParentPopupRecord,
|
||||||
} = useParentPopupVariableContext();
|
} = useParentPopupVariableContext();
|
||||||
const { urlSearchParamsCtx, shouldDisplay: shouldDisplayURLSearchParams, defaultValue: defaultValueOfURLSearchParams } = useURLSearchParamsVariable();
|
const {
|
||||||
|
urlSearchParamsCtx,
|
||||||
|
shouldDisplay: shouldDisplayURLSearchParams,
|
||||||
|
defaultValue: defaultValueOfURLSearchParams,
|
||||||
|
} = useURLSearchParamsVariable();
|
||||||
const { datetimeCtx } = useDatetimeVariableContext();
|
const { datetimeCtx } = useDatetimeVariableContext();
|
||||||
const { currentFormCtx } = useCurrentFormContext({ form: props?.currentForm });
|
const { currentFormCtx } = useCurrentFormContext({ form: props?.currentForm });
|
||||||
const { name: currentCollectionName } = useCollection_deprecated();
|
const { name: currentCollectionName } = useCollection_deprecated();
|
||||||
|
@ -84,8 +84,8 @@ export const actionDesignerCss = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const DuplicateAction = observer(
|
export const DuplicateAction = observer(
|
||||||
(props: any) => {
|
({ onlyIcon, ...props }: any) => {
|
||||||
const { children, onlyIcon, icon, title, ...others } = props;
|
const { children, icon, title, ...others } = props;
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
|
@ -10,9 +10,14 @@
|
|||||||
import { useToken } from '@nocobase/client';
|
import { useToken } from '@nocobase/client';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { FC, useEffect } from 'react';
|
import React, { FC, useEffect } from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
import { PageBackgroundColor } from '../../../constants';
|
import { PageBackgroundColor } from '../../../constants';
|
||||||
|
|
||||||
export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ children, hideTabBar }) => {
|
export const MobilePageContentContainer: FC<{ hideTabBar?: boolean; className?: string }> = ({
|
||||||
|
children,
|
||||||
|
hideTabBar,
|
||||||
|
className,
|
||||||
|
}) => {
|
||||||
const [mobileTabBarHeight, setMobileTabBarHeight] = React.useState(0);
|
const [mobileTabBarHeight, setMobileTabBarHeight] = React.useState(0);
|
||||||
const [mobilePageHeader, setMobilePageHeader] = React.useState(0);
|
const [mobilePageHeader, setMobilePageHeader] = React.useState(0);
|
||||||
const { token } = useToken();
|
const { token } = useToken();
|
||||||
@ -31,7 +36,7 @@ export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ child
|
|||||||
<>
|
<>
|
||||||
{mobilePageHeader ? <div style={{ height: mobilePageHeader }}></div> : null}
|
{mobilePageHeader ? <div style={{ height: mobilePageHeader }}></div> : null}
|
||||||
<div
|
<div
|
||||||
className="mobile-page-content"
|
className={classnames('mobile-page-content', className)}
|
||||||
data-testid="mobile-page-content"
|
data-testid="mobile-page-content"
|
||||||
style={{
|
style={{
|
||||||
height: `calc(100% - ${(mobileTabBarHeight || 0) + (mobilePageHeader || 0)}px)`,
|
height: `calc(100% - ${(mobileTabBarHeight || 0) + (mobilePageHeader || 0)}px)`,
|
||||||
|
@ -40,6 +40,7 @@ import {
|
|||||||
ActionContextProvider,
|
ActionContextProvider,
|
||||||
useRequest,
|
useRequest,
|
||||||
CollectionRecordProvider,
|
CollectionRecordProvider,
|
||||||
|
useMobileLayout,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import WorkflowPlugin, {
|
import WorkflowPlugin, {
|
||||||
DetailsBlockProvider,
|
DetailsBlockProvider,
|
||||||
@ -56,6 +57,7 @@ import { NAMESPACE, useLang } from '../locale';
|
|||||||
import { FormBlockProvider } from './instruction/FormBlockProvider';
|
import { FormBlockProvider } from './instruction/FormBlockProvider';
|
||||||
import { ManualFormType, manualFormTypes } from './instruction/SchemaConfig';
|
import { ManualFormType, manualFormTypes } from './instruction/SchemaConfig';
|
||||||
import { TaskStatusOptionsMap, TASK_STATUS } from '../common/constants';
|
import { TaskStatusOptionsMap, TASK_STATUS } from '../common/constants';
|
||||||
|
import { useMobilePage } from '@nocobase/plugin-mobile/client';
|
||||||
|
|
||||||
function TaskStatusColumn(props) {
|
function TaskStatusColumn(props) {
|
||||||
const recordData = useCollectionRecordData();
|
const recordData = useCollectionRecordData();
|
||||||
@ -390,7 +392,7 @@ function FlowContextProvider(props) {
|
|||||||
}}
|
}}
|
||||||
schema={{
|
schema={{
|
||||||
type: 'void',
|
type: 'void',
|
||||||
name: 'tabs',
|
name: `manual-${id}}`,
|
||||||
'x-component': 'Tabs',
|
'x-component': 'Tabs',
|
||||||
properties: node.config?.schema,
|
properties: node.config?.schema,
|
||||||
}}
|
}}
|
||||||
@ -429,16 +431,23 @@ function useDetailsBlockProps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FooterStatus() {
|
function FooterStatus() {
|
||||||
|
const { isMobileLayout } = useMobileLayout();
|
||||||
|
const mobilePage = useMobilePage();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
const { status, updatedAt } = useCollectionRecordData() || {};
|
const { status, updatedAt } = useCollectionRecordData() || {};
|
||||||
const statusOption = TaskStatusOptionsMap[status];
|
const statusOption = TaskStatusOptionsMap[status];
|
||||||
|
const isMobile = Boolean(mobilePage || isMobileLayout);
|
||||||
return status ? (
|
return status ? (
|
||||||
<Space
|
<Space
|
||||||
className={css`
|
className={css`
|
||||||
margin-bottom: 1em;
|
padding: ${isMobileLayout ? '0 1em' : '0'};
|
||||||
|
margin-bottom: ${isMobile ? '0' : '1em'};
|
||||||
time {
|
time {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
.ant-tag {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<time>{dayjs(updatedAt).format('YYYY-MM-DD HH:mm:ss')}</time>
|
<time>{dayjs(updatedAt).format('YYYY-MM-DD HH:mm:ss')}</time>
|
||||||
@ -449,9 +458,10 @@ function FooterStatus() {
|
|||||||
|
|
||||||
function Drawer() {
|
function Drawer() {
|
||||||
const ctx = useContext(SchemaComponentContext);
|
const ctx = useContext(SchemaComponentContext);
|
||||||
const { id, node, workflow, status } = useCollectionRecordData() || {};
|
const record = useCollectionRecordData();
|
||||||
|
const { id, node, workflow, status } = record || {};
|
||||||
|
|
||||||
return (
|
return record ? (
|
||||||
<SchemaComponentContext.Provider value={{ ...ctx, reset() {}, designable: false }}>
|
<SchemaComponentContext.Provider value={{ ...ctx, reset() {}, designable: false }}>
|
||||||
<SchemaComponent
|
<SchemaComponent
|
||||||
components={{
|
components={{
|
||||||
@ -460,7 +470,7 @@ function Drawer() {
|
|||||||
}}
|
}}
|
||||||
schema={{
|
schema={{
|
||||||
type: 'void',
|
type: 'void',
|
||||||
name: `drawer-${id}-${status}`,
|
name: `manual-detail-drawer-${id}-${status}`,
|
||||||
'x-component': 'Action.Container',
|
'x-component': 'Action.Container',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
className: 'nb-action-popup',
|
className: 'nb-action-popup',
|
||||||
@ -485,7 +495,7 @@ function Drawer() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SchemaComponentContext.Provider>
|
</SchemaComponentContext.Provider>
|
||||||
);
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Decorator(props) {
|
function Decorator(props) {
|
||||||
@ -667,6 +677,8 @@ function useTodoActionParams(status) {
|
|||||||
return {
|
return {
|
||||||
filter,
|
filter,
|
||||||
appends: [
|
appends: [
|
||||||
|
'node.id',
|
||||||
|
'node.title',
|
||||||
'job.id',
|
'job.id',
|
||||||
'job.status',
|
'job.status',
|
||||||
'job.result',
|
'job.result',
|
||||||
@ -676,10 +688,11 @@ function useTodoActionParams(status) {
|
|||||||
'execution.id',
|
'execution.id',
|
||||||
'execution.status',
|
'execution.status',
|
||||||
],
|
],
|
||||||
|
except: ['node.config', 'workflow.config', 'workflow.options'],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function TodoExtraActions() {
|
function TodoExtraActions(props) {
|
||||||
return (
|
return (
|
||||||
<SchemaComponent
|
<SchemaComponent
|
||||||
schema={{
|
schema={{
|
||||||
@ -694,6 +707,7 @@ function TodoExtraActions() {
|
|||||||
'x-use-component-props': 'useRefreshActionProps',
|
'x-use-component-props': 'useRefreshActionProps',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
icon: 'ReloadOutlined',
|
icon: 'ReloadOutlined',
|
||||||
|
...props,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
filter: {
|
filter: {
|
||||||
@ -703,6 +717,7 @@ function TodoExtraActions() {
|
|||||||
'x-use-component-props': 'useFilterActionProps',
|
'x-use-component-props': 'useFilterActionProps',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
icon: 'FilterOutlined',
|
icon: 'FilterOutlined',
|
||||||
|
...props,
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
$and: [{ title: { $includes: '' } }, { 'workflow.title': { $includes: '' } }],
|
$and: [{ title: { $includes: '' } }, { 'workflow.title': { $includes: '' } }],
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"@nocobase/logger": "1.x",
|
"@nocobase/logger": "1.x",
|
||||||
"@nocobase/plugin-data-source-main": "1.x",
|
"@nocobase/plugin-data-source-main": "1.x",
|
||||||
"@nocobase/plugin-error-handler": "1.x",
|
"@nocobase/plugin-error-handler": "1.x",
|
||||||
|
"@nocobase/plugin-mobile": "1.x",
|
||||||
"@nocobase/plugin-users": "1.x",
|
"@nocobase/plugin-users": "1.x",
|
||||||
"@nocobase/resourcer": "1.x",
|
"@nocobase/resourcer": "1.x",
|
||||||
"@nocobase/server": "1.x",
|
"@nocobase/server": "1.x",
|
||||||
|
@ -6,12 +6,14 @@
|
|||||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
import { CheckCircleOutlined } from '@ant-design/icons';
|
import { CheckCircleOutlined, EllipsisOutlined } from '@ant-design/icons';
|
||||||
import { PageHeader } from '@ant-design/pro-layout';
|
import { PageHeader } from '@ant-design/pro-layout';
|
||||||
import { Badge, Button, Layout, Menu, Tabs, Tooltip } from 'antd';
|
import { Badge, Button, Flex, Layout, Menu, Popover, Segmented, Tabs, theme, Tooltip } from 'antd';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||||
|
import { NavBar, Toast } from 'antd-mobile';
|
||||||
|
import { observer } from '@formily/react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionContextProvider,
|
ActionContextProvider,
|
||||||
@ -26,11 +28,25 @@ import {
|
|||||||
useCompile,
|
useCompile,
|
||||||
useDocumentTitle,
|
useDocumentTitle,
|
||||||
useIsLoggedIn,
|
useIsLoggedIn,
|
||||||
|
useMobileLayout,
|
||||||
usePlugin,
|
usePlugin,
|
||||||
useRequest,
|
useRequest,
|
||||||
useToken,
|
useToken,
|
||||||
|
SchemaInitializerItemType,
|
||||||
|
APIClient,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MobilePageContentContainer,
|
||||||
|
MobilePageHeader,
|
||||||
|
MobilePageNavigationBar,
|
||||||
|
MobilePageProvider,
|
||||||
|
MobileRouteItem,
|
||||||
|
MobileTabBarItem,
|
||||||
|
useMobilePage,
|
||||||
|
useMobileRoutes,
|
||||||
|
} from '@nocobase/plugin-mobile/client';
|
||||||
|
|
||||||
import PluginWorkflowClient from '.';
|
import PluginWorkflowClient from '.';
|
||||||
import { lang, NAMESPACE } from './locale';
|
import { lang, NAMESPACE } from './locale';
|
||||||
|
|
||||||
@ -39,11 +55,6 @@ const layoutClass = css`
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const contentClass = css`
|
|
||||||
min-height: 280px;
|
|
||||||
overflow: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface TaskTypeOptions {
|
export interface TaskTypeOptions {
|
||||||
title: string;
|
title: string;
|
||||||
collection: string;
|
collection: string;
|
||||||
@ -52,6 +63,7 @@ export interface TaskTypeOptions {
|
|||||||
Actions?: React.ComponentType;
|
Actions?: React.ComponentType;
|
||||||
Item: React.ComponentType;
|
Item: React.ComponentType;
|
||||||
Detail: React.ComponentType;
|
Detail: React.ComponentType;
|
||||||
|
getPopupRecord?: (apiClient: APIClient, { params }: { params: any }) => Promise<any>;
|
||||||
// children?: TaskTypeOptions[];
|
// children?: TaskTypeOptions[];
|
||||||
alwaysShow?: boolean;
|
alwaysShow?: boolean;
|
||||||
}
|
}
|
||||||
@ -70,12 +82,18 @@ function MenuLink({ type }: any) {
|
|||||||
const { title } = workflowPlugin.taskTypes.get(type);
|
const { title } = workflowPlugin.taskTypes.get(type);
|
||||||
const { counts } = useContext(TasksCountsContext);
|
const { counts } = useContext(TasksCountsContext);
|
||||||
const typeTitle = compile(title);
|
const typeTitle = compile(title);
|
||||||
|
const mobilePage = useMobilePage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
to={`/admin/workflow/tasks/${type}/${TASK_STATUS.PENDING}`}
|
to={
|
||||||
|
mobilePage
|
||||||
|
? `/page/workflow/tasks/${type}/${TASK_STATUS.PENDING}`
|
||||||
|
: `/admin/workflow/tasks/${type}/${TASK_STATUS.PENDING}`
|
||||||
|
}
|
||||||
className={css`
|
className={css`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 0.5em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -103,13 +121,42 @@ function StatusTabs() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { taskType, status = TASK_STATUS.PENDING } = useParams();
|
const { taskType, status = TASK_STATUS.PENDING } = useParams();
|
||||||
const type = useCurrentTaskType();
|
const type = useCurrentTaskType();
|
||||||
|
const { isMobileLayout } = useMobileLayout();
|
||||||
|
const mobilePage = useMobilePage();
|
||||||
|
const onSwitchTab = useCallback(
|
||||||
|
(key: string) => {
|
||||||
|
navigate(mobilePage ? `/page/workflow/tasks/${taskType}/${key}` : `/admin/workflow/tasks/${taskType}/${key}`);
|
||||||
|
},
|
||||||
|
[navigate, taskType, mobilePage],
|
||||||
|
);
|
||||||
|
const isMobile = Boolean(mobilePage || isMobileLayout);
|
||||||
const { Actions } = type;
|
const { Actions } = type;
|
||||||
return (
|
return isMobile ? (
|
||||||
|
<Flex justify="space-between">
|
||||||
|
<Segmented
|
||||||
|
defaultValue={status}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
value: TASK_STATUS.PENDING,
|
||||||
|
label: lang('Pending'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TASK_STATUS.COMPLETED,
|
||||||
|
label: lang('Completed'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TASK_STATUS.ALL,
|
||||||
|
label: lang('All'),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onChange={onSwitchTab}
|
||||||
|
/>
|
||||||
|
<Actions onlyIcon={isMobile} />
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
<Tabs
|
<Tabs
|
||||||
activeKey={status}
|
activeKey={status}
|
||||||
onChange={(activeKey) => {
|
onChange={onSwitchTab}
|
||||||
navigate(`/admin/workflow/tasks/${taskType}/${activeKey}`);
|
|
||||||
}}
|
|
||||||
className={css`
|
className={css`
|
||||||
&.ant-tabs-top > .ant-tabs-nav {
|
&.ant-tabs-top > .ant-tabs-nav {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -142,8 +189,8 @@ function StatusTabs() {
|
|||||||
|
|
||||||
function useTaskTypeItems() {
|
function useTaskTypeItems() {
|
||||||
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
const workflowPlugin = usePlugin(PluginWorkflowClient);
|
||||||
const { counts } = useContext(TasksCountsContext);
|
|
||||||
const types = workflowPlugin.taskTypes.getKeys();
|
const types = workflowPlugin.taskTypes.getKeys();
|
||||||
|
const { counts } = useContext(TasksCountsContext);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -173,26 +220,30 @@ function PopupContext(props: any) {
|
|||||||
const { taskType, status = TASK_STATUS.PENDING, popupId } = useParams();
|
const { taskType, status = TASK_STATUS.PENDING, popupId } = useParams();
|
||||||
const { record } = usePopupRecordContext();
|
const { record } = usePopupRecordContext();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const mobilePage = useMobilePage();
|
||||||
|
const setVisible = useCallback(
|
||||||
|
(visible: boolean) => {
|
||||||
|
if (!visible) {
|
||||||
|
if (window.history.state.idx) {
|
||||||
|
navigate(-1);
|
||||||
|
} else {
|
||||||
|
navigate(
|
||||||
|
mobilePage ? `/page/workflow/tasks/${taskType}/${status}` : `/admin/workflow/tasks/${taskType}/${status}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[mobilePage, navigate, status, taskType],
|
||||||
|
);
|
||||||
if (!popupId) {
|
if (!popupId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
|
||||||
<ActionContextProvider
|
return record ? (
|
||||||
visible={Boolean(popupId)}
|
<ActionContextProvider visible={Boolean(popupId)} setVisible={setVisible} openMode="modal" openSize="large">
|
||||||
setVisible={(visible) => {
|
|
||||||
if (!visible) {
|
|
||||||
if (window.history.state.idx) {
|
|
||||||
navigate(-1);
|
|
||||||
} else {
|
|
||||||
navigate(`/admin/workflow/tasks/${taskType}/${status}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
openMode="modal"
|
|
||||||
>
|
|
||||||
<CollectionRecordProvider record={record}>{props.children}</CollectionRecordProvider>
|
<CollectionRecordProvider record={record}>{props.children}</CollectionRecordProvider>
|
||||||
</ActionContextProvider>
|
</ActionContextProvider>
|
||||||
);
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PopupRecordContext = createContext<any>({ record: null, setRecord: (record) => {} });
|
const PopupRecordContext = createContext<any>({ record: null, setRecord: (record) => {} });
|
||||||
@ -200,18 +251,229 @@ export function usePopupRecordContext() {
|
|||||||
return useContext(PopupRecordContext);
|
return useContext(PopupRecordContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function TaskPageContent() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const apiClient = useAPIClient();
|
||||||
|
const { taskType, status = TASK_STATUS.PENDING, popupId } = useParams();
|
||||||
|
const mobilePage = useMobilePage();
|
||||||
|
const [currentRecord, setCurrentRecord] = useState<any>(null);
|
||||||
|
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const items = useTaskTypeItems();
|
||||||
|
const { title, collection, action = 'list', useActionParams, Item, Detail, getPopupRecord } = useCurrentTaskType();
|
||||||
|
const params = useActionParams(status);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// setTitle?.(`${lang('Workflow todos')}${title ? `: ${compile(title)}` : ''}`);
|
||||||
|
// }, [taskType, status, setTitle, title, compile]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!taskType) {
|
||||||
|
navigate(
|
||||||
|
mobilePage
|
||||||
|
? `/page/workflow/tasks/${items[0].key}/${status}`
|
||||||
|
: `/admin/workflow/tasks/${items[0].key}/${status}`,
|
||||||
|
{ replace: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [items, mobilePage, navigate, status, taskType]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (popupId && !currentRecord) {
|
||||||
|
let load;
|
||||||
|
if (getPopupRecord) {
|
||||||
|
load = getPopupRecord(apiClient, { params: { ...params, filterByTk: popupId } });
|
||||||
|
} else {
|
||||||
|
load = apiClient.resource(collection).get({
|
||||||
|
...params,
|
||||||
|
filterByTk: popupId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
load
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data?.data) {
|
||||||
|
setCurrentRecord(res.data.data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [popupId, collection, currentRecord, apiClient, getPopupRecord]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!taskType) {
|
||||||
|
navigate(
|
||||||
|
mobilePage
|
||||||
|
? `/page/workflow/tasks/${items[0].key}/${status}`
|
||||||
|
: `/admin/workflow/tasks/${items[0].key}/${status}`,
|
||||||
|
{ replace: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [items, mobilePage, navigate, status, taskType]);
|
||||||
|
|
||||||
|
const typeKey = taskType ?? items[0].key;
|
||||||
|
|
||||||
|
const { isMobileLayout } = useMobileLayout();
|
||||||
|
|
||||||
|
const isMobile = mobilePage || isMobileLayout;
|
||||||
|
|
||||||
|
const contentClass = css`
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.nb-list {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.nb-list-container {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-formily-layout {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-spin-nested-loading {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-spin-container {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
padding: ${isMobile ? '0.5em' : `${token.paddingContentHorizontalLG}px`};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemCss:not(:last-child) {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-list-pagination {
|
||||||
|
margin-top: 0;
|
||||||
|
padding: ${isMobile
|
||||||
|
? '0.5em'
|
||||||
|
: `${token.paddingContentHorizontal}px ${token.paddingContentHorizontalLG}px`};
|
||||||
|
border-top: 1px solid ${token.colorBorderSecondary};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PopupRecordContext.Provider
|
||||||
|
value={{
|
||||||
|
record: currentRecord,
|
||||||
|
setRecord: setCurrentRecord,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SchemaComponentContext.Provider value={{ designable: false }}>
|
||||||
|
<SchemaComponent
|
||||||
|
components={{
|
||||||
|
Layout,
|
||||||
|
PageHeader,
|
||||||
|
StatusTabs,
|
||||||
|
}}
|
||||||
|
schema={{
|
||||||
|
name: `${taskType}-${status}`,
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'List.Decorator',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection,
|
||||||
|
action,
|
||||||
|
params: {
|
||||||
|
pageSize: 20,
|
||||||
|
sort: ['-createdAt'],
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
header: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'PageHeader',
|
||||||
|
'x-component-props': {
|
||||||
|
className: classnames(
|
||||||
|
'pageHeaderCss',
|
||||||
|
css`
|
||||||
|
.ant-page-header-content {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
),
|
||||||
|
style: {
|
||||||
|
position: 'sticky',
|
||||||
|
background: token.colorBgContainer,
|
||||||
|
padding: isMobile
|
||||||
|
? '8px'
|
||||||
|
: `${token.paddingContentVertical}px ${token.paddingContentHorizontalLG}px 0 ${token.paddingContentHorizontalLG}px`,
|
||||||
|
borderBottom: isMobile ? `1px solid ${token.colorBorderSecondary}` : null,
|
||||||
|
},
|
||||||
|
title: isMobile ? null : title,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
tabs: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'StatusTabs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Layout.Content',
|
||||||
|
'x-component-props': {
|
||||||
|
className: contentClass,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
list: {
|
||||||
|
type: 'array',
|
||||||
|
'x-component': 'List',
|
||||||
|
'x-component-props': {
|
||||||
|
locale: {
|
||||||
|
emptyText: `{{ t("No data yet", { ns: "${NAMESPACE}" }) }}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
item: {
|
||||||
|
type: 'object',
|
||||||
|
'x-decorator': 'List.Item',
|
||||||
|
'x-component': Item,
|
||||||
|
'x-read-pretty': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
popup: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': PopupContext,
|
||||||
|
'x-component': Detail,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaComponentContext.Provider>
|
||||||
|
</PopupRecordContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function WorkflowTasks() {
|
export function WorkflowTasks() {
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
const { setTitle } = useDocumentTitle();
|
const { setTitle } = useDocumentTitle();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { taskType, status = TASK_STATUS.PENDING, popupId } = useParams();
|
const { taskType, status = TASK_STATUS.PENDING } = useParams();
|
||||||
const { token } = useToken();
|
const { token } = useToken();
|
||||||
const [currentRecord, setCurrentRecord] = useState<any>(null);
|
|
||||||
const items = useTaskTypeItems();
|
const items = useTaskTypeItems();
|
||||||
|
|
||||||
const { title, collection, action = 'list', useActionParams, Item, Detail } = useCurrentTaskType();
|
const { title } = useCurrentTaskType();
|
||||||
|
|
||||||
const params = useActionParams(status);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTitle?.(`${lang('Workflow todos')}${title ? `: ${compile(title)}` : ''}`);
|
setTitle?.(`${lang('Workflow todos')}${title ? `: ${compile(title)}` : ''}`);
|
||||||
@ -223,19 +485,21 @@ export function WorkflowTasks() {
|
|||||||
}
|
}
|
||||||
}, [items, navigate, status, taskType]);
|
}, [items, navigate, status, taskType]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (popupId && !currentRecord) {
|
|
||||||
setCurrentRecord({ id: popupId });
|
|
||||||
}
|
|
||||||
}, [popupId, currentRecord]);
|
|
||||||
|
|
||||||
const typeKey = taskType ?? items[0].key;
|
const typeKey = taskType ?? items[0].key;
|
||||||
|
|
||||||
|
const { isMobileLayout } = useMobileLayout();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className={layoutClass}>
|
<Layout className={layoutClass}>
|
||||||
<Layout.Sider theme="light" breakpoint="md" collapsedWidth="0" zeroWidthTriggerStyle={{ top: 24 }}>
|
{isMobileLayout ? (
|
||||||
<Menu mode="inline" selectedKeys={[typeKey]} items={items} style={{ height: '100%' }} />
|
<Layout.Header style={{ background: token.colorBgContainer, padding: 0, height: '3em', lineHeight: '3em' }}>
|
||||||
</Layout.Sider>
|
<Menu mode="horizontal" selectedKeys={[typeKey]} items={items} />
|
||||||
|
</Layout.Header>
|
||||||
|
) : (
|
||||||
|
<Layout.Sider theme="light" breakpoint="md" collapsedWidth="0" zeroWidthTriggerStyle={{ top: 24 }}>
|
||||||
|
<Menu mode="inline" selectedKeys={[typeKey]} items={items} style={{ height: '100%' }} />
|
||||||
|
</Layout.Sider>
|
||||||
|
)}
|
||||||
<Layout
|
<Layout
|
||||||
className={css`
|
className={css`
|
||||||
> div {
|
> div {
|
||||||
@ -254,95 +518,7 @@ export function WorkflowTasks() {
|
|||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<PopupRecordContext.Provider
|
<TaskPageContent />
|
||||||
value={{
|
|
||||||
record: currentRecord,
|
|
||||||
setRecord: setCurrentRecord,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SchemaComponentContext.Provider value={{ designable: false }}>
|
|
||||||
<SchemaComponent
|
|
||||||
components={{
|
|
||||||
Layout,
|
|
||||||
PageHeader,
|
|
||||||
StatusTabs,
|
|
||||||
}}
|
|
||||||
schema={{
|
|
||||||
name: `${taskType}-${status}`,
|
|
||||||
type: 'void',
|
|
||||||
'x-decorator': 'List.Decorator',
|
|
||||||
'x-decorator-props': {
|
|
||||||
collection,
|
|
||||||
action,
|
|
||||||
params: {
|
|
||||||
pageSize: 20,
|
|
||||||
sort: ['-createdAt'],
|
|
||||||
...params,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
header: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'PageHeader',
|
|
||||||
'x-component-props': {
|
|
||||||
className: classnames('pageHeaderCss'),
|
|
||||||
style: {
|
|
||||||
background: token.colorBgContainer,
|
|
||||||
padding: '12px 24px 0 24px',
|
|
||||||
},
|
|
||||||
title,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
tabs: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'StatusTabs',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Layout.Content',
|
|
||||||
'x-component-props': {
|
|
||||||
className: contentClass,
|
|
||||||
style: {
|
|
||||||
padding: `${token.paddingPageVertical}px ${token.paddingPageHorizontal}px`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
list: {
|
|
||||||
type: 'array',
|
|
||||||
'x-component': 'List',
|
|
||||||
'x-component-props': {
|
|
||||||
className: css`
|
|
||||||
> .itemCss:not(:last-child) {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
locale: {
|
|
||||||
emptyText: `{{ t("No data yet", { ns: "${NAMESPACE}" }) }}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
item: {
|
|
||||||
type: 'object',
|
|
||||||
'x-decorator': 'List.Item',
|
|
||||||
'x-component': Item,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
popup: {
|
|
||||||
type: 'void',
|
|
||||||
'x-decorator': PopupContext,
|
|
||||||
'x-component': Detail,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SchemaComponentContext.Provider>
|
|
||||||
</PopupRecordContext.Provider>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
@ -439,3 +615,168 @@ export function TasksProvider(props: any) {
|
|||||||
|
|
||||||
return isLoggedIn ? <TasksCountsProvider>{content}</TasksCountsProvider> : content;
|
return isLoggedIn ? <TasksCountsProvider>{content}</TasksCountsProvider> : content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const tasksSchemaInitializerItem: SchemaInitializerItemType = {
|
||||||
|
name: 'workflow-tasks-center',
|
||||||
|
type: 'item',
|
||||||
|
useComponentProps() {
|
||||||
|
const { resource, refresh, schemaResource } = useMobileRoutes();
|
||||||
|
const items = useTaskTypeItems();
|
||||||
|
return {
|
||||||
|
isItem: true,
|
||||||
|
title: lang('Workflow Tasks'),
|
||||||
|
badge: 10,
|
||||||
|
async onClick(values) {
|
||||||
|
const res = await resource.list();
|
||||||
|
if (Array.isArray(res?.data?.data)) {
|
||||||
|
const findIndex = res?.data?.data.findIndex((route) => route?.options?.url === `/page/workflow/tasks`);
|
||||||
|
if (findIndex > -1) {
|
||||||
|
Toast.show({
|
||||||
|
icon: 'fail',
|
||||||
|
content: lang('The workflow tasks page has already been created.'),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { data } = await resource.create({
|
||||||
|
values: {
|
||||||
|
type: 'page',
|
||||||
|
title: lang('Workflow Tasks'),
|
||||||
|
icon: 'CheckCircleOutlined',
|
||||||
|
schemaUid: 'workflow/tasks',
|
||||||
|
options: {
|
||||||
|
url: `/page/workflow/tasks`,
|
||||||
|
schema: {
|
||||||
|
'x-component': 'MobileTabBarWorkflowTasksItem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// type: 'page',
|
||||||
|
// title: lang('Workflow tasks'),
|
||||||
|
// icon: 'CheckCircleOutlined',
|
||||||
|
// schemaUid: 'workflow-tasks',
|
||||||
|
// options: {
|
||||||
|
// url: `/page/workflow/tasks`,
|
||||||
|
// itemSchema: {
|
||||||
|
// name: uid(),
|
||||||
|
// 'x-decorator': 'BlockItem',
|
||||||
|
// 'x-settings': `mobile:tab-bar:page`,
|
||||||
|
// 'x-component': 'MobileTabBarWorkflowTasksItem',
|
||||||
|
// 'x-toolbar-props': {
|
||||||
|
// showBorder: false,
|
||||||
|
// showBackground: true,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
} as MobileRouteItem,
|
||||||
|
});
|
||||||
|
// const parentId = data.data.id;
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MobileTabBarWorkflowTasksItem = observer(
|
||||||
|
(props: any) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const items = useTaskTypeItems();
|
||||||
|
const onClick = useCallback(() => {
|
||||||
|
navigate(`/page/workflow/tasks/${items[0].key}/${TASK_STATUS.PENDING}`);
|
||||||
|
}, [items, navigate]);
|
||||||
|
const { total } = useContext(TasksCountsContext);
|
||||||
|
|
||||||
|
const selected = props.url && location.pathname.startsWith(props.url);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MobileTabBarItem
|
||||||
|
{...{
|
||||||
|
...props,
|
||||||
|
onClick,
|
||||||
|
badge: total > 0 ? total : undefined,
|
||||||
|
selected,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'MobileTabBarWorkflowTasksItem',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export function WorkflowTasksMobile() {
|
||||||
|
const items = useTaskTypeItems();
|
||||||
|
const { token } = useToken();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MobilePageProvider>
|
||||||
|
<MobilePageHeader>
|
||||||
|
<NavBar className="nb-workflow-tasks-back-action" onBack={() => navigate(-1)}>
|
||||||
|
{lang('Workflow tasks')}
|
||||||
|
</NavBar>
|
||||||
|
<Tabs
|
||||||
|
className={css({
|
||||||
|
padding: `0 ${token.paddingPageHorizontal}px`,
|
||||||
|
'.adm-tabs-header': {
|
||||||
|
borderBottomWidth: 0,
|
||||||
|
},
|
||||||
|
'.adm-tabs-tab': {
|
||||||
|
height: 49,
|
||||||
|
padding: '10px 0 10px',
|
||||||
|
},
|
||||||
|
'> .ant-tabs-nav': {
|
||||||
|
marginBottom: 0,
|
||||||
|
'&::before': {
|
||||||
|
borderBottom: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.ant-tabs-tab+.ant-tabs-tab': {
|
||||||
|
marginLeft: '2em',
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
items={items}
|
||||||
|
/>
|
||||||
|
</MobilePageHeader>
|
||||||
|
<MobilePageContentContainer
|
||||||
|
className={css`
|
||||||
|
padding: 0 !important;
|
||||||
|
> div {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> .ant-formily-layout {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-nb-list {
|
||||||
|
.itemCss:not(:last-child) {
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.itemCss:not(:first-child) {
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<TaskPageContent />
|
||||||
|
</MobilePageContentContainer>
|
||||||
|
</MobilePageProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { PagePopups, Plugin, useCompile } from '@nocobase/client';
|
import { PagePopups, Plugin, useCompile, lazy } from '@nocobase/client';
|
||||||
import { Registry } from '@nocobase/utils/client';
|
import { Registry } from '@nocobase/utils/client';
|
||||||
|
import MobileManager from '@nocobase/plugin-mobile/client';
|
||||||
|
|
||||||
// import { ExecutionPage } from './ExecutionPage';
|
// import { ExecutionPage } from './ExecutionPage';
|
||||||
// import { WorkflowPage } from './WorkflowPage';
|
// import { WorkflowPage } from './WorkflowPage';
|
||||||
// import { WorkflowPane } from './WorkflowPane';
|
// import { WorkflowPane } from './WorkflowPane';
|
||||||
import { lazy } from '@nocobase/client';
|
|
||||||
const { ExecutionPage } = lazy(() => import('./ExecutionPage'), 'ExecutionPage');
|
const { ExecutionPage } = lazy(() => import('./ExecutionPage'), 'ExecutionPage');
|
||||||
const { WorkflowPage } = lazy(() => import('./WorkflowPage'), 'WorkflowPage');
|
const { WorkflowPage } = lazy(() => import('./WorkflowPage'), 'WorkflowPage');
|
||||||
const { WorkflowPane } = lazy(() => import('./WorkflowPane'), 'WorkflowPane');
|
const { WorkflowPane } = lazy(() => import('./WorkflowPane'), 'WorkflowPane');
|
||||||
@ -33,8 +33,16 @@ import CollectionTrigger from './triggers/collection';
|
|||||||
import ScheduleTrigger from './triggers/schedule';
|
import ScheduleTrigger from './triggers/schedule';
|
||||||
import { getWorkflowDetailPath, getWorkflowExecutionsPath } from './utils';
|
import { getWorkflowDetailPath, getWorkflowExecutionsPath } from './utils';
|
||||||
import { VariableOption } from './variable';
|
import { VariableOption } from './variable';
|
||||||
import { TasksProvider, TaskTypeOptions, WorkflowTasks } from './WorkflowTasks';
|
import {
|
||||||
|
MobileTabBarWorkflowTasksItem,
|
||||||
|
TasksProvider,
|
||||||
|
tasksSchemaInitializerItem,
|
||||||
|
TaskTypeOptions,
|
||||||
|
WorkflowTasks,
|
||||||
|
WorkflowTasksMobile,
|
||||||
|
} from './WorkflowTasks';
|
||||||
import { WorkflowCollectionsProvider } from './WorkflowCollectionsProvider';
|
import { WorkflowCollectionsProvider } from './WorkflowCollectionsProvider';
|
||||||
|
import { observer } from '@formily/react';
|
||||||
|
|
||||||
const workflowConfigSettings = {
|
const workflowConfigSettings = {
|
||||||
Component: BindWorkflowConfig,
|
Component: BindWorkflowConfig,
|
||||||
@ -111,6 +119,22 @@ export default class PluginWorkflowClient extends Plugin {
|
|||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
this.app.addProvider(WorkflowCollectionsProvider);
|
this.app.addProvider(WorkflowCollectionsProvider);
|
||||||
|
this.app.addProvider(TasksProvider);
|
||||||
|
|
||||||
|
this.app.pluginSettingsManager.add(NAMESPACE, {
|
||||||
|
icon: 'PartitionOutlined',
|
||||||
|
title: `{{t("Workflow", { ns: "${NAMESPACE}" })}}`,
|
||||||
|
Component: WorkflowPane,
|
||||||
|
aclSnippet: 'pm.workflow.workflows',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:submit', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:createSubmit', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:updateSubmit', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:saveRecord', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:updateRecord', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:delete', 'workflowConfig', workflowConfigSettings);
|
||||||
|
this.app.schemaSettingsManager.addItem('actionSettings:bulkEditSubmit', 'workflowConfig', workflowConfigSettings);
|
||||||
|
|
||||||
this.router.add('admin.workflow.workflows.id', {
|
this.router.add('admin.workflow.workflows.id', {
|
||||||
path: getWorkflowDetailPath(':id'),
|
path: getWorkflowDetailPath(':id'),
|
||||||
@ -127,22 +151,18 @@ export default class PluginWorkflowClient extends Plugin {
|
|||||||
Component: WorkflowTasks,
|
Component: WorkflowTasks,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.app.pluginSettingsManager.add(NAMESPACE, {
|
const mobileManager = this.pm.get(MobileManager);
|
||||||
icon: 'PartitionOutlined',
|
this.app.schemaInitializerManager.addItem('mobile:tab-bar', 'workflow-tasks', tasksSchemaInitializerItem);
|
||||||
title: `{{t("Workflow", { ns: "${NAMESPACE}" })}}`,
|
this.app.addComponents({ MobileTabBarWorkflowTasksItem });
|
||||||
Component: WorkflowPane,
|
if (mobileManager.mobileRouter) {
|
||||||
aclSnippet: 'pm.workflow.workflows',
|
mobileManager.mobileRouter.add('mobile.page.workflow', {
|
||||||
});
|
path: '/page/workflow',
|
||||||
|
});
|
||||||
this.app.use(TasksProvider);
|
mobileManager.mobileRouter.add('mobile.page.workflow.tasks', {
|
||||||
|
path: '/page/workflow/tasks/:taskType/:status/:popupId?',
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:submit', 'workflowConfig', workflowConfigSettings);
|
Component: observer(WorkflowTasksMobile, { displayName: 'WorkflowTasksMobile' }),
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:createSubmit', 'workflowConfig', workflowConfigSettings);
|
});
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:updateSubmit', 'workflowConfig', workflowConfigSettings);
|
}
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:saveRecord', 'workflowConfig', workflowConfigSettings);
|
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:updateRecord', 'workflowConfig', workflowConfigSettings);
|
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:delete', 'workflowConfig', workflowConfigSettings);
|
|
||||||
this.app.schemaSettingsManager.addItem('actionSettings:bulkEditSubmit', 'workflowConfig', workflowConfigSettings);
|
|
||||||
|
|
||||||
this.registerInstructionGroup('control', { key: 'control', label: `{{t("Control", { ns: "${NAMESPACE}" })}}` });
|
this.registerInstructionGroup('control', { key: 'control', label: `{{t("Control", { ns: "${NAMESPACE}" })}}` });
|
||||||
this.registerInstructionGroup('calculation', {
|
this.registerInstructionGroup('calculation', {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user