contextMenuFactory menus中action支持数组

This commit is contained in:
wkj 2024-01-19 09:53:29 +08:00
parent fcb720eb79
commit 1d4b59bda5
18 changed files with 188 additions and 86 deletions

View File

@ -62,7 +62,7 @@ export default function Render(props) {
tfColumns.forEach((column, index) => {
const { colSpan } = column;
const colSpan2 = getSpan(colSpan || 1, mergedColumn);
const item = (<Col span={gridColumn * colSpan2}>
const item = (<Col key={`c_filterPanel_col_${index}`} span={gridColumn * colSpan2}>
<Filter column={column} entity={entity} oakPath={oakFullpath}/>
</Col>);
if (index === 0) {
@ -120,7 +120,7 @@ export default function Render(props) {
}
}
else {
if (width === 'xs') {
if (width === 'xs' && !!firstItem) {
items.push(firstItem);
}
}
@ -137,7 +137,7 @@ export default function Render(props) {
const buttonItemLayout = formLayout === 'horizontal'
? { wrapperCol: { span: 18, offset: 6 } }
: null;
items.push(<Col span={_gridColumn}>
items.push(<Col key={`c_filterPanel_buttons`} span={_gridColumn}>
<Form.Item {...buttonItemLayout}>
<Space className={Style.actionBox}>
<Badge count={count}>
@ -162,7 +162,9 @@ export default function Render(props) {
setOpen(!open);
}}>
<Space>
{open ? t('common::shrink') : t('common::expand')}
{open
? t('common::shrink')
: t('common::expand')}
{open ? <UpOutlined /> : <DownOutlined />}
</Space>

View File

@ -1,8 +1,7 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { ListButtonProps, ED } from '../../../types/AbstractComponent';
import { WebComponentProps } from '../../../types/Page';
export default function Render(props: WebComponentProps<EntityDict & BaseEntityDict, keyof EntityDict, false, {
export default function Render(props: WebComponentProps<ED, keyof EntityDict, false, {
items: ListButtonProps[];
}, {}>): React.JSX.Element;
}, {}>): React.JSX.Element | null;

View File

@ -4,13 +4,15 @@ import { FloatButton } from 'antd';
import { BarsOutlined, } from '@ant-design/icons';
export default function Render(props) {
const { methods, data } = props;
const { t } = methods;
const { items } = data;
if (items && items.length === 1) {
if (!items || items.length === 0) {
return null;
}
if (items?.length === 1) {
const item = items[0];
return (<FloatButton shape="circle" type="primary" style={{ right: 24 }} icon={item.icon} description={item.icon ? null : item.label} onClick={() => item.onClick()}/>);
}
return (<FloatButton.Group shape='circle' trigger="click" type="primary" style={{ right: 24 }} icon={<BarsOutlined />}>
{items && items.map((ele) => (<FloatButton icon={ele.icon} description={ele.icon ? null : ele.label} onClick={() => ele.onClick()}/>))}
return (<FloatButton.Group shape="circle" trigger="click" type="primary" style={{ right: 24 }} icon={<BarsOutlined />}>
{items?.map((ele, index) => (<FloatButton key={`c_buttonGroup_${index}`} icon={ele.icon} description={ele.icon ? null : ele.label} onClick={() => ele.onClick()}/>))}
</FloatButton.Group>);
}

View File

@ -1,8 +1,7 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../../types/Page';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
export default function Render(props: WebComponentProps<EntityDict & BaseEntityDict, keyof EntityDict, false, {
import { ListButtonProps, ED } from '../../../types/AbstractComponent';
export default function Render(props: WebComponentProps<ED, keyof EntityDict, false, {
items: ListButtonProps[];
}, {}>): React.JSX.Element;
}, {}>): React.JSX.Element | null;

View File

@ -1,12 +1,15 @@
import React from 'react';
import { Space, Button } from 'antd';
export default function Render(props) {
const { methods, data: oakData } = props;
const { items } = oakData;
// 为了i18更新时能够重新渲染
const { methods, data } = props;
const { items } = data;
if (!items || items.length === 0) {
return null;
}
return (<Space>
{items.filter((ele) => ele.show).map((ele) => (<Button type={ele.type} onClick={ele.onClick}>
{ele.label}
</Button>))}
{items?.filter((ele) => ele.show)
.map((ele, index) => (<Button key={`c_buttonGroup_${index}`} type={ele.type} onClick={ele.onClick}>
{ele.label}
</Button>))}
</Space>);
}

View File

@ -5,7 +5,7 @@ export default OakComponent({
properties: {
entity: '',
extraActions: [],
onAction: (() => undefined),
onAction: (() => { }),
disabledOp: false,
attributes: [],
data: [],

View File

@ -9,7 +9,7 @@ import { RelationAuth } from './relationAuth';
interface IMenu<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
name: string;
entity: T;
action: ED[T]['Action'];
action: ED[T]['Action'] | ED[T]['Action'][];
paths: string[];
}
export declare class ContextMenuFactory<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt> & Record<string, Aspect<ED, Cxt>>> extends Feature {

View File

@ -28,9 +28,9 @@ export class ContextMenuFactory extends Feature {
}
return;
}
const pathhh = path.split('.');
const pathArr = path.split('.');
const judgeIter = (e2, idx) => {
const attr = pathhh[idx];
const attr = pathArr[idx];
const rel = judgeRelation(schema, e2, attr);
let e3 = e2;
if (typeof rel === 'string') {
@ -43,14 +43,14 @@ export class ContextMenuFactory extends Feature {
assert(rel instanceof Array);
e3 = rel[0];
}
if (idx === pathhh.length - 1) {
if (idx === pathArr.length - 1) {
if (e3 === 'user') {
// 用user连接说明一定满足
return true;
}
if (e3 === entity) {
const filter = {};
const paths2 = pathhh.slice(0, pathhh.length - 1);
const paths2 = pathArr.slice(0, pathArr.length - 1);
if (rel === 2) {
set(filter, paths2.concat('entity'), entity);
set(filter, paths2.concat('entityId'), entityId);
@ -87,6 +87,28 @@ export class ContextMenuFactory extends Feature {
return true;
}
// relationAuth和其它的checker现在分开判断
let result = false;
if (action instanceof Array) {
for (let i = 0; i < action.length; i++) {
// action有一个满足就行了
const checkResult = this.relationAuth.checkRelation(destEntity, {
action: action[i],
data: undefined,
filter,
}) &&
this.cache.checkOperation(destEntity, action[i], undefined, filter, [
'logical',
'relation',
'logicalRelation',
'row',
]);
if (checkResult) {
result = checkResult;
break;
}
}
return result;
}
return (this.relationAuth.checkRelation(destEntity, {
action,
data: undefined,

View File

@ -73,7 +73,9 @@ export function resolvePath(dataSchema, entity, path) {
idx++;
}
catch (err) {
console.log(`存在非schema属性${path}`);
if (process.env.NODE_ENV === 'development') {
console.warn(`存在非「${_entity}」schema属性: ${path}`);
}
return {
entity: 'notExist',
attr: path,

View File

@ -9,7 +9,7 @@ import { RelationAuth } from './relationAuth';
interface IMenu<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
name: string;
entity: T;
action: ED[T]['Action'];
action: ED[T]['Action'] | ED[T]['Action'][];
paths: string[];
}
export declare class ContextMenuFactory<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt> & Record<string, Aspect<ED, Cxt>>> extends Feature {

View File

@ -31,9 +31,9 @@ class ContextMenuFactory extends Feature_1.Feature {
}
return;
}
const pathhh = path.split('.');
const pathArr = path.split('.');
const judgeIter = (e2, idx) => {
const attr = pathhh[idx];
const attr = pathArr[idx];
const rel = (0, relation_1.judgeRelation)(schema, e2, attr);
let e3 = e2;
if (typeof rel === 'string') {
@ -46,14 +46,14 @@ class ContextMenuFactory extends Feature_1.Feature {
(0, assert_1.assert)(rel instanceof Array);
e3 = rel[0];
}
if (idx === pathhh.length - 1) {
if (idx === pathArr.length - 1) {
if (e3 === 'user') {
// 用user连接说明一定满足
return true;
}
if (e3 === entity) {
const filter = {};
const paths2 = pathhh.slice(0, pathhh.length - 1);
const paths2 = pathArr.slice(0, pathArr.length - 1);
if (rel === 2) {
(0, lodash_1.set)(filter, paths2.concat('entity'), entity);
(0, lodash_1.set)(filter, paths2.concat('entityId'), entityId);
@ -90,6 +90,28 @@ class ContextMenuFactory extends Feature_1.Feature {
return true;
}
// relationAuth和其它的checker现在分开判断
let result = false;
if (action instanceof Array) {
for (let i = 0; i < action.length; i++) {
// action有一个满足就行了
const checkResult = this.relationAuth.checkRelation(destEntity, {
action: action[i],
data: undefined,
filter,
}) &&
this.cache.checkOperation(destEntity, action[i], undefined, filter, [
'logical',
'relation',
'logicalRelation',
'row',
]);
if (checkResult) {
result = checkResult;
break;
}
}
return result;
}
return (this.relationAuth.checkRelation(destEntity, {
action,
data: undefined,

View File

@ -78,7 +78,9 @@ function resolvePath(dataSchema, entity, path) {
idx++;
}
catch (err) {
console.log(`存在非schema属性${path}`);
if (process.env.NODE_ENV === 'development') {
console.warn(`存在非「${_entity}」schema属性: ${path}`);
}
return {
entity: 'notExist',
attr: path,

View File

@ -111,7 +111,7 @@ export default function Render<ED2 extends ED>(
);
const count = filters2?.length || 0; //查询条件个数
const items: any = [];
const items: React.JSX.Element[] = [];
let rowSum = 0;
let rowSum2 = 0;
let rows2 = 1;
@ -122,7 +122,10 @@ export default function Render<ED2 extends ED>(
const colSpan2 = getSpan(colSpan || 1, mergedColumn);
const item = (
<Col span={gridColumn * colSpan2}>
<Col
key={`c_filterPanel_col_${index}`}
span={gridColumn * colSpan2}
>
<Filter
column={column as ColumnProps<ED, keyof ED>}
entity={entity}
@ -183,7 +186,7 @@ export default function Render<ED2 extends ED>(
_gridColumn = gridColumn * (mergedColumn - rowSum);
}
} else {
if (width === 'xs') {
if (width === 'xs' && !!firstItem) {
items.push(firstItem);
}
}
@ -204,7 +207,7 @@ export default function Render<ED2 extends ED>(
? { wrapperCol: { span: 18, offset: 6 } }
: null;
items.push(
<Col span={_gridColumn}>
<Col key={`c_filterPanel_buttons`} span={_gridColumn}>
<Form.Item {...buttonItemLayout}>
<Space className={Style.actionBox}>
<Badge count={count}>
@ -241,7 +244,9 @@ export default function Render<ED2 extends ED>(
}}
>
<Space>
{open ? t('common::shrink') : t('common::expand')}
{open
? t('common::shrink')
: t('common::expand')}
{open ? <UpOutlined /> : <DownOutlined />}
</Space>

View File

@ -2,36 +2,36 @@ import React from 'react';
import { Space, Button } from 'antd';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../../types/Page';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
type ED = EntityDict & BaseEntityDict;
import { ListButtonProps, ED } from '../../../types/AbstractComponent';
export default function Render(
props: WebComponentProps<
EntityDict & BaseEntityDict,
ED,
keyof EntityDict,
false,
{
items: ListButtonProps[];
},
{
}
{}
>
) {
const { methods, data: oakData } = props;
const {
items
} = oakData;
// 为了i18更新时能够重新渲染
const { methods, data } = props;
const { items } = data;
if (!items || items.length === 0) {
return null;
}
return (
<Space>
{items.filter((ele) => ele.show).map((ele) => (
<Button type={ele.type} onClick={ele.onClick}>
{ele.label}
</Button>
))}
{items?.filter((ele) => ele.show)
.map((ele, index) => (
<Button
key={`c_buttonGroup_${index}`}
type={ele.type}
onClick={ele.onClick}
>
{ele.label}
</Button>
))}
</Space>
);
}

View File

@ -3,33 +3,30 @@ import React from 'react';
import { FloatButton } from 'antd';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { ListButtonProps, ED } from '../../../types/AbstractComponent';
import { WebComponentProps } from '../../../types/Page';
import {
BarsOutlined,
} from '@ant-design/icons';
type ED = EntityDict & BaseEntityDict;
export default function Render(
props: WebComponentProps<
EntityDict & BaseEntityDict,
ED,
keyof EntityDict,
false,
{
items: ListButtonProps[];
},
{
}
{}
>
) {
const { methods, data } = props;
const { t } = methods;
const {
items
} = data;
if (items && items.length === 1) {
const { items } = data;
if (!items || items.length === 0) {
return null;
}
if (items?.length === 1) {
const item = items[0];
return (
<FloatButton
@ -40,18 +37,19 @@ export default function Render(
description={item.icon ? null : item.label}
onClick={() => item.onClick()}
/>
)
);
}
return (
<FloatButton.Group
shape='circle'
shape="circle"
trigger="click"
type="primary"
style={{ right: 24 }}
icon={<BarsOutlined />}
>
{items && items.map((ele) => (
{items?.map((ele, index) => (
<FloatButton
key={`c_buttonGroup_${index}`}
icon={ele.icon}
description={ele.icon ? null : ele.label}
onClick={() => ele.onClick()}

View File

@ -1,15 +1,17 @@
import { CardDef, ED, OakAbsAttrDef, onActionFnDef, OakExtraActionProps, ListButtonProps, OakAbsAttrJudgeDef } from '../../types/AbstractComponent';
import { ED, OakAbsAttrDef, onActionFnDef, OakExtraActionProps, OakAbsAttrJudgeDef } from '../../types/AbstractComponent';
import { analyzeAttrMobileForCard, translateAttributes } from '../../utils/usefulFn';
import { assert } from 'oak-domain/lib/utils/assert';
import { TableProps, PaginationProps } from 'antd';
import { TableProps } from 'antd';
import { RowWithActions, ReactComponentProps } from '../../types/Page';
export default OakComponent({
isList: false,
properties: {
entity: '' as keyof ED,
extraActions: [] as OakExtraActionProps[] | ((row: any) => OakExtraActionProps[]),
onAction: (() => undefined) as Function,
extraActions: [] as
| OakExtraActionProps[]
| ((row: RowWithActions<ED, keyof ED>) => OakExtraActionProps[]),
onAction: (() => {}) as Function,
disabledOp: false,
attributes: [] as OakAbsAttrDef[],
data: [] as RowWithActions<ED, keyof ED>[],
@ -40,7 +42,7 @@ export default OakComponent({
return {};
},
data: {
converter: (data: any) => <any>[],
converter: (data: RowWithActions<ED, keyof ED>[]) => <any>[],
judgeAttributes: [] as OakAbsAttrJudgeDef[],
},
listeners: {
@ -62,9 +64,13 @@ export default OakComponent({
schema,
entity,
ttt,
attributes!,
attributes!
);
const judgeAttributes = translateAttributes(
schema,
entity,
attributes!
);
const judgeAttributes = translateAttributes(schema, entity, attributes!);
this.setState({
converter,
schema,
@ -92,7 +98,9 @@ export default OakComponent({
false,
{
entity: T2;
extraActions: OakExtraActionProps[] | ((row: ED2[T2]['Schema']) => OakExtraActionProps[]);
extraActions:
| OakExtraActionProps[]
| ((row: ED2[T2]['Schema']) => OakExtraActionProps[]);
onAction: onActionFnDef;
disabledOp: boolean;
attributes: OakAbsAttrDef[];

View File

@ -13,7 +13,7 @@ import { RelationAuth } from './relationAuth';
interface IMenu<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
name: string;
entity: T;
action: ED[T]['Action'];
action: ED[T]['Action'] | ED[T]['Action'][];
paths: string[];
}
@ -60,13 +60,13 @@ export class ContextMenuFactory<
}
return;
}
const pathhh = path.split('.');
const pathArr = path.split('.');
const judgeIter = (
e2: keyof ED,
idx: number
): true | undefined | ED[keyof ED]['Selection']['filter'] => {
const attr = pathhh[idx];
const attr = pathArr[idx];
const rel = judgeRelation(schema, e2, attr);
let e3 = e2;
if (typeof rel === 'string') {
@ -77,7 +77,7 @@ export class ContextMenuFactory<
assert(rel instanceof Array);
e3 = rel[0];
}
if (idx === pathhh.length - 1) {
if (idx === pathArr.length - 1) {
if (e3 === 'user') {
// 用user连接说明一定满足
return true;
@ -85,7 +85,7 @@ export class ContextMenuFactory<
if (e3 === entity) {
const filter: ED[keyof ED]['Selection']['filter'] =
{};
const paths2 = pathhh.slice(0, pathhh.length - 1);
const paths2 = pathArr.slice(0, pathArr.length - 1);
if (rel === 2) {
set(filter, paths2.concat('entity'), entity);
set(
@ -140,6 +140,42 @@ export class ContextMenuFactory<
return true;
}
// relationAuth和其它的checker现在分开判断
let result = false;
if (action instanceof Array) {
for (let i = 0; i < action.length; i++) {
// action有一个满足就行了
const checkResult =
this.relationAuth.checkRelation(
destEntity,
{
action: action[i],
data: undefined as any,
filter,
} as Omit<
ED[keyof ED]['Operation'],
'id'
>
) &&
this.cache.checkOperation(
destEntity,
action[i],
undefined,
filter,
[
'logical',
'relation',
'logicalRelation',
'row',
]
);
if (checkResult) {
result = checkResult;
break;
}
}
return result;
}
return (
this.relationAuth.checkRelation(destEntity, {
action,

View File

@ -111,7 +111,9 @@ export function resolvePath<ED extends EntityDict & BaseEntityDict>(
}
idx++;
} catch (err) {
console.log(`存在非schema属性${path}`);
if (process.env.NODE_ENV === 'development') {
console.warn(`存在非「${_entity as string}」schema属性: ${path}`);
}
return {
entity: 'notExist',
attr: path,