fix: tree gantt block does not display correctly (#2123)
* fix: tree gantt block display error * fix: tree gantt block display error * refactor: code improve * refactor: code improve
This commit is contained in:
parent
6d80593f27
commit
f042a2307a
@ -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<any>({});
|
||||
|
||||
@ -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',
|
||||
|
@ -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<any>({});
|
||||
|
||||
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 (
|
||||
<FixedBlockWrapper>
|
||||
<TableBlockContext.Provider
|
||||
@ -37,6 +58,7 @@ const InternalTableBlockProvider = (props: Props) => {
|
||||
rowKey,
|
||||
expandFlag,
|
||||
childrenColumnName,
|
||||
allIncludesChildren,
|
||||
setExpandFlag: () => setExpandFlag(!expandFlag),
|
||||
}}
|
||||
>
|
||||
|
@ -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);
|
||||
|
@ -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[];
|
||||
|
@ -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<TaskItemProps> = ({
|
||||
|
@ -102,7 +102,9 @@ export const TaskItem: React.FC<TaskItemProps> = (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}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
|
@ -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) => {
|
||||
|
@ -57,5 +57,7 @@ export const sortTasks = (taskA: Task, taskB: Task) => {
|
||||
};
|
||||
|
||||
export const getYmd = (date: Date) => {
|
||||
if (!isNaN(date.getTime())) {
|
||||
return date.getFullYear() + '/' + `${date.getMonth() + 1}` + '/' + date.getDate();
|
||||
}
|
||||
};
|
||||
|
@ -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<ArrayField>();
|
||||
@ -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<any[]>(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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user