@tap-payments/os-micro-frontend-shared 0.1.375 → 0.1.376-test.1-test.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/AnimatedSpinnerIcon/style.d.ts +0 -1
- package/build/components/Chip/style.d.ts +0 -1
- package/build/components/CountBadge/style.d.ts +0 -1
- package/build/components/Dialog/style.d.ts +0 -1
- package/build/components/FlippingCard/style.d.ts +0 -1
- package/build/components/ImageWrapper/ImageWrapper.d.ts +0 -1
- package/build/components/JSONViewer/style.d.ts +0 -1
- package/build/components/LeftPeekRightExpandingChip/style.d.ts +0 -1
- package/build/components/RightLeftExpandingCenterChip/style.d.ts +0 -1
- package/build/components/SearchButton/styles.d.ts +0 -1
- package/build/components/StatusIcons/AuthIcons/style.d.ts +0 -1
- package/build/components/StatusIcons/AuthorizationAutoIcons/style.d.ts +0 -1
- package/build/components/StatusIcons/ChargeStatusIcon/style.d.ts +0 -1
- package/build/components/StatusIcons/SourceIcons/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/ActionCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/AgreementCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/ApplicationStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/AuthenticationCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/AuthenticationStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/AuthenticationTypeCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/BalanceCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/ChannelsCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/CheckoutStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/DestinationStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/DueDateCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/IDButton/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/IntentsStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/InvoiceStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/PayoutReportCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/PayoutStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/ProductsCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/ReferenceCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/RefundChargeCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/RefundStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/SalesChannelCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/SegmentsCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/StatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/TokenStatusCell/style.d.ts +0 -1
- package/build/components/TableCells/CustomCells/style.d.ts +0 -1
- package/build/components/TableHeader/FiltersRow.d.ts +1 -1
- package/build/components/TableHeader/FiltersRow.js +4 -2
- package/build/components/TableHeader/TableHeader.d.ts +1 -1
- package/build/components/TableHeader/TableHeader.js +2 -2
- package/build/components/TableHeader/TableView/CreateViewDialog.d.ts +3 -0
- package/build/components/TableHeader/TableView/CreateViewDialog.js +91 -0
- package/build/components/TableHeader/TableView/CustomViews.js +1 -1
- package/build/components/TableHeader/TableView/TableView.js +0 -1
- package/build/components/TableHeader/TableView/ViewSelector.d.ts +5 -0
- package/build/components/TableHeader/TableView/ViewSelector.js +81 -0
- package/build/components/TableHeader/TableView/ViewsDropdown.d.ts +5 -0
- package/build/components/TableHeader/TableView/ViewsDropdown.js +198 -0
- package/build/components/TableHeader/TableView/components/ColumnList.d.ts +3 -0
- package/build/components/TableHeader/TableView/components/ColumnList.js +70 -0
- package/build/components/TableHeader/TableView/components/ViewsSubmenu.d.ts +3 -0
- package/build/components/TableHeader/TableView/components/ViewsSubmenu.js +71 -0
- package/build/components/TableHeader/TableView/components/index.d.ts +2 -0
- package/build/components/TableHeader/TableView/components/index.js +2 -0
- package/build/components/TableHeader/TableView/constants.d.ts +10 -0
- package/build/components/TableHeader/TableView/constants.js +10 -0
- package/build/components/TableHeader/TableView/data.d.ts +5 -0
- package/build/components/TableHeader/TableView/data.js +48 -0
- package/build/components/TableHeader/TableView/hooks/index.d.ts +6 -0
- package/build/components/TableHeader/TableView/hooks/index.js +6 -0
- package/build/components/TableHeader/TableView/hooks/useCreateViewDialog.d.ts +22 -0
- package/build/components/TableHeader/TableView/hooks/useCreateViewDialog.js +86 -0
- package/build/components/TableHeader/TableView/hooks/useDialogPosition.d.ts +8 -0
- package/build/components/TableHeader/TableView/hooks/useDialogPosition.js +16 -0
- package/build/components/TableHeader/TableView/hooks/useNestedSubmenu.d.ts +7 -0
- package/build/components/TableHeader/TableView/hooks/useNestedSubmenu.js +34 -0
- package/build/components/TableHeader/TableView/hooks/useOriginalColumns.d.ts +6 -0
- package/build/components/TableHeader/TableView/hooks/useOriginalColumns.js +18 -0
- package/build/components/TableHeader/TableView/hooks/useSubmenuHover.d.ts +8 -0
- package/build/components/TableHeader/TableView/hooks/useSubmenuHover.js +43 -0
- package/build/components/TableHeader/TableView/hooks/useViewSelector.d.ts +50 -0
- package/build/components/TableHeader/TableView/hooks/useViewSelector.js +239 -0
- package/build/components/TableHeader/TableView/hooks/useViewsManager.d.ts +20 -0
- package/build/components/TableHeader/TableView/hooks/useViewsManager.js +96 -0
- package/build/components/TableHeader/TableView/index.d.ts +12 -3
- package/build/components/TableHeader/TableView/index.js +13 -3
- package/build/components/TableHeader/TableView/styles.d.ts +127 -0
- package/build/components/TableHeader/TableView/styles.js +426 -0
- package/build/components/TableHeader/TableView/types.d.ts +183 -0
- package/build/components/TableHeader/TableView/types.js +1 -0
- package/build/components/TableHeader/TableView/utils.d.ts +121 -0
- package/build/components/TableHeader/TableView/utils.js +463 -0
- package/build/components/TableHeader/index.d.ts +1 -0
- package/build/components/TableHeader/type.d.ts +15 -1
- package/build/components/TableReports/components/DownloadButton/style.d.ts +0 -1
- package/build/components/TableReports/style.d.ts +0 -1
- package/build/components/VirtualTables/components/style.d.ts +0 -1
- package/build/constants/assets.d.ts +2 -0
- package/build/constants/assets.js +2 -0
- package/package.json +4 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { SUBMENU_CLOSE_DELAY } from '../constants';
|
|
3
|
+
export const useNestedSubmenu = () => {
|
|
4
|
+
const [hoveredNestedColumn, setHoveredNestedColumn] = useState(null);
|
|
5
|
+
const [nestedSubmenuAnchorEl, setNestedSubmenuAnchorEl] = useState(null);
|
|
6
|
+
const nestedCloseTimeoutRef = useRef(null);
|
|
7
|
+
const openNestedSubmenu = useCallback((columnName, element) => {
|
|
8
|
+
if (nestedCloseTimeoutRef.current) {
|
|
9
|
+
clearTimeout(nestedCloseTimeoutRef.current);
|
|
10
|
+
nestedCloseTimeoutRef.current = null;
|
|
11
|
+
}
|
|
12
|
+
setHoveredNestedColumn(columnName);
|
|
13
|
+
setNestedSubmenuAnchorEl(element);
|
|
14
|
+
}, []);
|
|
15
|
+
const closeNestedSubmenu = useCallback(() => {
|
|
16
|
+
nestedCloseTimeoutRef.current = setTimeout(() => {
|
|
17
|
+
setHoveredNestedColumn(null);
|
|
18
|
+
setNestedSubmenuAnchorEl(null);
|
|
19
|
+
}, SUBMENU_CLOSE_DELAY);
|
|
20
|
+
}, []);
|
|
21
|
+
const cancelNestedClose = useCallback(() => {
|
|
22
|
+
if (nestedCloseTimeoutRef.current) {
|
|
23
|
+
clearTimeout(nestedCloseTimeoutRef.current);
|
|
24
|
+
nestedCloseTimeoutRef.current = null;
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
return {
|
|
28
|
+
hoveredNestedColumn,
|
|
29
|
+
nestedSubmenuAnchorEl,
|
|
30
|
+
openNestedSubmenu,
|
|
31
|
+
closeNestedSubmenu,
|
|
32
|
+
cancelNestedClose,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
export const useOriginalColumns = (defaultColumns) => {
|
|
3
|
+
const [originalColumns, setOriginalColumns] = useState([]);
|
|
4
|
+
const saveOriginalState = useCallback(() => {
|
|
5
|
+
setOriginalColumns(defaultColumns.map((col) => {
|
|
6
|
+
var _a;
|
|
7
|
+
return (Object.assign(Object.assign({}, col), { selected: col.selected, menuItems: (_a = col.menuItems) === null || _a === void 0 ? void 0 : _a.map((item) => (Object.assign(Object.assign({}, item), { selected: item.selected }))) }));
|
|
8
|
+
}));
|
|
9
|
+
}, [defaultColumns]);
|
|
10
|
+
const clearOriginalState = useCallback(() => {
|
|
11
|
+
setOriginalColumns([]);
|
|
12
|
+
}, []);
|
|
13
|
+
return {
|
|
14
|
+
originalColumns,
|
|
15
|
+
saveOriginalState,
|
|
16
|
+
clearOriginalState,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { SUBMENU_CLOSE_DELAY } from '../constants';
|
|
3
|
+
export const useSubmenuHover = () => {
|
|
4
|
+
const [hoveredColumn, setHoveredColumn] = useState(null);
|
|
5
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
6
|
+
const closeTimeoutRef = useRef(null);
|
|
7
|
+
const openSubmenu = useCallback((columnName, element) => {
|
|
8
|
+
if (closeTimeoutRef.current) {
|
|
9
|
+
clearTimeout(closeTimeoutRef.current);
|
|
10
|
+
closeTimeoutRef.current = null;
|
|
11
|
+
}
|
|
12
|
+
setHoveredColumn(columnName);
|
|
13
|
+
setAnchorEl(element);
|
|
14
|
+
}, []);
|
|
15
|
+
const closeSubmenu = useCallback(() => {
|
|
16
|
+
closeTimeoutRef.current = setTimeout(() => {
|
|
17
|
+
setHoveredColumn(null);
|
|
18
|
+
setAnchorEl(null);
|
|
19
|
+
}, SUBMENU_CLOSE_DELAY);
|
|
20
|
+
}, []);
|
|
21
|
+
const cancelClose = useCallback(() => {
|
|
22
|
+
if (closeTimeoutRef.current) {
|
|
23
|
+
clearTimeout(closeTimeoutRef.current);
|
|
24
|
+
closeTimeoutRef.current = null;
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
const forceClose = useCallback(() => {
|
|
28
|
+
if (closeTimeoutRef.current) {
|
|
29
|
+
clearTimeout(closeTimeoutRef.current);
|
|
30
|
+
closeTimeoutRef.current = null;
|
|
31
|
+
}
|
|
32
|
+
setHoveredColumn(null);
|
|
33
|
+
setAnchorEl(null);
|
|
34
|
+
}, []);
|
|
35
|
+
return {
|
|
36
|
+
hoveredColumn,
|
|
37
|
+
anchorEl,
|
|
38
|
+
openSubmenu,
|
|
39
|
+
closeSubmenu,
|
|
40
|
+
cancelClose,
|
|
41
|
+
forceClose,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type MouseEvent } from 'react';
|
|
2
|
+
import type { ColumnViewProps, TableMode } from '../../../../types/index.js';
|
|
3
|
+
import type { ViewMenuItem, LayoutSection } from '../types';
|
|
4
|
+
import type { ViewOption } from '../../type';
|
|
5
|
+
export interface UseViewSelectorProps {
|
|
6
|
+
mode: TableMode;
|
|
7
|
+
onViewChange?: (selectedView?: ViewMenuItem) => void;
|
|
8
|
+
onCreateCustomView?: (data: {
|
|
9
|
+
name: string;
|
|
10
|
+
selectedColumns: ColumnViewProps[];
|
|
11
|
+
layout: LayoutSection;
|
|
12
|
+
}) => Promise<void>;
|
|
13
|
+
onEditCustomView?: (viewId: string, data: {
|
|
14
|
+
name: string;
|
|
15
|
+
selectedColumns: ColumnViewProps[];
|
|
16
|
+
layout: LayoutSection;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
onDeleteCustomView?: (viewId: string) => Promise<void>;
|
|
19
|
+
customViews: ViewMenuItem[];
|
|
20
|
+
defaultColumns: ColumnViewProps[];
|
|
21
|
+
defaultTemplate?: ViewMenuItem;
|
|
22
|
+
allTemplates: ViewMenuItem[];
|
|
23
|
+
setInternalCustomViews: (views: ViewMenuItem[]) => void;
|
|
24
|
+
}
|
|
25
|
+
export declare const useViewSelector: ({ mode, onViewChange, onCreateCustomView, onEditCustomView, onDeleteCustomView, customViews, defaultColumns, defaultTemplate, allTemplates, setInternalCustomViews, }: UseViewSelectorProps) => {
|
|
26
|
+
anchorViewEl: HTMLDivElement | null;
|
|
27
|
+
defaultViewEl: HTMLDivElement | null;
|
|
28
|
+
setDefaultViewElement: import("react").Dispatch<import("react").SetStateAction<HTMLDivElement | null>>;
|
|
29
|
+
isCreateDialogOpen: boolean;
|
|
30
|
+
editingView: ViewMenuItem | null;
|
|
31
|
+
selectedViewInfo: ViewOption;
|
|
32
|
+
shouldUseCurrentState: boolean;
|
|
33
|
+
selectedView: ViewMenuItem | undefined;
|
|
34
|
+
currentViewColumns: ColumnViewProps[];
|
|
35
|
+
handleViewButtonClick: (event: MouseEvent<HTMLDivElement>) => void;
|
|
36
|
+
handleCloseViewDropdown: () => void;
|
|
37
|
+
handleSelectedViewInfo: (selected: ViewOption, viewMenuItem?: ViewMenuItem) => void;
|
|
38
|
+
handleOpenCreateDialog: (useCurrentState?: boolean) => void;
|
|
39
|
+
handleOpenEditDialog: (view: ViewMenuItem) => void;
|
|
40
|
+
handleCloseCreateDialog: () => void;
|
|
41
|
+
handleSaveView: (data: {
|
|
42
|
+
name: string;
|
|
43
|
+
selectedColumns: ColumnViewProps[];
|
|
44
|
+
layout: LayoutSection;
|
|
45
|
+
}) => Promise<void>;
|
|
46
|
+
handleDeleteView: (viewId: string) => Promise<void>;
|
|
47
|
+
handleResetViews: () => void;
|
|
48
|
+
updateSelectedView: (updatedView: ViewMenuItem) => void;
|
|
49
|
+
updateCurrentViewColumns: (columns: ColumnViewProps[]) => void;
|
|
50
|
+
};
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
11
|
+
import { deepCloneColumns } from '../utils';
|
|
12
|
+
export const useViewSelector = ({ mode, onViewChange, onCreateCustomView, onEditCustomView, onDeleteCustomView, customViews, defaultColumns, defaultTemplate, allTemplates, setInternalCustomViews, }) => {
|
|
13
|
+
const [anchorViewEl, setAnchorViewEl] = useState(null);
|
|
14
|
+
const [defaultViewEl, setDefaultViewElement] = useState(null);
|
|
15
|
+
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
|
16
|
+
const [editingView, setEditingView] = useState(null);
|
|
17
|
+
const [selectedViewInfo, setSelectedViewInfo] = useState({ id: 'default', label: 'Default' });
|
|
18
|
+
const [shouldUseCurrentState, setShouldUseCurrentState] = useState(false);
|
|
19
|
+
const [selectedView, setSelectedView] = useState(undefined);
|
|
20
|
+
// Current view columns - this is what gets displayed and can be modified
|
|
21
|
+
const [currentViewColumns, setCurrentViewColumns] = useState([]);
|
|
22
|
+
const hasInitializedRef = useRef(false);
|
|
23
|
+
// Helper: Filter view to only include selected columns for parent
|
|
24
|
+
const getViewForParent = useCallback((view) => {
|
|
25
|
+
var _a;
|
|
26
|
+
const selectedColumns = ((_a = view.submenu) === null || _a === void 0 ? void 0 : _a.filter((col) => col.selected)) || [];
|
|
27
|
+
return Object.assign(Object.assign({}, view), { submenu: selectedColumns, columns: selectedColumns.map((col) => col.name) });
|
|
28
|
+
}, []);
|
|
29
|
+
// Initialize with default template on mount
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (hasInitializedRef.current)
|
|
32
|
+
return;
|
|
33
|
+
if (!defaultTemplate)
|
|
34
|
+
return;
|
|
35
|
+
setSelectedView(defaultTemplate);
|
|
36
|
+
setCurrentViewColumns(deepCloneColumns(defaultColumns));
|
|
37
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(defaultTemplate));
|
|
38
|
+
hasInitializedRef.current = true;
|
|
39
|
+
}, [defaultTemplate, defaultColumns, onViewChange, getViewForParent]);
|
|
40
|
+
// Sync currentViewColumns with defaultColumns when they change (e.g., after save)
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!hasInitializedRef.current)
|
|
43
|
+
return;
|
|
44
|
+
if ((selectedView === null || selectedView === void 0 ? void 0 : selectedView.default) && defaultColumns.length > 0) {
|
|
45
|
+
setCurrentViewColumns(deepCloneColumns(defaultColumns));
|
|
46
|
+
}
|
|
47
|
+
}, [defaultColumns, selectedView === null || selectedView === void 0 ? void 0 : selectedView.default]);
|
|
48
|
+
// Track the last mode we successfully synced columns for
|
|
49
|
+
const lastSyncedModeRef = useRef(null);
|
|
50
|
+
// Handle mode changes - sync with allTemplates updates
|
|
51
|
+
// This effect needs to run whenever mode changes OR when defaultColumns/allTemplates update
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!hasInitializedRef.current)
|
|
54
|
+
return;
|
|
55
|
+
if (!selectedView)
|
|
56
|
+
return;
|
|
57
|
+
// Check if we need to sync: either mode changed, or we haven't synced for current mode yet
|
|
58
|
+
const needsSync = lastSyncedModeRef.current !== mode;
|
|
59
|
+
if (!needsSync)
|
|
60
|
+
return;
|
|
61
|
+
// For default template, wait until defaultColumns has data for the new mode
|
|
62
|
+
if (selectedView.default) {
|
|
63
|
+
if (defaultColumns.length === 0)
|
|
64
|
+
return; // Wait for columns to load
|
|
65
|
+
const newView = Object.assign(Object.assign({}, selectedView), { submenu: deepCloneColumns(defaultColumns), columns: defaultColumns.map((col) => col.name) });
|
|
66
|
+
setSelectedView(newView);
|
|
67
|
+
setCurrentViewColumns(deepCloneColumns(defaultColumns));
|
|
68
|
+
lastSyncedModeRef.current = mode; // Mark as synced only after successful update
|
|
69
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(newView));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Custom template: find it in allTemplates (which has new mode's columns)
|
|
73
|
+
const updatedTemplate = allTemplates.find((t) => t.templateId === selectedView.templateId || t.id === selectedView.id);
|
|
74
|
+
if (updatedTemplate && updatedTemplate.submenu && updatedTemplate.submenu.length > 0) {
|
|
75
|
+
const newView = Object.assign(Object.assign({}, updatedTemplate), { submenu: deepCloneColumns(updatedTemplate.submenu) });
|
|
76
|
+
setSelectedView(newView);
|
|
77
|
+
setCurrentViewColumns(deepCloneColumns(updatedTemplate.submenu));
|
|
78
|
+
lastSyncedModeRef.current = mode; // Mark as synced only after successful update
|
|
79
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(newView));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}, [mode, defaultColumns, selectedView, allTemplates, onViewChange]);
|
|
83
|
+
// Track template updates ref to detect external changes
|
|
84
|
+
const templatesUpdateRef = useRef(0);
|
|
85
|
+
// Sync selected view when templates change (for edits/updates)
|
|
86
|
+
// This ensures that template edits automatically reflect in the selected view
|
|
87
|
+
// ONLY when triggered by explicit save actions (Okay/Update buttons)
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
var _a;
|
|
90
|
+
if (!hasInitializedRef.current)
|
|
91
|
+
return;
|
|
92
|
+
if (!selectedView)
|
|
93
|
+
return;
|
|
94
|
+
// Find the current selected view in updated allTemplates
|
|
95
|
+
const updatedTemplate = allTemplates.find((t) => {
|
|
96
|
+
const templateId = t.templateId || t.id;
|
|
97
|
+
const selectedId = selectedView.templateId || selectedView.id;
|
|
98
|
+
return templateId === selectedId;
|
|
99
|
+
});
|
|
100
|
+
if (!updatedTemplate)
|
|
101
|
+
return;
|
|
102
|
+
// Check if the template has actually changed by comparing submenu
|
|
103
|
+
const currentSubmenu = selectedView.submenu || [];
|
|
104
|
+
const updatedSubmenu = updatedTemplate.submenu || [];
|
|
105
|
+
// Simple check: if lengths differ or selected states differ, update
|
|
106
|
+
const hasChanged = currentSubmenu.length !== updatedSubmenu.length ||
|
|
107
|
+
currentSubmenu.some((col, idx) => {
|
|
108
|
+
const updatedCol = updatedSubmenu[idx];
|
|
109
|
+
if (!updatedCol)
|
|
110
|
+
return true;
|
|
111
|
+
return col.selected !== updatedCol.selected || col.name !== updatedCol.name;
|
|
112
|
+
});
|
|
113
|
+
if (hasChanged) {
|
|
114
|
+
console.log('🔄 Template updated, syncing selected view:', selectedView.label);
|
|
115
|
+
console.log(' Old columns count:', currentSubmenu.length, 'New columns count:', updatedSubmenu.length);
|
|
116
|
+
console.log(' Old selected:', currentSubmenu.filter((c) => c.selected).length, 'New selected:', updatedSubmenu.filter((c) => c.selected).length);
|
|
117
|
+
// Store the full view internally (with all columns)
|
|
118
|
+
const fullView = Object.assign(Object.assign({}, updatedTemplate), { submenu: deepCloneColumns(updatedTemplate.submenu || []) });
|
|
119
|
+
setSelectedView(fullView);
|
|
120
|
+
setCurrentViewColumns(deepCloneColumns(updatedTemplate.submenu || []));
|
|
121
|
+
// Pass only selected columns to parent
|
|
122
|
+
const viewForParent = getViewForParent(fullView);
|
|
123
|
+
console.log('✅ Calling onViewChange with', (_a = viewForParent.submenu) === null || _a === void 0 ? void 0 : _a.length, 'selected columns');
|
|
124
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(viewForParent);
|
|
125
|
+
templatesUpdateRef.current++;
|
|
126
|
+
}
|
|
127
|
+
}, [allTemplates, selectedView, onViewChange]);
|
|
128
|
+
const handleViewButtonClick = useCallback((event) => {
|
|
129
|
+
setAnchorViewEl(event.currentTarget);
|
|
130
|
+
setDefaultViewElement(event.currentTarget);
|
|
131
|
+
}, []);
|
|
132
|
+
const handleCloseViewDropdown = useCallback(() => {
|
|
133
|
+
setDefaultViewElement(null);
|
|
134
|
+
}, []);
|
|
135
|
+
const handleSelectedViewInfo = useCallback((selected, viewMenuItem) => {
|
|
136
|
+
setSelectedViewInfo(selected);
|
|
137
|
+
const newSelectedView = viewMenuItem || undefined;
|
|
138
|
+
setSelectedView(newSelectedView);
|
|
139
|
+
setCurrentViewColumns(deepCloneColumns((newSelectedView === null || newSelectedView === void 0 ? void 0 : newSelectedView.submenu) || []));
|
|
140
|
+
if (newSelectedView) {
|
|
141
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(newSelectedView));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(undefined);
|
|
145
|
+
}
|
|
146
|
+
handleCloseViewDropdown();
|
|
147
|
+
}, [handleCloseViewDropdown, onViewChange, getViewForParent]);
|
|
148
|
+
// Update selected view with modified columns
|
|
149
|
+
const updateSelectedView = useCallback((updatedView) => {
|
|
150
|
+
var _a, _b;
|
|
151
|
+
console.log('🔴 updateSelectedView called:', {
|
|
152
|
+
id: updatedView.id,
|
|
153
|
+
columnsCount: (_a = updatedView.submenu) === null || _a === void 0 ? void 0 : _a.length,
|
|
154
|
+
selectedColumns: (_b = updatedView.submenu) === null || _b === void 0 ? void 0 : _b.filter((c) => c.selected).length,
|
|
155
|
+
});
|
|
156
|
+
// CRITICAL: Force new object/array references to trigger React re-renders
|
|
157
|
+
const viewWithNewRefs = Object.assign(Object.assign({}, updatedView), { submenu: updatedView.submenu ? [...updatedView.submenu] : undefined, columns: updatedView.columns ? [...updatedView.columns] : undefined });
|
|
158
|
+
setSelectedView(viewWithNewRefs);
|
|
159
|
+
setCurrentViewColumns(deepCloneColumns(viewWithNewRefs.submenu || []));
|
|
160
|
+
setSelectedViewInfo({ id: viewWithNewRefs.id, label: viewWithNewRefs.label });
|
|
161
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(viewWithNewRefs));
|
|
162
|
+
}, [onViewChange, getViewForParent]);
|
|
163
|
+
// Update current view columns (for temporary modifications)
|
|
164
|
+
const updateCurrentViewColumns = useCallback((columns) => {
|
|
165
|
+
setCurrentViewColumns(columns);
|
|
166
|
+
}, []);
|
|
167
|
+
const handleOpenCreateDialog = useCallback((useCurrentState = false) => {
|
|
168
|
+
setEditingView(null);
|
|
169
|
+
setShouldUseCurrentState(useCurrentState);
|
|
170
|
+
setIsCreateDialogOpen(true);
|
|
171
|
+
setDefaultViewElement(null);
|
|
172
|
+
}, []);
|
|
173
|
+
const handleOpenEditDialog = useCallback((view) => {
|
|
174
|
+
setEditingView(view);
|
|
175
|
+
setShouldUseCurrentState(true);
|
|
176
|
+
setIsCreateDialogOpen(true);
|
|
177
|
+
}, []);
|
|
178
|
+
const handleCloseCreateDialog = useCallback(() => {
|
|
179
|
+
setIsCreateDialogOpen(false);
|
|
180
|
+
setEditingView(null);
|
|
181
|
+
setShouldUseCurrentState(false);
|
|
182
|
+
}, []);
|
|
183
|
+
const handleSaveView = useCallback((data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
|
+
if (editingView) {
|
|
185
|
+
const templateId = editingView.templateId || editingView.id;
|
|
186
|
+
// Call the edit handler - parent will update templates
|
|
187
|
+
yield (onEditCustomView === null || onEditCustomView === void 0 ? void 0 : onEditCustomView(templateId, data));
|
|
188
|
+
// After edit completes successfully, the template will be updated externally via templates prop
|
|
189
|
+
// The useEffect watching allTemplates will automatically sync the view
|
|
190
|
+
console.log('✅ View saved - templates will update and trigger sync');
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Call the create handler - parent will add new template
|
|
194
|
+
yield (onCreateCustomView === null || onCreateCustomView === void 0 ? void 0 : onCreateCustomView(data));
|
|
195
|
+
// After create completes successfully, the new template will be added externally via templates prop
|
|
196
|
+
// The new template will automatically appear in the dropdown
|
|
197
|
+
console.log('✅ View created - new template will appear in dropdown');
|
|
198
|
+
}
|
|
199
|
+
}), [editingView, onEditCustomView, onCreateCustomView]);
|
|
200
|
+
const handleDeleteView = useCallback((viewId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
201
|
+
const viewToDelete = allTemplates.find((view) => view.id === viewId || view.templateId === viewId);
|
|
202
|
+
const templateId = (viewToDelete === null || viewToDelete === void 0 ? void 0 : viewToDelete.templateId) || viewId;
|
|
203
|
+
yield (onDeleteCustomView === null || onDeleteCustomView === void 0 ? void 0 : onDeleteCustomView(templateId));
|
|
204
|
+
// If deleted view was selected, reset to default
|
|
205
|
+
if ((selectedView === null || selectedView === void 0 ? void 0 : selectedView.id) === viewId || (selectedView === null || selectedView === void 0 ? void 0 : selectedView.templateId) === viewId) {
|
|
206
|
+
setSelectedView(defaultTemplate);
|
|
207
|
+
setCurrentViewColumns(deepCloneColumns(defaultColumns));
|
|
208
|
+
if (defaultTemplate) {
|
|
209
|
+
onViewChange === null || onViewChange === void 0 ? void 0 : onViewChange(getViewForParent(defaultTemplate));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}), [allTemplates, onDeleteCustomView, selectedView, defaultTemplate, defaultColumns, onViewChange, getViewForParent]);
|
|
213
|
+
// Reset views to default
|
|
214
|
+
const handleResetViews = useCallback(() => {
|
|
215
|
+
setCurrentViewColumns(deepCloneColumns(defaultColumns));
|
|
216
|
+
}, [defaultColumns]);
|
|
217
|
+
return {
|
|
218
|
+
anchorViewEl,
|
|
219
|
+
defaultViewEl,
|
|
220
|
+
setDefaultViewElement,
|
|
221
|
+
isCreateDialogOpen,
|
|
222
|
+
editingView,
|
|
223
|
+
selectedViewInfo,
|
|
224
|
+
shouldUseCurrentState,
|
|
225
|
+
selectedView,
|
|
226
|
+
currentViewColumns,
|
|
227
|
+
handleViewButtonClick,
|
|
228
|
+
handleCloseViewDropdown,
|
|
229
|
+
handleSelectedViewInfo,
|
|
230
|
+
handleOpenCreateDialog,
|
|
231
|
+
handleOpenEditDialog,
|
|
232
|
+
handleCloseCreateDialog,
|
|
233
|
+
handleSaveView,
|
|
234
|
+
handleDeleteView,
|
|
235
|
+
handleResetViews,
|
|
236
|
+
updateSelectedView,
|
|
237
|
+
updateCurrentViewColumns,
|
|
238
|
+
};
|
|
239
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { ColumnViewProps } from '../../../../types/index.js';
|
|
3
|
+
import type { UseViewsManagerProps, ViewMenuItem } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Simplified hook for managing templates and views.
|
|
6
|
+
*
|
|
7
|
+
* Key principles:
|
|
8
|
+
* - Templates from parent are parsed into allTemplates
|
|
9
|
+
* - defaultColumns is the local working copy that can be modified
|
|
10
|
+
* - When user modifies default template, we keep changes locally
|
|
11
|
+
*/
|
|
12
|
+
export declare const useViewsManager: ({ tableMode, templates, lang }: UseViewsManagerProps) => {
|
|
13
|
+
defaultTemplate: ViewMenuItem | undefined;
|
|
14
|
+
customViews: ViewMenuItem[];
|
|
15
|
+
allTemplates: ViewMenuItem[];
|
|
16
|
+
defaultColumns: ColumnViewProps[];
|
|
17
|
+
updateDefaultColumns: (columns: ColumnViewProps[]) => void;
|
|
18
|
+
internalCustomViews: ViewMenuItem[];
|
|
19
|
+
setInternalCustomViews: import("react").Dispatch<import("react").SetStateAction<ViewMenuItem[]>>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo, useCallback } from 'react';
|
|
2
|
+
import { transformTemplatesToViewMenuItems, deepCloneColumns } from '../utils';
|
|
3
|
+
/**
|
|
4
|
+
* Simplified hook for managing templates and views.
|
|
5
|
+
*
|
|
6
|
+
* Key principles:
|
|
7
|
+
* - Templates from parent are parsed into allTemplates
|
|
8
|
+
* - defaultColumns is the local working copy that can be modified
|
|
9
|
+
* - When user modifies default template, we keep changes locally
|
|
10
|
+
*/
|
|
11
|
+
export const useViewsManager = ({ tableMode, templates, lang = 'en' }) => {
|
|
12
|
+
// Parse templates (this just transforms the data, doesn't manage modifications)
|
|
13
|
+
const parsedTemplates = useMemo(() => {
|
|
14
|
+
if (!templates || templates.length === 0) {
|
|
15
|
+
return {
|
|
16
|
+
customViews: [],
|
|
17
|
+
defaultTemplate: undefined,
|
|
18
|
+
templateDefaultColumns: [],
|
|
19
|
+
allTemplates: [],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const { customViews, defaultTemplate } = transformTemplatesToViewMenuItems(templates, tableMode, lang);
|
|
23
|
+
// Combine all templates for easy access
|
|
24
|
+
const allTemplates = defaultTemplate ? [defaultTemplate, ...customViews] : customViews;
|
|
25
|
+
return {
|
|
26
|
+
customViews,
|
|
27
|
+
defaultTemplate,
|
|
28
|
+
templateDefaultColumns: (defaultTemplate === null || defaultTemplate === void 0 ? void 0 : defaultTemplate.submenu) || [],
|
|
29
|
+
allTemplates,
|
|
30
|
+
};
|
|
31
|
+
}, [templates, tableMode, lang]);
|
|
32
|
+
// Local state for default columns - this is the working copy that can be modified
|
|
33
|
+
const [defaultColumns, setDefaultColumns] = useState([]);
|
|
34
|
+
// Track if we've initialized for this mode (to avoid resetting user modifications)
|
|
35
|
+
const [initializedMode, setInitializedMode] = useState(null);
|
|
36
|
+
// Initialize defaultColumns when templates load or mode changes
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
// Only initialize if mode changed or we haven't initialized yet
|
|
39
|
+
if (initializedMode !== tableMode && parsedTemplates.templateDefaultColumns.length > 0) {
|
|
40
|
+
setDefaultColumns(deepCloneColumns(parsedTemplates.templateDefaultColumns));
|
|
41
|
+
setInitializedMode(tableMode);
|
|
42
|
+
}
|
|
43
|
+
}, [tableMode, parsedTemplates.templateDefaultColumns, initializedMode]);
|
|
44
|
+
// Custom views state
|
|
45
|
+
const [internalCustomViews, setInternalCustomViews] = useState([]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setInternalCustomViews([...parsedTemplates.customViews]);
|
|
48
|
+
}, [parsedTemplates.customViews]);
|
|
49
|
+
// Function to update default columns (called when user modifies and clicks Okay)
|
|
50
|
+
const updateDefaultColumns = useCallback((columns) => {
|
|
51
|
+
setDefaultColumns(deepCloneColumns(columns));
|
|
52
|
+
}, []);
|
|
53
|
+
// Create an updated default template with current defaultColumns
|
|
54
|
+
// IMPORTANT: When mode just changed (initializedMode !== tableMode), use parsedTemplates
|
|
55
|
+
// directly because defaultColumns state hasn't updated yet
|
|
56
|
+
const updatedDefaultTemplate = useMemo(() => {
|
|
57
|
+
if (!parsedTemplates.defaultTemplate) {
|
|
58
|
+
return parsedTemplates.defaultTemplate;
|
|
59
|
+
}
|
|
60
|
+
// If mode just changed, use the fresh parsed columns, not the stale state
|
|
61
|
+
const columnsToUse = initializedMode !== tableMode ? parsedTemplates.templateDefaultColumns : defaultColumns;
|
|
62
|
+
if (columnsToUse.length === 0) {
|
|
63
|
+
return parsedTemplates.defaultTemplate;
|
|
64
|
+
}
|
|
65
|
+
return Object.assign(Object.assign({}, parsedTemplates.defaultTemplate), { submenu: columnsToUse, columns: columnsToUse.map((col) => col.name) });
|
|
66
|
+
}, [parsedTemplates.defaultTemplate, parsedTemplates.templateDefaultColumns, defaultColumns, initializedMode, tableMode]);
|
|
67
|
+
// Build allTemplates with the updated default template
|
|
68
|
+
const updatedAllTemplates = useMemo(() => {
|
|
69
|
+
if (!updatedDefaultTemplate) {
|
|
70
|
+
return parsedTemplates.customViews;
|
|
71
|
+
}
|
|
72
|
+
return [updatedDefaultTemplate, ...parsedTemplates.customViews];
|
|
73
|
+
}, [updatedDefaultTemplate, parsedTemplates.customViews]);
|
|
74
|
+
// For mode changes, provide the correct columns
|
|
75
|
+
// Key: ALWAYS prefer state columns if they exist (preserves user modifications)
|
|
76
|
+
const effectiveDefaultColumns = useMemo(() => {
|
|
77
|
+
// If mode just changed AND we have no initialized state, use parsed columns
|
|
78
|
+
if (initializedMode !== tableMode && defaultColumns.length === 0) {
|
|
79
|
+
return parsedTemplates.templateDefaultColumns;
|
|
80
|
+
}
|
|
81
|
+
// Otherwise use state columns (which may include user edits)
|
|
82
|
+
return defaultColumns.length > 0 ? defaultColumns : parsedTemplates.templateDefaultColumns;
|
|
83
|
+
}, [initializedMode, tableMode, defaultColumns, parsedTemplates.templateDefaultColumns]);
|
|
84
|
+
return {
|
|
85
|
+
// Template data (with updated default template including modifications)
|
|
86
|
+
defaultTemplate: updatedDefaultTemplate,
|
|
87
|
+
customViews: parsedTemplates.customViews,
|
|
88
|
+
allTemplates: updatedAllTemplates,
|
|
89
|
+
// Default columns - preserves user edits
|
|
90
|
+
defaultColumns: effectiveDefaultColumns,
|
|
91
|
+
updateDefaultColumns,
|
|
92
|
+
// Internal state
|
|
93
|
+
internalCustomViews,
|
|
94
|
+
setInternalCustomViews,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export default
|
|
1
|
+
export { default } from './TableView';
|
|
2
|
+
export { default as TableView } from './TableView';
|
|
3
|
+
export { default as DefaultViews } from './DefaultViews';
|
|
4
|
+
export { default as CustomViews } from './CustomViews';
|
|
5
|
+
export { default as ViewSelector } from './ViewSelector';
|
|
6
|
+
export { default as ViewsDropdown } from './ViewsDropdown';
|
|
7
|
+
export { default as CreateViewDialog } from './CreateViewDialog';
|
|
8
|
+
export type { ViewMenuItem, CreateCustomViewDialogProps, LayoutSection, ColumnItem, FieldItem, Template, CreateTemplatePayload, UpdateTemplatePayload, } from './types';
|
|
9
|
+
export { transformLayoutToColumns, getColumnsByMode, createCustomViewMenuItem, setViewAsDefault, transformTemplatesToViewMenuItems, convertColumnsToLayoutSection, isDateColumn, getColumnCheckState, } from './utils';
|
|
10
|
+
export { useSubmenuHover, useViewsManager, useViewSelector } from './hooks';
|
|
11
|
+
export { DIALOG_WIDTH, DIALOG_HEIGHT, MAX_CUSTOM_VIEWS, TEMPLATE_NAME_MAX_LENGTH } from './constants';
|
|
12
|
+
export { defaultViewList, advancedColumns, sheetColumns } from './data';
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export default
|
|
1
|
+
export { default } from './TableView';
|
|
2
|
+
export { default as TableView } from './TableView';
|
|
3
|
+
export { default as DefaultViews } from './DefaultViews';
|
|
4
|
+
export { default as CustomViews } from './CustomViews';
|
|
5
|
+
export { default as ViewSelector } from './ViewSelector';
|
|
6
|
+
export { default as ViewsDropdown } from './ViewsDropdown';
|
|
7
|
+
export { default as CreateViewDialog } from './CreateViewDialog';
|
|
8
|
+
export { transformLayoutToColumns, getColumnsByMode, createCustomViewMenuItem, setViewAsDefault, transformTemplatesToViewMenuItems, convertColumnsToLayoutSection, isDateColumn, getColumnCheckState, } from './utils';
|
|
9
|
+
export { useSubmenuHover, useViewsManager, useViewSelector } from './hooks';
|
|
10
|
+
export { DIALOG_WIDTH, DIALOG_HEIGHT, MAX_CUSTOM_VIEWS, TEMPLATE_NAME_MAX_LENGTH } from './constants';
|
|
11
|
+
// Note: defaultViewList, advancedColumns, sheetColumns are only exported for demo purposes
|
|
12
|
+
// They should not be used as defaults in production - all data should come from API
|
|
13
|
+
export { defaultViewList, advancedColumns, sheetColumns } from './data';
|