diff --git a/packages/core/client/src/block-provider/GanttBlockProvider.tsx b/packages/core/client/src/block-provider/GanttBlockProvider.tsx index f94e8d5ba..6a8d6acab 100644 --- a/packages/core/client/src/block-provider/GanttBlockProvider.tsx +++ b/packages/core/client/src/block-provider/GanttBlockProvider.tsx @@ -1,9 +1,9 @@ import { useField } from '@formily/react'; import React, { createContext, useContext, useEffect, useState } from 'react'; -import { BlockProvider, useBlockRequestContext } from './BlockProvider'; -import { TableBlockProvider } from './TableBlockProvider'; import { useACLRoleContext } from '../acl/ACLProvider'; import { useCollection } from '../collection-manager/hooks'; +import { BlockProvider, useBlockRequestContext } from './BlockProvider'; +import { TableBlockProvider } from './TableBlockProvider'; export const GanttBlockContext = createContext({}); @@ -13,15 +13,15 @@ const formatData = ( tasks: any[] = [], projectId: any = undefined, hideChildren = false, - checkPermassion?: Function, + checkPermassion?: (any) => boolean, ) => { data.forEach((item: any) => { const disable = checkPermassion(item); const percent = item[fieldNames.progress] * 100; if (item.children && item.children.length) { tasks.push({ - start: new Date(item[fieldNames.start]), - end: new Date(item[fieldNames.end]), + start: new Date(item[fieldNames.start] ?? undefined), + end: new Date(item[fieldNames.end] ?? undefined), name: item[fieldNames.title], id: item.id + '', type: 'project', diff --git a/packages/core/client/src/block-provider/TableBlockProvider.tsx b/packages/core/client/src/block-provider/TableBlockProvider.tsx index 8032c1c4b..642a73904 100644 --- a/packages/core/client/src/block-provider/TableBlockProvider.tsx +++ b/packages/core/client/src/block-provider/TableBlockProvider.tsx @@ -1,29 +1,50 @@ import { ArrayField, createForm } from '@formily/core'; import { FormContext, useField, useFieldSchema } from '@formily/react'; +import { boolean } from 'mathjs'; import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; import { useCollectionManager } from '../collection-manager'; import { useFilterBlock } from '../filter-provider/FilterProvider'; import { useRecord } from '../record-provider'; -import { FixedBlockWrapper, SchemaComponentOptions, removeNullCondition } from '../schema-component'; +import { FixedBlockWrapper, removeNullCondition, SchemaComponentOptions } from '../schema-component'; import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider'; -import { mergeFilter } from './SharedFilterProvider'; import { findFilterTargets } from './hooks'; +import { mergeFilter } from './SharedFilterProvider'; export const TableBlockContext = createContext({}); - +export function getIdsWithChildren(nodes) { + const ids = []; + if (nodes) { + for (const node of nodes) { + if (node?.children && node.children.length > 0) { + ids.push(node.id); + ids.push(...getIdsWithChildren(node?.children)); + } + } + } + return ids; +} interface Props { params?: any; showIndex?: boolean; dragSort?: boolean; rowKey?: string; childrenColumnName: any; + fieldNames?: any; } const InternalTableBlockProvider = (props: Props) => { - const { params, showIndex, dragSort, rowKey, childrenColumnName } = props; + const { params, showIndex, dragSort, rowKey, childrenColumnName, fieldNames } = props; const field: any = useField(); const { resource, service } = useBlockRequestContext(); - const [expandFlag, setExpandFlag] = useState(false); + const fieldSchema = useFieldSchema(); + const { treeTable } = fieldSchema?.['x-decorator-props'] || {}; + const [expandFlag, setExpandFlag] = useState(fieldNames ? true : false); + const allIncludesChildren = useMemo(() => { + if (treeTable !== false) { + const keys = getIdsWithChildren(service?.data?.data); + return keys || []; + } + }, [service?.loading]); return ( { rowKey, expandFlag, childrenColumnName, + allIncludesChildren, setExpandFlag: () => setExpandFlag(!expandFlag), }} > diff --git a/packages/core/client/src/schema-component/antd/gantt/components/gantt/gantt.tsx b/packages/core/client/src/schema-component/antd/gantt/components/gantt/gantt.tsx index 983f5ae81..5e520b4dd 100644 --- a/packages/core/client/src/schema-component/antd/gantt/components/gantt/gantt.tsx +++ b/packages/core/client/src/schema-component/antd/gantt/components/gantt/gantt.tsx @@ -133,7 +133,6 @@ export const Gantt: any = (props: any) => { useEffect(() => { tableCtx.field.onExpandClick = handleTableExpanderClick; tableCtx.field.onRowSelect = handleRowSelect; - tableCtx.setExpandFlag(true); }, []); useEffect(() => { expandAndCollapseAll?.(!expandFlag); diff --git a/packages/core/client/src/schema-component/antd/gantt/components/grid/grid-body.tsx b/packages/core/client/src/schema-component/antd/gantt/components/grid/grid-body.tsx index 60d149474..556ca4fc0 100644 --- a/packages/core/client/src/schema-component/antd/gantt/components/grid/grid-body.tsx +++ b/packages/core/client/src/schema-component/antd/gantt/components/grid/grid-body.tsx @@ -1,9 +1,9 @@ -import React, { ReactChild } from 'react'; import { cx } from '@emotion/css'; -import { Task } from '../../types/public-types'; -import { addToDate } from '../../helpers/date-helper'; -import { gridRowLine, gridRow, gridTick, gridHeightRow } from './style'; import { uid } from '@nocobase/utils/client'; +import React, { ReactChild } from 'react'; +import { addToDate } from '../../helpers/date-helper'; +import { Task } from '../../types/public-types'; +import { gridHeightRow, gridRow, gridRowLine, gridTick } from './style'; export type GridBodyProps = { tasks: Task[]; diff --git a/packages/core/client/src/schema-component/antd/gantt/components/task-item/bar/bar-small.tsx b/packages/core/client/src/schema-component/antd/gantt/components/task-item/bar/bar-small.tsx index 863bf26f6..22e19df5c 100644 --- a/packages/core/client/src/schema-component/antd/gantt/components/task-item/bar/bar-small.tsx +++ b/packages/core/client/src/schema-component/antd/gantt/components/task-item/bar/bar-small.tsx @@ -1,9 +1,9 @@ -import React from 'react'; import { cx } from '@emotion/css'; +import React from 'react'; import { getProgressPoint } from '../../../helpers/bar-helper'; +import { TaskItemProps } from '../task-item'; import { BarDisplay } from './bar-display'; import { BarProgressHandle } from './bar-progress-handle'; -import { TaskItemProps } from '../task-item'; import { barWrapper } from './style'; export const BarSmall: React.FC = ({ diff --git a/packages/core/client/src/schema-component/antd/gantt/components/task-item/task-item.tsx b/packages/core/client/src/schema-component/antd/gantt/components/task-item/task-item.tsx index 1017c3fd5..2c4655123 100644 --- a/packages/core/client/src/schema-component/antd/gantt/components/task-item/task-item.tsx +++ b/packages/core/client/src/schema-component/antd/gantt/components/task-item/task-item.tsx @@ -102,7 +102,9 @@ export const TaskItem: React.FC = (props) => { className={isProjectBar ? cx(projectLabel) : isTextInside ? cx(barLabel) : cx(barLabel) && cx(barLabelOutside)} ref={textRef} > - {isProjectBar ? `${task.name}: ${getYmd(task.start)} ~ ${getYmd(task.end)}` : task.name} + {isProjectBar && getYmd(task.start) && getYmd(task.end) + ? `${task.name}: ${getYmd(task.start)} ~ ${getYmd(task.end)}` + : task.name} ); diff --git a/packages/core/client/src/schema-component/antd/gantt/helpers/bar-helper.ts b/packages/core/client/src/schema-component/antd/gantt/helpers/bar-helper.ts index 43b07dc33..6ae2b24bd 100644 --- a/packages/core/client/src/schema-component/antd/gantt/helpers/bar-helper.ts +++ b/packages/core/client/src/schema-component/antd/gantt/helpers/bar-helper.ts @@ -1,6 +1,6 @@ -import { Task } from '../types/public-types'; import { BarTask, TaskTypeInternal } from '../types/bar-task'; import { BarMoveAction } from '../types/gantt-task-actions'; +import { Task } from '../types/public-types'; export const convertToBarTasks = ( tasks: Task[], @@ -161,7 +161,7 @@ const convertToBar = ( let typeInternal: TaskTypeInternal = task.type; if (typeInternal === 'task' && x2 - x1 < handleWidth * 2) { typeInternal = 'smalltask'; - x2 = x1 + handleWidth * 2; + x2 = x1 > 0 ? x1 + handleWidth * 2 : x1; } const [progressWidth, progressX] = progressWithByParams(x1, x2, task.progress, rtl); @@ -244,20 +244,19 @@ const convertToMilestone = ( const taskXCoordinate = (xDate: Date, dates: Date[], columnWidth: number) => { const index = dates.findIndex((d) => d?.getTime() >= xDate?.getTime()) - 1; - const remainderMillis = xDate?.getTime() - dates[index]?.getTime(); const percentOfInterval = remainderMillis / (dates[index + 1]?.getTime() - dates[index]?.getTime()); const x = index * columnWidth + percentOfInterval * columnWidth; - return x; + return isNaN(x) ? 0 : x; }; const taskXCoordinateRTL = (xDate: Date, dates: Date[], columnWidth: number) => { let x = taskXCoordinate(xDate, dates, columnWidth); x += columnWidth; - return x; + return isNaN(x) ? 0 : x; }; const taskYCoordinate = (index: number, rowHeight: number, taskHeight: number) => { const y = index * rowHeight + (rowHeight - taskHeight) / 2; - return y; + return isNaN(y) ? 0 : y; }; export const progressWithByParams = (taskX1: number, taskX2: number, progress: number, rtl: boolean) => { diff --git a/packages/core/client/src/schema-component/antd/gantt/helpers/other-helper.ts b/packages/core/client/src/schema-component/antd/gantt/helpers/other-helper.ts index 5f475549d..b01206c1b 100644 --- a/packages/core/client/src/schema-component/antd/gantt/helpers/other-helper.ts +++ b/packages/core/client/src/schema-component/antd/gantt/helpers/other-helper.ts @@ -57,5 +57,7 @@ export const sortTasks = (taskA: Task, taskB: Task) => { }; export const getYmd = (date: Date) => { - return date.getFullYear() + '/' + `${date.getMonth() + 1}` + '/' + date.getDate(); + if (!isNaN(date.getTime())) { + return date.getFullYear() + '/' + `${date.getMonth() + 1}` + '/' + date.getDate(); + } }; diff --git a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx index 9bd5a8a80..9c14fb7b6 100644 --- a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx +++ b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx @@ -3,7 +3,7 @@ import { SortableContext, useSortable } from '@dnd-kit/sortable'; import { css } from '@emotion/css'; import { ArrayField, Field } from '@formily/core'; import { spliceArrayState } from '@formily/core/esm/shared/internals'; -import { RecursionField, Schema, observer, useField, useFieldSchema } from '@formily/react'; +import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; import { action, reaction } from '@formily/reactive'; import { useMemoizedFn } from 'ahooks'; import { Table as AntdTable, TableColumnProps } from 'antd'; @@ -19,7 +19,7 @@ import { useTableSelectorContext, } from '../../../'; import { useACLFieldWhitelist } from '../../../acl/ACLProvider'; -import { extractIndex, getIdsWithChildren, isCollectionFieldComponent, isColumnComponent } from './utils'; +import { extractIndex, isCollectionFieldComponent, isColumnComponent } from './utils'; const useArrayField = (props) => { const field = useField(); @@ -213,18 +213,14 @@ export const Table: any = observer( const schema = useFieldSchema(); const isTableSelector = schema?.parent?.['x-decorator'] === 'TableSelectorProvider'; const ctx = isTableSelector ? useTableSelectorContext() : useTableBlockContext(); - const { expandFlag } = ctx; + const { expandFlag, allIncludesChildren } = ctx; const onRowDragEnd = useMemoizedFn(others.onRowDragEnd || (() => {})); const paginationProps = usePaginationProps(pagination1, pagination2); - // const requiredValidator = field.required || required; - const { treeTable } = schema?.parent?.['x-decorator-props'] || {}; const [expandedKeys, setExpandesKeys] = useState([]); - const [allIncludesChildren, setAllIncludesChildren] = useState([]); const [selectedRowKeys, setSelectedRowKeys] = useState(field?.data?.selectedRowKeys || []); const [selectedRow, setSelectedRow] = useState([]); const dataSource = field?.value?.slice?.()?.filter?.(Boolean) || []; const isRowSelect = rowSelection?.type !== 'none'; - let onRow = null, highlightRow = ''; @@ -244,21 +240,6 @@ export const Table: any = observer( `; } - // useEffect(() => { - // field.setValidator((value) => { - // if (requiredValidator) { - // return Array.isArray(value) && value.length > 0 ? null : 'The field value is required'; - // } - // return; - // }); - // }, [requiredValidator]); - - useEffect(() => { - if (treeTable !== false) { - const keys = getIdsWithChildren(field.value?.slice?.()); - setAllIncludesChildren(keys); - } - }, [field.value]); useEffect(() => { if (expandFlag) { setExpandesKeys(allIncludesChildren); diff --git a/packages/core/client/src/schema-component/antd/table-v2/utils.ts b/packages/core/client/src/schema-component/antd/table-v2/utils.ts index 9d4efeae6..d0153bf4a 100644 --- a/packages/core/client/src/schema-component/antd/table-v2/utils.ts +++ b/packages/core/client/src/schema-component/antd/table-v2/utils.ts @@ -17,16 +17,3 @@ export function extractIndex(str) { }); return numbers.join('.'); } - -export function getIdsWithChildren(nodes) { - const ids = []; - if (nodes) { - for (const node of nodes) { - if (node?.children && node.children.length > 0) { - ids.push(node.id); - ids.push(...getIdsWithChildren(node?.children)); - } - } - } - return ids; -}