nocobase/packages/core/client/src/block-provider/KanbanBlockProvider.tsx
被雨水过滤的空气-Rain 29bf187fbf
chore: optimize locators (#2833)
* test(e2e): better locators for designer buttons

* fix: make test passing

* refactor: remove DesignerControl

* chore: better locators

* fix: should not disable add-menu-item

* chore: better test id for block

* chore: optimize Action

* chore: remove role in BlockItem

* feat: improve locators

* chore: menu & add block

* chore: initializer

* chore: testid -> aria label

* chore: tabs

* chore: designers

* refactor: optimize schemaInitializer

* refactor: rename

* chore: add collectionName

* chore: block item

* chore: action

* fix: avoid crashting

* chore(e2e): add __E2E__

* chore: all dialog

* chore: add aria-label for block menu

* Revert "chore: add aria-label for block menu"

This reverts commit 6a840ef816ee1095484dc268b5dfa1bbe6cd8cbe.

* chore: optimize aria-label of Action

* chore: schema-initializer

* chore(e2e): increase timeout

* chore: schema settings

* chore: optimize table

* chore: workflow

* chore: plugin manager

* chore: collection manager and workflow

* chore: details of workflow

* chore: remove testid of Select

* test: fix unit-tests

* test: fix unit-tests

* test(e2e): passing tests

* test: fix unit test

* chore: should use hover

* test: passing tests

* chore: passing tests

* chore: fix CI

* chore: fix CI

* chore: increase timeout in CI

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
2023-10-27 15:32:17 +08:00

163 lines
5.1 KiB
TypeScript

import { ArrayField } from '@formily/core';
import { Schema, useField, useFieldSchema } from '@formily/react';
import { Spin } from 'antd';
import uniq from 'lodash/uniq';
import React, { createContext, useContext, useEffect } from 'react';
import { useACLRoleContext } from '../acl';
import { useCollection, useCollectionManager } from '../collection-manager';
import { FixedBlockWrapper } from '../schema-component';
import { toColumns } from '../schema-component/antd/kanban/Kanban';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
export const KanbanBlockContext = createContext<any>({});
const useGroupField = (props) => {
const { getField } = useCollection();
const { groupField } = props;
if (typeof groupField === 'string') {
return getField(groupField);
}
if (groupField?.name) {
return getField(groupField?.name);
}
};
const InternalKanbanBlockProvider = (props) => {
const field = useField<any>();
const { resource, service } = useBlockRequestContext();
const groupField = useGroupField(props);
if (!groupField) {
return null;
}
if (service.loading && !field.loaded) {
return <Spin />;
}
field.loaded = true;
return (
<FixedBlockWrapper>
<KanbanBlockContext.Provider
value={{
props: {
resource: props.resource,
},
field,
service,
resource,
groupField,
fixedBlock: field?.decoratorProps?.fixedBlock,
}}
>
{props.children}
</KanbanBlockContext.Provider>
</FixedBlockWrapper>
);
};
const recursiveProperties = (schema: Schema, component = 'CollectionField', associationFields, appends: any = []) => {
schema.mapProperties((s: any) => {
const name = s.name.toString();
if (s['x-component'] === component && !appends.includes(name)) {
// 关联字段和关联的关联字段
const [firstName] = name.split('.');
if (associationFields.has(name)) {
appends.push(name);
} else if (associationFields.has(firstName) && !appends.includes(firstName)) {
appends.push(firstName);
}
} else {
recursiveProperties(s, component, associationFields, appends);
}
});
};
const useAssociationNames = (collection) => {
const { getCollectionFields } = useCollectionManager();
const collectionFields = getCollectionFields(collection);
const associationFields = new Set();
for (const collectionField of collectionFields) {
if (collectionField.target) {
associationFields.add(collectionField.name);
const fields = getCollectionFields(collectionField.target);
for (const field of fields) {
if (field.target) {
associationFields.add(`${collectionField.name}.${field.name}`);
}
}
}
}
const fieldSchema = useFieldSchema();
const kanbanSchema = fieldSchema.reduceProperties((buf, schema) => {
if (schema['x-component'].startsWith('Kanban')) {
return schema;
}
return buf;
}, new Schema({}));
const gridSchema: any = kanbanSchema?.properties?.card?.properties?.grid;
const appends = [];
if (gridSchema) {
recursiveProperties(gridSchema, 'CollectionField', associationFields, appends);
}
return uniq(appends);
};
export const KanbanBlockProvider = (props) => {
const params = { ...props.params };
const appends = useAssociationNames(props.collection);
if (!Object.keys(params).includes('appends')) {
params['appends'] = appends;
}
return (
<BlockProvider name="kanban" {...props} params={params}>
<InternalKanbanBlockProvider {...props} params={params} />
</BlockProvider>
);
};
export const useKanbanBlockContext = () => {
return useContext(KanbanBlockContext);
};
const useDisableCardDrag = () => {
const ctx = useKanbanBlockContext();
const { allowAll, allowConfigure, parseAction } = useACLRoleContext();
if (allowAll || allowConfigure) {
return false;
}
const result = parseAction(`${ctx?.props?.resource}:update`, { ignoreScope: true });
return !result;
};
export const useKanbanBlockProps = () => {
const field = useField<ArrayField>();
const ctx = useKanbanBlockContext();
useEffect(() => {
if (!ctx?.service?.loading) {
field.value = toColumns(ctx.groupField, ctx?.service?.data?.data);
}
// field.loading = ctx?.service?.loading;
}, [ctx?.service?.loading]);
return {
groupField: ctx.groupField,
disableCardDrag: useDisableCardDrag(),
async onCardDragEnd({ columns, groupField }, { fromColumnId, fromPosition }, { toColumnId, toPosition }) {
const sourceColumn = columns.find((column) => column.id === fromColumnId);
const destinationColumn = columns.find((column) => column.id === toColumnId);
const sourceCard = sourceColumn?.cards?.[fromPosition];
const targetCard = destinationColumn?.cards?.[toPosition];
const values = {
sourceId: sourceCard.id,
sortField: `${groupField.name}_sort`,
};
if (targetCard) {
values['targetId'] = targetCard.id;
} else {
values['targetScope'] = {
[groupField.name]: toColumnId,
};
}
await ctx.resource.move(values);
},
};
};