GanttView düzenlemeleri
This commit is contained in:
parent
55793e3db0
commit
9988cd11b0
10 changed files with 335 additions and 65 deletions
|
|
@ -76,6 +76,10 @@ public class GanttOptionDto
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowTaskUpdating { get; set; } = false;
|
public bool AllowTaskUpdating { get; set; } = false;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Task kaynaklarının güncellenmesine izin verilsin mi
|
||||||
|
/// </summary>
|
||||||
|
public bool AllowTaskResourceUpdating { get; set; } = false;
|
||||||
|
/// <summary>
|
||||||
/// Task silmeye izin verilsin mi
|
/// Task silmeye izin verilsin mi
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowTaskDeleting { get; set; } = false;
|
public bool AllowTaskDeleting { get; set; } = false;
|
||||||
|
|
@ -94,6 +98,11 @@ public class GanttOptionDto
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowResourceAdding { get; set; } = false;
|
public bool AllowResourceAdding { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kaynak güncellemeye izin verilsin mi
|
||||||
|
/// </summary>
|
||||||
|
public bool AllowResourceUpdating { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kaynaklar için kullanılan field adı (örn: "resources")
|
/// Kaynaklar için kullanılan field adı (örn: "resources")
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -5562,6 +5562,12 @@
|
||||||
"en": "Allow Task Updating",
|
"en": "Allow Task Updating",
|
||||||
"tr": "Görev Güncelleme İzni"
|
"tr": "Görev Güncelleme İzni"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "ListForms.ListFormEdit.AllowTaskResourceUpdating",
|
||||||
|
"en": "Allow Task Resource Updating",
|
||||||
|
"tr": "Görev Kaynaklarını Güncelleme İzni"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "ListForms.ListFormEdit.AllowDependencyAdding",
|
"key": "ListForms.ListFormEdit.AllowDependencyAdding",
|
||||||
|
|
@ -5580,6 +5586,12 @@
|
||||||
"en": "Allow Resource Adding",
|
"en": "Allow Resource Adding",
|
||||||
"tr": "Kaynak Ekleme İzni"
|
"tr": "Kaynak Ekleme İzni"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "ListForms.ListFormEdit.AllowResourceUpdating",
|
||||||
|
"en": "Allow Resource Updating",
|
||||||
|
"tr": "Kaynak Güncelleme İzni"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "ListForms.ListFormEdit.AllowResourceDeleting",
|
"key": "ListForms.ListFormEdit.AllowResourceDeleting",
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,8 @@ div.dialog-after-open > div.dialog-content.maximized {
|
||||||
}
|
}
|
||||||
|
|
||||||
.dx-datagrid-header-panel > .dx-toolbar .dx-toolbar-after .dx-button-text,
|
.dx-datagrid-header-panel > .dx-toolbar .dx-toolbar-after .dx-button-text,
|
||||||
.dx-treelist-header-panel > .dx-toolbar .dx-toolbar-after .dx-button-text {
|
.dx-treelist-header-panel > .dx-toolbar .dx-toolbar-after .dx-button-text,
|
||||||
|
.dx-gantt-toolbar-wrapper .dx-button-text {
|
||||||
text-transform: none !important;
|
text-transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -420,10 +420,12 @@ export interface GanttOptionDto {
|
||||||
allowEditing?: boolean
|
allowEditing?: boolean
|
||||||
allowTaskAdding?: boolean
|
allowTaskAdding?: boolean
|
||||||
allowTaskUpdating?: boolean
|
allowTaskUpdating?: boolean
|
||||||
|
allowTaskResourceUpdating?: boolean
|
||||||
allowTaskDeleting?: boolean
|
allowTaskDeleting?: boolean
|
||||||
allowDependencyAdding?: boolean
|
allowDependencyAdding?: boolean
|
||||||
allowDependencyDeleting?: boolean
|
allowDependencyDeleting?: boolean
|
||||||
allowResourceAdding?: boolean
|
allowResourceAdding?: boolean
|
||||||
|
allowResourceUpdating?: boolean
|
||||||
allowResourceDeleting?: boolean
|
allowResourceDeleting?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -361,21 +361,6 @@ function FormTabGantt(props: FormEditProps) {
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<FormItem
|
|
||||||
label={translate('::ListForms.ListFormEdit.AllowTaskAdding')}
|
|
||||||
invalid={
|
|
||||||
errors.ganttOptionDto?.allowTaskAdding &&
|
|
||||||
touched.ganttOptionDto?.allowTaskAdding
|
|
||||||
}
|
|
||||||
errorMessage={errors.ganttOptionDto?.allowTaskAdding}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="ganttOptionDto.allowTaskAdding"
|
|
||||||
placeholder={translate('::ListForms.ListFormEdit.AllowTaskAdding')}
|
|
||||||
component={Checkbox}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label={translate('::ListForms.ListFormEdit.AllowTaskUpdating')}
|
label={translate('::ListForms.ListFormEdit.AllowTaskUpdating')}
|
||||||
invalid={
|
invalid={
|
||||||
|
|
@ -391,22 +376,6 @@ function FormTabGantt(props: FormEditProps) {
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<FormItem
|
|
||||||
label={translate('::ListForms.ListFormEdit.AllowTaskDeleting')}
|
|
||||||
invalid={
|
|
||||||
errors.ganttOptionDto?.allowTaskDeleting &&
|
|
||||||
touched.ganttOptionDto?.allowTaskDeleting
|
|
||||||
}
|
|
||||||
errorMessage={errors.ganttOptionDto?.allowTaskDeleting}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="ganttOptionDto.allowTaskDeleting"
|
|
||||||
placeholder={translate('::ListForms.ListFormEdit.AllowTaskDeleting')}
|
|
||||||
component={Checkbox}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label={translate('::ListForms.ListFormEdit.AllowDependencyAdding')}
|
label={translate('::ListForms.ListFormEdit.AllowDependencyAdding')}
|
||||||
invalid={
|
invalid={
|
||||||
|
|
@ -422,21 +391,6 @@ function FormTabGantt(props: FormEditProps) {
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
<FormItem
|
|
||||||
label={translate('::ListForms.ListFormEdit.AllowDependencyDeleting')}
|
|
||||||
invalid={
|
|
||||||
errors.ganttOptionDto?.allowDependencyDeleting &&
|
|
||||||
touched.ganttOptionDto?.allowDependencyDeleting
|
|
||||||
}
|
|
||||||
errorMessage={errors.ganttOptionDto?.allowDependencyDeleting}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="ganttOptionDto.allowDependencyDeleting"
|
|
||||||
placeholder={translate('::ListForms.ListFormEdit.AllowDependencyDeleting')}
|
|
||||||
component={Checkbox}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label={translate('::ListForms.ListFormEdit.AllowResourceAdding')}
|
label={translate('::ListForms.ListFormEdit.AllowResourceAdding')}
|
||||||
invalid={
|
invalid={
|
||||||
|
|
@ -467,11 +421,96 @@ function FormTabGantt(props: FormEditProps) {
|
||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormEdit.AllowTaskAdding')}
|
||||||
|
invalid={
|
||||||
|
errors.ganttOptionDto?.allowTaskAdding &&
|
||||||
|
touched.ganttOptionDto?.allowTaskAdding
|
||||||
|
}
|
||||||
|
errorMessage={errors.ganttOptionDto?.allowTaskAdding}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name="ganttOptionDto.allowTaskAdding"
|
||||||
|
placeholder={translate('::ListForms.ListFormEdit.AllowTaskAdding')}
|
||||||
|
component={Checkbox}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormEdit.AllowTaskDeleting')}
|
||||||
|
invalid={
|
||||||
|
errors.ganttOptionDto?.allowTaskDeleting &&
|
||||||
|
touched.ganttOptionDto?.allowTaskDeleting
|
||||||
|
}
|
||||||
|
errorMessage={errors.ganttOptionDto?.allowTaskDeleting}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name="ganttOptionDto.allowTaskDeleting"
|
||||||
|
placeholder={translate('::ListForms.ListFormEdit.AllowTaskDeleting')}
|
||||||
|
component={Checkbox}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormEdit.AllowDependencyDeleting')}
|
||||||
|
invalid={
|
||||||
|
errors.ganttOptionDto?.allowDependencyDeleting &&
|
||||||
|
touched.ganttOptionDto?.allowDependencyDeleting
|
||||||
|
}
|
||||||
|
errorMessage={errors.ganttOptionDto?.allowDependencyDeleting}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name="ganttOptionDto.allowDependencyDeleting"
|
||||||
|
placeholder={translate('::ListForms.ListFormEdit.AllowDependencyDeleting')}
|
||||||
|
component={Checkbox}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormEdit.AllowResourceUpdating')}
|
||||||
|
invalid={
|
||||||
|
errors.ganttOptionDto?.allowResourceUpdating &&
|
||||||
|
touched.ganttOptionDto?.allowResourceUpdating
|
||||||
|
}
|
||||||
|
errorMessage={errors.ganttOptionDto?.allowResourceUpdating}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name="ganttOptionDto.allowResourceUpdating"
|
||||||
|
placeholder={translate('::ListForms.ListFormEdit.AllowResourceUpdating')}
|
||||||
|
component={Checkbox}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormEdit.AllowTaskResourceUpdating')}
|
||||||
|
invalid={
|
||||||
|
errors.ganttOptionDto?.allowTaskResourceUpdating &&
|
||||||
|
touched.ganttOptionDto?.allowTaskResourceUpdating
|
||||||
|
}
|
||||||
|
errorMessage={errors.ganttOptionDto?.allowTaskResourceUpdating}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name="ganttOptionDto.allowTaskResourceUpdating"
|
||||||
|
placeholder={translate(
|
||||||
|
'::ListForms.ListFormEdit.AllowTaskResourceUpdating',
|
||||||
|
)}
|
||||||
|
component={Checkbox}
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button block size="sm" variant="solid" loading={isSubmitting} type="submit" className="my-2">
|
<Button
|
||||||
|
block
|
||||||
|
size="sm"
|
||||||
|
variant="solid"
|
||||||
|
loading={isSubmitting}
|
||||||
|
type="submit"
|
||||||
|
className="my-2"
|
||||||
|
>
|
||||||
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
{isSubmitting ? translate('::Saving') : translate('::Save')}
|
||||||
</Button>
|
</Button>
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,12 @@ const initialValues: ListFormWizardDto = {
|
||||||
allowEditing: false,
|
allowEditing: false,
|
||||||
allowTaskAdding: false,
|
allowTaskAdding: false,
|
||||||
allowTaskUpdating: false,
|
allowTaskUpdating: false,
|
||||||
|
allowTaskResourceUpdating: false,
|
||||||
allowTaskDeleting: false,
|
allowTaskDeleting: false,
|
||||||
allowDependencyAdding: false,
|
allowDependencyAdding: false,
|
||||||
allowDependencyDeleting: false,
|
allowDependencyDeleting: false,
|
||||||
allowResourceAdding: false,
|
allowResourceAdding: false,
|
||||||
|
allowResourceUpdating: false,
|
||||||
allowResourceDeleting: false,
|
allowResourceDeleting: false,
|
||||||
},
|
},
|
||||||
schedulerOptionDto: {
|
schedulerOptionDto: {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ const WizardStep9 = ({ selectCommandColumns, translate, onBack, onNext }: Wizard
|
||||||
['allowDependencyAdding', '::ListForms.ListFormEdit.AllowDependencyAdding'],
|
['allowDependencyAdding', '::ListForms.ListFormEdit.AllowDependencyAdding'],
|
||||||
['allowDependencyDeleting', '::ListForms.ListFormEdit.AllowDependencyDeleting'],
|
['allowDependencyDeleting', '::ListForms.ListFormEdit.AllowDependencyDeleting'],
|
||||||
['allowResourceAdding', '::ListForms.ListFormEdit.AllowResourceAdding'],
|
['allowResourceAdding', '::ListForms.ListFormEdit.AllowResourceAdding'],
|
||||||
|
['allowResourceUpdating', '::ListForms.ListFormEdit.AllowResourceUpdating'],
|
||||||
['allowResourceDeleting', '::ListForms.ListFormEdit.AllowResourceDeleting'],
|
['allowResourceDeleting', '::ListForms.ListFormEdit.AllowResourceDeleting'],
|
||||||
|
['allowTaskResourceUpdating', '::ListForms.ListFormEdit.AllowTaskResourceUpdating'],
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -382,15 +382,6 @@ const GANTT_COLUMNS: ColumnDefinition[] = [
|
||||||
defaultValue: 'NEWID()',
|
defaultValue: 'NEWID()',
|
||||||
description: 'Gantt task primary key',
|
description: 'Gantt task primary key',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: '__GanttParentId',
|
|
||||||
columnName: 'ParentId',
|
|
||||||
dataType: 'uniqueidentifier',
|
|
||||||
maxLength: '',
|
|
||||||
isNullable: true,
|
|
||||||
defaultValue: '',
|
|
||||||
description: 'Parent Gantt task ID',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: '__GanttTitle',
|
id: '__GanttTitle',
|
||||||
columnName: 'Title',
|
columnName: 'Title',
|
||||||
|
|
@ -400,6 +391,15 @@ const GANTT_COLUMNS: ColumnDefinition[] = [
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
description: 'Gantt task title',
|
description: 'Gantt task title',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '__GanttParentId',
|
||||||
|
columnName: 'ParentId',
|
||||||
|
dataType: 'uniqueidentifier',
|
||||||
|
maxLength: '',
|
||||||
|
isNullable: true,
|
||||||
|
defaultValue: '',
|
||||||
|
description: 'Parent Gantt task ID',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: '__GanttStartDate',
|
id: '__GanttStartDate',
|
||||||
columnName: 'StartDate',
|
columnName: 'StartDate',
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import Container from '@/components/shared/Container'
|
import Container from '@/components/shared/Container'
|
||||||
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
|
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
|
||||||
import { GridDto } from '@/proxy/form/models'
|
import { GridDto, ListFormCustomizationTypeEnum } from '@/proxy/form/models'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import Gantt, {
|
import Gantt, {
|
||||||
Column,
|
Column,
|
||||||
|
|
@ -24,12 +24,24 @@ import { layoutTypes } from '../admin/listForm/edit/types'
|
||||||
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
|
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { usePWA } from '@/utils/hooks/usePWA'
|
import { usePWA } from '@/utils/hooks/usePWA'
|
||||||
import type { GanttScaleType } from 'devextreme/ui/gantt'
|
import type { ContentReadyEvent, GanttScaleType } from 'devextreme/ui/gantt'
|
||||||
import { useListFormColumns } from './useListFormColumns'
|
import { useListFormColumns } from './useListFormColumns'
|
||||||
import CustomStore from 'devextreme/data/custom_store'
|
import CustomStore from 'devextreme/data/custom_store'
|
||||||
import { GridColumnData } from './GridColumnData'
|
import { GridColumnData } from './GridColumnData'
|
||||||
import { Loading } from '@/components/shared'
|
import { Loading } from '@/components/shared'
|
||||||
import { usePermission } from '@/utils/hooks/usePermission'
|
import { usePermission } from '@/utils/hooks/usePermission'
|
||||||
|
import { useListFormStateStoring } from './useListFormStateStoring'
|
||||||
|
import TreeList from 'devextreme/ui/tree_list'
|
||||||
|
import { postListFormCustomization } from '@/services/list-form-customization.service'
|
||||||
|
import { useFilters } from './useFilters'
|
||||||
|
import GridFilterDialogs from './GridFilterDialogs'
|
||||||
|
|
||||||
|
type GanttInstance = ReturnType<GanttRef['instance']>
|
||||||
|
|
||||||
|
const getGanttTreeList = (gantt: GanttInstance) => {
|
||||||
|
const element = (gantt.element() as HTMLElement).querySelector('.dx-treelist')
|
||||||
|
return element ? TreeList.getInstance(element as HTMLElement) : undefined
|
||||||
|
}
|
||||||
|
|
||||||
interface GanttViewProps {
|
interface GanttViewProps {
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
|
|
@ -55,7 +67,30 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
const [gridDto, setGridDto] = useState<GridDto>()
|
const [gridDto, setGridDto] = useState<GridDto>()
|
||||||
const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
|
const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
|
||||||
const [scaleType, setScaleType] = useState<GanttScaleType>('weeks')
|
const [scaleType, setScaleType] = useState<GanttScaleType>('weeks')
|
||||||
|
const [taskListWidth, setTaskListWidth] = useState(500)
|
||||||
const layout = layoutTypes.gantt || 'gantt'
|
const layout = layoutTypes.gantt || 'gantt'
|
||||||
|
const pendingStateRef = useRef<Record<string, any>>()
|
||||||
|
const loadedStateKeyRef = useRef('')
|
||||||
|
|
||||||
|
const { customSaveState, customLoadState, storageKey } = useListFormStateStoring({
|
||||||
|
listFormCode,
|
||||||
|
storageKey: gridDto?.gridOptions.stateStoringDto?.storageKey,
|
||||||
|
filterPrefix: 'gantt',
|
||||||
|
})
|
||||||
|
const ganttFilterRef = useRef<any>({
|
||||||
|
instance: () => {
|
||||||
|
const gantt = gridRef.current?.instance()
|
||||||
|
return gantt ? getGanttTreeList(gantt) : undefined
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const { filterToolbarData, ...filterData } = useFilters({
|
||||||
|
gridDto,
|
||||||
|
gridRef: ganttFilterRef,
|
||||||
|
listFormCode,
|
||||||
|
})
|
||||||
|
const ganttFilterToolbarData = filterToolbarData.filter((item) =>
|
||||||
|
['saveActiveFilter', 'deleteFilter', 'clearFilter'].includes(item.name ?? ''),
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeGantt = async () => {
|
const initializeGantt = async () => {
|
||||||
|
|
@ -92,7 +127,6 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
isSubForm,
|
isSubForm,
|
||||||
gridRef,
|
gridRef,
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gridDto) {
|
if (!gridDto) {
|
||||||
return
|
return
|
||||||
|
|
@ -164,12 +198,14 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
const getSettingButtonOptions = useCallback(
|
const getSettingButtonOptions = useCallback(
|
||||||
() => ({
|
() => ({
|
||||||
icon: 'preferences',
|
icon: 'preferences',
|
||||||
|
text: translate('::ListForms.ListForm.Manage'),
|
||||||
|
hint: translate('::ListForms.ListForm.Manage'),
|
||||||
stylingMode: 'icon',
|
stylingMode: 'icon',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
settingButtonClick()
|
settingButtonClick()
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[settingButtonClick],
|
[settingButtonClick, translate],
|
||||||
)
|
)
|
||||||
|
|
||||||
const getRefreshButtonOptions = useCallback(
|
const getRefreshButtonOptions = useCallback(
|
||||||
|
|
@ -184,6 +220,124 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
[settingButtonClick],
|
[settingButtonClick],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const getCurrentState = useCallback((gantt: GanttInstance) => {
|
||||||
|
const treeList = getGanttTreeList(gantt)
|
||||||
|
const state = (treeList?.state() ?? {}) as Record<string, any>
|
||||||
|
const visibleColumns = (treeList?.getVisibleColumns() ?? []) as Array<Record<string, any>>
|
||||||
|
const headerCells = Array.from(
|
||||||
|
(treeList?.element() as HTMLElement | undefined)?.querySelectorAll('.dx-header-row > td') ??
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
const widths = new Map(
|
||||||
|
visibleColumns.map((column, index) => [
|
||||||
|
column.dataField,
|
||||||
|
headerCells[index]?.getBoundingClientRect().width,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
const taskListElement = (gantt.element() as HTMLElement).querySelector(
|
||||||
|
'.dx-gantt-treelist-wrapper',
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
columns: state.columns?.map((column: Record<string, any>) => {
|
||||||
|
const width = widths.get(column.dataField)
|
||||||
|
return width ? { ...column, width: Math.round(width) } : column
|
||||||
|
}),
|
||||||
|
scaleType: gantt.option('scaleType'),
|
||||||
|
showDependencies: gantt.option('showDependencies'),
|
||||||
|
showResources: gantt.option('showResources'),
|
||||||
|
taskListWidth: Math.round(
|
||||||
|
taskListElement?.getBoundingClientRect().width ?? gantt.option('taskListWidth'),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const applyState = useCallback((gantt: GanttInstance, state: Record<string, any>) => {
|
||||||
|
const treeList = getGanttTreeList(gantt)
|
||||||
|
if (!treeList) return
|
||||||
|
|
||||||
|
const {
|
||||||
|
scaleType: savedScaleType,
|
||||||
|
showDependencies,
|
||||||
|
showResources,
|
||||||
|
taskListWidth: savedTaskListWidth,
|
||||||
|
treeListState,
|
||||||
|
...treeState
|
||||||
|
} = state
|
||||||
|
|
||||||
|
treeList.state(treeListState ?? treeState)
|
||||||
|
if (savedScaleType) setScaleType(savedScaleType)
|
||||||
|
if (savedTaskListWidth) setTaskListWidth(savedTaskListWidth)
|
||||||
|
gantt.option({
|
||||||
|
...(showDependencies !== undefined ? { showDependencies } : {}),
|
||||||
|
...(showResources !== undefined ? { showResources } : {}),
|
||||||
|
...(savedTaskListWidth ? { taskListWidth: savedTaskListWidth } : {}),
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleGanttContentReady = useCallback(
|
||||||
|
(event: ContentReadyEvent) => {
|
||||||
|
if (!pendingStateRef.current) return
|
||||||
|
|
||||||
|
const state = pendingStateRef.current
|
||||||
|
pendingStateRef.current = undefined
|
||||||
|
requestAnimationFrame(() => requestAnimationFrame(() => applyState(event.component, state)))
|
||||||
|
},
|
||||||
|
[applyState],
|
||||||
|
)
|
||||||
|
|
||||||
|
const saveGanttState = useCallback(() => {
|
||||||
|
const gantt = gridRef.current?.instance()
|
||||||
|
if (gantt) customSaveState(getCurrentState(gantt)).catch(() => undefined)
|
||||||
|
}, [customSaveState, getCurrentState])
|
||||||
|
|
||||||
|
const resetGanttState = useCallback(async () => {
|
||||||
|
const gantt = gridRef.current?.instance()
|
||||||
|
if (!gantt || !storageKey) return
|
||||||
|
|
||||||
|
await postListFormCustomization({
|
||||||
|
listFormCode,
|
||||||
|
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||||
|
filterName: `gantt-${storageKey}`,
|
||||||
|
customizationData: '',
|
||||||
|
})
|
||||||
|
getGanttTreeList(gantt)?.state(null)
|
||||||
|
setTaskListWidth(500)
|
||||||
|
}, [listFormCode, storageKey])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
!gridDto?.gridOptions.stateStoringDto?.enabled ||
|
||||||
|
!ganttDataSource ||
|
||||||
|
!columnData ||
|
||||||
|
!storageKey
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
const key = `${listFormCode}-${storageKey}`
|
||||||
|
if (loadedStateKeyRef.current === key) return
|
||||||
|
loadedStateKeyRef.current = key
|
||||||
|
|
||||||
|
customLoadState()
|
||||||
|
.then((state) => {
|
||||||
|
pendingStateRef.current = state ?? undefined
|
||||||
|
const gantt = gridRef.current?.instance()
|
||||||
|
if (gantt && state) handleGanttContentReady({ component: gantt } as ContentReadyEvent)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadedStateKeyRef.current = ''
|
||||||
|
})
|
||||||
|
}, [
|
||||||
|
columnData,
|
||||||
|
customLoadState,
|
||||||
|
ganttDataSource,
|
||||||
|
gridDto,
|
||||||
|
handleGanttContentReady,
|
||||||
|
listFormCode,
|
||||||
|
storageKey,
|
||||||
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
|
<div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
|
||||||
|
|
@ -217,7 +371,7 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
ref={gridRef as any}
|
ref={gridRef as any}
|
||||||
key={`Gantt-${listFormCode}-${ganttDataSource ? 'loaded' : 'loading'}`}
|
key={`Gantt-${listFormCode}-${ganttDataSource ? 'loaded' : 'loading'}`}
|
||||||
id={'Gantt-' + listFormCode}
|
id={'Gantt-' + listFormCode}
|
||||||
taskListWidth={500}
|
taskListWidth={taskListWidth}
|
||||||
scaleType={scaleType}
|
scaleType={scaleType}
|
||||||
rootValue={
|
rootValue={
|
||||||
gridDto.gridOptions.ganttOptionDto?.rootValue === '' ||
|
gridDto.gridOptions.ganttOptionDto?.rootValue === '' ||
|
||||||
|
|
@ -232,6 +386,7 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
? `calc(100vh - ${170 + widgetGroupHeight}px)`
|
? `calc(100vh - ${170 + widgetGroupHeight}px)`
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
onContentReady={handleGanttContentReady}
|
||||||
>
|
>
|
||||||
<Tasks
|
<Tasks
|
||||||
dataSource={ganttDataSource}
|
dataSource={ganttDataSource}
|
||||||
|
|
@ -288,6 +443,45 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
showText="always"
|
showText="always"
|
||||||
options={getRefreshButtonOptions()}
|
options={getRefreshButtonOptions()}
|
||||||
/>
|
/>
|
||||||
|
{ganttFilterToolbarData.map((item) => (
|
||||||
|
<Item
|
||||||
|
key={item.name}
|
||||||
|
name={item.name}
|
||||||
|
location="after"
|
||||||
|
widget="dxButton"
|
||||||
|
locateInMenu="never"
|
||||||
|
showText="always"
|
||||||
|
options={item.options}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{gridDto.gridOptions.stateStoringDto?.enabled && (
|
||||||
|
<Item
|
||||||
|
location="after"
|
||||||
|
widget="dxButton"
|
||||||
|
locateInMenu="auto"
|
||||||
|
showText="always"
|
||||||
|
options={{
|
||||||
|
icon: 'save',
|
||||||
|
text: translate('::ListForms.ListForm.SaveGridState'),
|
||||||
|
hint: translate('::ListForms.ListForm.SaveGridState'),
|
||||||
|
onClick: saveGanttState,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{gridDto.gridOptions.stateStoringDto?.enabled && (
|
||||||
|
<Item
|
||||||
|
location="after"
|
||||||
|
widget="dxButton"
|
||||||
|
locateInMenu="auto"
|
||||||
|
showText="always"
|
||||||
|
options={{
|
||||||
|
icon: 'revert',
|
||||||
|
text: translate('::ListForms.ListForm.ResetGridState'),
|
||||||
|
hint: translate('::ListForms.ListForm.ResetGridState'),
|
||||||
|
onClick: resetGanttState,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{checkPermission('App.Listforms.Listform.Update') && (
|
{checkPermission('App.Listforms.Listform.Update') && (
|
||||||
<Item
|
<Item
|
||||||
location="after"
|
location="after"
|
||||||
|
|
@ -298,20 +492,24 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
<Editing
|
<Editing
|
||||||
enabled={gridDto.gridOptions.ganttOptionDto?.allowEditing}
|
enabled={gridDto.gridOptions.ganttOptionDto?.allowEditing}
|
||||||
allowTaskAdding={gridDto.gridOptions.ganttOptionDto?.allowTaskAdding}
|
allowTaskAdding={gridDto.gridOptions.ganttOptionDto?.allowTaskAdding}
|
||||||
allowTaskUpdating={gridDto.gridOptions.ganttOptionDto?.allowTaskUpdating}
|
allowTaskUpdating={gridDto.gridOptions.ganttOptionDto?.allowTaskUpdating}
|
||||||
allowTaskDeleting={gridDto.gridOptions.ganttOptionDto?.allowTaskDeleting}
|
allowTaskDeleting={gridDto.gridOptions.ganttOptionDto?.allowTaskDeleting}
|
||||||
|
allowTaskResourceUpdating={
|
||||||
|
gridDto.gridOptions.ganttOptionDto?.allowTaskResourceUpdating
|
||||||
|
}
|
||||||
allowDependencyAdding={gridDto.gridOptions.ganttOptionDto?.allowDependencyAdding}
|
allowDependencyAdding={gridDto.gridOptions.ganttOptionDto?.allowDependencyAdding}
|
||||||
allowDependencyDeleting={
|
allowDependencyDeleting={
|
||||||
gridDto.gridOptions.ganttOptionDto?.allowDependencyDeleting
|
gridDto.gridOptions.ganttOptionDto?.allowDependencyDeleting
|
||||||
}
|
}
|
||||||
allowResourceAdding={gridDto.gridOptions.ganttOptionDto?.allowResourceAdding}
|
allowResourceAdding={gridDto.gridOptions.ganttOptionDto?.allowResourceAdding}
|
||||||
allowResourceDeleting={gridDto.gridOptions.ganttOptionDto?.allowResourceDeleting}
|
allowResourceDeleting={gridDto.gridOptions.ganttOptionDto?.allowResourceDeleting}
|
||||||
|
allowResourceUpdating={gridDto.gridOptions.ganttOptionDto?.allowResourceUpdating}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FilterRow visible={gridDto.gridOptions.filterRowDto?.visible}></FilterRow>
|
<FilterRow visible={gridDto.gridOptions.filterRowDto?.visible}></FilterRow>
|
||||||
<HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
|
<HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
|
||||||
<Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
|
<Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
|
||||||
|
|
@ -324,6 +522,11 @@ const GanttView = (props: GanttViewProps) => {
|
||||||
<Column key={col.dataField} {...col} />
|
<Column key={col.dataField} {...col} />
|
||||||
))}
|
))}
|
||||||
</Gantt>
|
</Gantt>
|
||||||
|
<GridFilterDialogs
|
||||||
|
gridRef={ganttFilterRef}
|
||||||
|
listFormCode={listFormCode}
|
||||||
|
{...filterData}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type PendingSave = {
|
||||||
type UseListFormStateStoringParams = {
|
type UseListFormStateStoringParams = {
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
storageKey?: string | null
|
storageKey?: string | null
|
||||||
filterPrefix: 'list' | 'tree' | 'pivot' | 'todo'
|
filterPrefix: 'list' | 'tree' | 'pivot' | 'todo' | 'gantt'
|
||||||
skipSaveRef?: MutableRefObject<boolean>
|
skipSaveRef?: MutableRefObject<boolean>
|
||||||
showSaveToast?: boolean
|
showSaveToast?: boolean
|
||||||
saveDebounceMs?: number
|
saveDebounceMs?: number
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue