nocobase/packages/core/client/src/block-provider/TableFieldProvider.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

169 lines
4.6 KiB
TypeScript

import { ArrayField, Field } from '@formily/core';
import { useField, useFieldSchema } from '@formily/react';
import React, { createContext, useContext, useEffect } from 'react';
import { APIClient } from '../api-client';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useFormBlockContext } from './FormBlockProvider';
import { useFormFieldContext } from './FormFieldProvider';
export const TableFieldContext = createContext<any>({});
const InternalTableFieldProvider = (props) => {
const { params = {}, showIndex, dragSort, fieldName } = props;
const field = useField();
const fieldSchema = useFieldSchema();
const { resource, service } = useBlockRequestContext();
const formBlockCtx = useFormBlockContext();
const formFieldCtx = useFormFieldContext();
const fullFieldName = formFieldCtx && formFieldCtx.fieldName ? `${formFieldCtx.fieldName}.${fieldName}` : fieldName;
if (!formBlockCtx?.updateAssociationValues?.includes(fullFieldName)) {
formBlockCtx?.updateAssociationValues?.push(fullFieldName);
}
// if (service.loading) {
// return <Spin />;
// }
return (
<TableFieldContext.Provider
value={{
field,
fieldSchema,
service,
resource,
params,
showIndex,
dragSort,
}}
>
{props.children}
</TableFieldContext.Provider>
);
};
export class TableFieldResource {
field: Field;
api: APIClient;
sourceId: any;
resource?: any;
constructor(options) {
this.field = options.field;
this.api = options.api;
this.sourceId = options.sourceId;
this.resource = this.api.resource(options.resource, this.sourceId);
}
async list(options) {
this.field.data = this.field.data || {};
if (this.field.data.changed) {
console.log('list.dataSource', this.field.data.dataSource);
return {
data: {
data: this.field.data.dataSource,
},
};
}
if (!this.sourceId) {
console.log('list.sourceId', this.field.data.dataSource);
this.field.data.dataSource = [];
return {
data: {
data: [],
},
};
}
const response = await this.resource.list(options);
console.log('list', response);
this.field.data.dataSource = response.data.data;
return {
data: {
data: response.data.data,
},
};
}
async get(options) {
console.log('get', options);
const { filterByTk } = options;
return {
data: {
data: this.field.data.dataSource[filterByTk],
},
};
}
async create(options) {
console.log('create', options);
const { values } = options;
this.field.data.dataSource.push(values);
this.field.data.changed = true;
}
async update(options) {
console.log('update', options);
const { filterByTk, values } = options;
this.field.data.dataSource[filterByTk] = values;
this.field.data.changed = true;
}
async destroy(options) {
console.log('destroy', options);
let { filterByTk } = options;
if (!Array.isArray(filterByTk)) {
filterByTk = [filterByTk];
}
this.field.data.dataSource = this.field.data.dataSource.filter((item, index) => {
return !filterByTk.includes(index);
});
this.field.data.changed = true;
}
}
export const WithoutTableFieldResource = createContext(null);
export const TableFieldProvider = (props) => {
return (
<WithoutTableFieldResource.Provider value={false}>
<BlockProvider name="table-field" block={'TableField'} {...props}>
<InternalTableFieldProvider {...props} />
</BlockProvider>
</WithoutTableFieldResource.Provider>
);
};
export const useTableFieldContext = () => {
return useContext(TableFieldContext);
};
export const useTableFieldProps = () => {
const field = useField<ArrayField>();
const ctx = useTableFieldContext();
useEffect(() => {
if (!ctx?.service?.loading) {
field.value = ctx?.service?.data?.data;
field.data = field.data || {};
field.data.selectedRowKeys = ctx?.field?.data?.selectedRowKeys;
}
}, [ctx?.service?.loading]);
return {
size: 'middle',
loading: ctx?.service?.loading,
showIndex: ctx.showIndex,
dragSort: ctx.dragSort,
pagination: false,
required: ctx?.fieldSchema?.parent?.required,
rowKey: (record: any) => {
return field.value?.indexOf?.(record);
},
onRowSelectionChange(selectedRowKeys) {
ctx.field.data = ctx?.field?.data || {};
ctx.field.data.selectedRowKeys = selectedRowKeys;
},
onChange({ current, pageSize }) {
ctx.service.run({ page: current, pageSize });
},
};
};