rez-table-listing-mui 1.0.37 → 1.0.39
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/dist/index.d.ts +100 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/App.tsx +82 -27
- package/src/components/common/confirm-modal/index.tsx +8 -3
- package/src/components/filter/components/forms/components/Date.tsx +109 -161
- package/src/components/filter/components/forms/components/Filter-criteria.tsx +12 -55
- package/src/components/filter/components/forms/index.tsx +1 -1
- package/src/components/filter/components/saved-filter.tsx +6 -3
- package/src/components/filter/index.tsx +1 -1
- package/src/components/filter/style.ts +0 -1
- package/src/components/index-table.tsx +5 -2
- package/src/components/index.scss +2 -0
- package/src/components/login/index.tsx +1 -1
- package/src/components/search/index.tsx +31 -6
- package/src/components/table-head-popover.tsx +1 -1
- package/src/components/table-settings/common/draggable-listitem.tsx +66 -0
- package/src/components/table-settings/common/listing-values.tsx +117 -0
- package/src/components/table-settings/components/column.tsx +332 -0
- package/src/components/table-settings/components/custom-button.tsx +15 -0
- package/src/components/table-settings/components/custom-dialog.tsx +27 -0
- package/src/components/table-settings/components/quick-tab.tsx +335 -0
- package/src/components/table-settings/components/sorting.tsx +619 -0
- package/src/components/table-settings/components/toggle-button-switch.tsx +45 -0
- package/src/components/table-settings/constants.ts +12 -0
- package/src/components/table-settings/index.tsx +133 -0
- package/src/components/table-settings/style.ts +115 -0
- package/src/components/table-settings/tabs/horizontal/index.tsx +21 -0
- package/src/components/table-settings/tabs/styles.ts +67 -0
- package/src/components/table-settings/tabs/vertical/custom-tab-panel.tsx +29 -0
- package/src/components/table-settings/tabs/vertical/index.tsx +38 -0
- package/src/components/tabs/index.tsx +30 -36
- package/src/index.ts +1 -0
- package/src/libs/hooks/useCraftTableFilterSettings.tsx +176 -0
- package/src/libs/hooks/useEntityTableAPI.tsx +82 -1
- package/src/libs/utils/apiColumn.ts +25 -0
- package/src/libs/utils/common.ts +2 -2
- package/src/types/common.ts +6 -0
- package/src/types/filter-settings.ts +97 -0
- package/src/types/filter.ts +6 -0
- package/src/types/table-options.ts +19 -0
- package/src/types/table.ts +10 -1
- package/.env.uat +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useRef } from "react";
|
|
1
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { SearchIcon } from "../../assets/svg";
|
|
3
3
|
import useOutsideClick from "../../libs/hooks/useOutsideClick";
|
|
4
4
|
|
|
@@ -12,14 +12,31 @@ const TableSearch: React.FC<TableSearchProps> = ({ value, onChange }) => {
|
|
|
12
12
|
const [localValue, setLocalValue] = useState(value);
|
|
13
13
|
const searchContainerRef = useRef<HTMLDivElement>(null);
|
|
14
14
|
|
|
15
|
+
// Sync local state with prop value
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
setLocalValue(value);
|
|
18
|
+
}, [value]);
|
|
19
|
+
|
|
15
20
|
useOutsideClick({
|
|
16
21
|
ref: searchContainerRef,
|
|
17
|
-
handler: () =>
|
|
22
|
+
handler: () => {
|
|
23
|
+
setShowSearchInput(false);
|
|
24
|
+
// Update parent when clicking outside if value changed
|
|
25
|
+
if (localValue !== value) {
|
|
26
|
+
onChange(localValue);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
18
29
|
});
|
|
19
30
|
|
|
31
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
32
|
+
const newValue = e.target.value;
|
|
33
|
+
setLocalValue(newValue);
|
|
34
|
+
onChange(newValue); // Update parent state immediately
|
|
35
|
+
};
|
|
36
|
+
|
|
20
37
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
21
|
-
if (e.key === "
|
|
22
|
-
|
|
38
|
+
if (e.key === "Escape") {
|
|
39
|
+
setShowSearchInput(false);
|
|
23
40
|
}
|
|
24
41
|
};
|
|
25
42
|
|
|
@@ -27,7 +44,15 @@ const TableSearch: React.FC<TableSearchProps> = ({ value, onChange }) => {
|
|
|
27
44
|
<div className="search-wrapper" ref={searchContainerRef}>
|
|
28
45
|
<div
|
|
29
46
|
className="search-icon ts--button"
|
|
30
|
-
onClick={() =>
|
|
47
|
+
onClick={() => {
|
|
48
|
+
setShowSearchInput((prev) => !prev);
|
|
49
|
+
if (!showSearchInput) {
|
|
50
|
+
// Focus input when showing
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
searchContainerRef.current?.querySelector('input')?.focus();
|
|
53
|
+
}, 100);
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
31
56
|
>
|
|
32
57
|
<SearchIcon />
|
|
33
58
|
</div>
|
|
@@ -36,7 +61,7 @@ const TableSearch: React.FC<TableSearchProps> = ({ value, onChange }) => {
|
|
|
36
61
|
className={`search-input ${showSearchInput ? "expanded" : ""}`}
|
|
37
62
|
placeholder="Type to search"
|
|
38
63
|
value={localValue}
|
|
39
|
-
onChange={
|
|
64
|
+
onChange={handleChange}
|
|
40
65
|
onKeyDown={handleKeyDown}
|
|
41
66
|
/>
|
|
42
67
|
</div>
|
|
@@ -78,7 +78,7 @@ function TableHeadPopover<T>({
|
|
|
78
78
|
{isPinned ? <IconPinOffOutline /> : <IconPinOutline />}
|
|
79
79
|
</ListItemIcon>
|
|
80
80
|
<ListItemText
|
|
81
|
-
primary={isPinned ? "Unfreeze column" : "Freeze
|
|
81
|
+
primary={isPinned ? "Unfreeze column" : "Freeze column"}
|
|
82
82
|
/>
|
|
83
83
|
</ListItemButton>
|
|
84
84
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useSortable } from "@dnd-kit/sortable";
|
|
3
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
4
|
+
import { Box } from "@mui/material";
|
|
5
|
+
import { DragIndicator } from "@mui/icons-material";
|
|
6
|
+
|
|
7
|
+
export interface SortableFilterItemProps {
|
|
8
|
+
id: string;
|
|
9
|
+
containerId: string;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const DraggableListItem = ({
|
|
14
|
+
id,
|
|
15
|
+
containerId,
|
|
16
|
+
children,
|
|
17
|
+
}: SortableFilterItemProps) => {
|
|
18
|
+
const {
|
|
19
|
+
attributes,
|
|
20
|
+
listeners,
|
|
21
|
+
setNodeRef,
|
|
22
|
+
transform,
|
|
23
|
+
transition,
|
|
24
|
+
isDragging,
|
|
25
|
+
} = useSortable({
|
|
26
|
+
id,
|
|
27
|
+
data: {
|
|
28
|
+
type: "filter-item",
|
|
29
|
+
containerId,
|
|
30
|
+
id,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const style = {
|
|
35
|
+
transform: CSS.Transform.toString(transform),
|
|
36
|
+
transition,
|
|
37
|
+
opacity: isDragging ? 0.8 : 1,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Box
|
|
42
|
+
ref={setNodeRef}
|
|
43
|
+
style={style}
|
|
44
|
+
{...attributes}
|
|
45
|
+
{...listeners}
|
|
46
|
+
sx={{
|
|
47
|
+
display: "flex",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
justifyContent: "space-between",
|
|
50
|
+
py: 1,
|
|
51
|
+
px: 1,
|
|
52
|
+
"&:hover": { bgcolor: "#f5f5f5" },
|
|
53
|
+
borderRadius: 1,
|
|
54
|
+
marginBottom: 1,
|
|
55
|
+
backgroundColor: "white",
|
|
56
|
+
cursor: isDragging ? "grabbing" : "grab",
|
|
57
|
+
boxShadow: isDragging ? "0 2px 8px rgba(0,0,0,0.1)" : "none",
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<DragIndicator sx={{ mr: 1, color: "#ccc" }} />
|
|
61
|
+
{children}
|
|
62
|
+
</Box>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default DraggableListItem;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Visibility, VisibilityOff } from "@mui/icons-material";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Button,
|
|
5
|
+
CircularProgress,
|
|
6
|
+
Grid,
|
|
7
|
+
IconButton,
|
|
8
|
+
Typography,
|
|
9
|
+
} from "@mui/material";
|
|
10
|
+
import CustomSearch from "../../filter/components/search/index.tsx";
|
|
11
|
+
import {
|
|
12
|
+
SortableContext,
|
|
13
|
+
verticalListSortingStrategy,
|
|
14
|
+
} from "@dnd-kit/sortable";
|
|
15
|
+
import { useDroppable } from "@dnd-kit/core";
|
|
16
|
+
import DraggableListItem from "./draggable-listitem.tsx";
|
|
17
|
+
import { listingValuesStyles } from "../style.ts";
|
|
18
|
+
|
|
19
|
+
interface FilterValue {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ListingValuesProps {
|
|
25
|
+
filteredValues: FilterValue[];
|
|
26
|
+
buttonText: string;
|
|
27
|
+
onClick: () => void;
|
|
28
|
+
headerText: string;
|
|
29
|
+
searchTerm?: string;
|
|
30
|
+
setSearchTerm?: React.Dispatch<React.SetStateAction<string>>;
|
|
31
|
+
containerId: string;
|
|
32
|
+
tabsApiDataLoading?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const ListingValues = ({
|
|
36
|
+
filteredValues,
|
|
37
|
+
buttonText,
|
|
38
|
+
onClick,
|
|
39
|
+
headerText,
|
|
40
|
+
searchTerm,
|
|
41
|
+
setSearchTerm,
|
|
42
|
+
containerId,
|
|
43
|
+
tabsApiDataLoading,
|
|
44
|
+
}: ListingValuesProps) => {
|
|
45
|
+
const { setNodeRef } = useDroppable({
|
|
46
|
+
id: containerId,
|
|
47
|
+
data: {
|
|
48
|
+
type: "container",
|
|
49
|
+
containerId: containerId,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Grid size={6} sx={listingValuesStyles.wrapper}>
|
|
55
|
+
{tabsApiDataLoading ? (
|
|
56
|
+
<Box
|
|
57
|
+
display={"flex"}
|
|
58
|
+
justifyContent="center"
|
|
59
|
+
alignItems={"center"}
|
|
60
|
+
height={"100%"}
|
|
61
|
+
>
|
|
62
|
+
<CircularProgress />
|
|
63
|
+
</Box>
|
|
64
|
+
) : (
|
|
65
|
+
<Box sx={{ p: 2 }}>
|
|
66
|
+
<Box sx={listingValuesStyles.headerContainer}>
|
|
67
|
+
<Typography variant="h6" sx={listingValuesStyles.heading}>
|
|
68
|
+
{headerText}
|
|
69
|
+
</Typography>
|
|
70
|
+
<Button
|
|
71
|
+
onClick={onClick}
|
|
72
|
+
variant="text"
|
|
73
|
+
size="small"
|
|
74
|
+
sx={listingValuesStyles.button}
|
|
75
|
+
>
|
|
76
|
+
{buttonText}
|
|
77
|
+
</Button>
|
|
78
|
+
</Box>
|
|
79
|
+
|
|
80
|
+
{searchTerm !== undefined && setSearchTerm !== undefined && (
|
|
81
|
+
<CustomSearch value={searchTerm} onChange={setSearchTerm} />
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
<Box ref={setNodeRef} sx={listingValuesStyles.draggableContainer}>
|
|
85
|
+
<SortableContext
|
|
86
|
+
items={filteredValues.map((item) => item.id)}
|
|
87
|
+
strategy={verticalListSortingStrategy}
|
|
88
|
+
>
|
|
89
|
+
<Box sx={listingValuesStyles.draggableCover}>
|
|
90
|
+
{filteredValues.map((item) => (
|
|
91
|
+
<DraggableListItem
|
|
92
|
+
key={item.id}
|
|
93
|
+
id={item.id}
|
|
94
|
+
containerId={containerId}
|
|
95
|
+
>
|
|
96
|
+
<Box sx={listingValuesStyles.itemLabel}>
|
|
97
|
+
<Typography>{item.label}</Typography>
|
|
98
|
+
</Box>
|
|
99
|
+
<IconButton size="small">
|
|
100
|
+
{containerId === "tabs" ? (
|
|
101
|
+
<Visibility />
|
|
102
|
+
) : (
|
|
103
|
+
<VisibilityOff />
|
|
104
|
+
)}
|
|
105
|
+
</IconButton>
|
|
106
|
+
</DraggableListItem>
|
|
107
|
+
))}
|
|
108
|
+
</Box>
|
|
109
|
+
</SortableContext>
|
|
110
|
+
</Box>
|
|
111
|
+
</Box>
|
|
112
|
+
)}
|
|
113
|
+
</Grid>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export default ListingValues;
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Box, Typography, Tab, Grid } from "@mui/material";
|
|
3
|
+
|
|
4
|
+
import ListingValues from "../common/listing-values";
|
|
5
|
+
import {
|
|
6
|
+
DndContext,
|
|
7
|
+
closestCenter,
|
|
8
|
+
KeyboardSensor,
|
|
9
|
+
MouseSensor,
|
|
10
|
+
TouchSensor,
|
|
11
|
+
useSensor,
|
|
12
|
+
useSensors,
|
|
13
|
+
DragEndEvent,
|
|
14
|
+
} from "@dnd-kit/core";
|
|
15
|
+
import { craftTableFilterSettingsOptionsProps } from "../../../types/table-options";
|
|
16
|
+
import CustomToggleSwitchButton from "./toggle-button-switch";
|
|
17
|
+
import { FilterColumnsDataProps } from "../../../types/filter";
|
|
18
|
+
import { TOGGLE_BUTTON_TABS } from "../constants";
|
|
19
|
+
import { ColumnTabConfigProps } from "../../../types/filter-settings";
|
|
20
|
+
import CustomTabs from "../tabs/horizontal";
|
|
21
|
+
|
|
22
|
+
export interface ColumnItem {
|
|
23
|
+
label: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TabData {
|
|
28
|
+
tab_name: string;
|
|
29
|
+
show_list: ColumnItem[];
|
|
30
|
+
hide_list: ColumnItem[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface ColumnTabProps {
|
|
34
|
+
filterSettingStates: craftTableFilterSettingsOptionsProps;
|
|
35
|
+
columnsData: FilterColumnsDataProps;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ColumnTab = ({ filterSettingStates, columnsData }: ColumnTabProps) => {
|
|
39
|
+
const [searchTerm, setSearchTerm] = useState<string>("");
|
|
40
|
+
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
|
|
41
|
+
|
|
42
|
+
const { quickTabStates, columnTabState, setColumnTabState } =
|
|
43
|
+
filterSettingStates;
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!Object.entries(columnTabState)?.length) {
|
|
47
|
+
const mappedColumns: ColumnItem[] =
|
|
48
|
+
columnsData?.column_list?.map((column) => ({
|
|
49
|
+
label: column?.name,
|
|
50
|
+
value: column?.attribute_key,
|
|
51
|
+
})) || [];
|
|
52
|
+
|
|
53
|
+
console.log("mappedColumnsssss", mappedColumns);
|
|
54
|
+
|
|
55
|
+
const newColumnState: ColumnTabConfigProps = {
|
|
56
|
+
isDefault: true,
|
|
57
|
+
show_list: mappedColumns,
|
|
58
|
+
hide_list: [],
|
|
59
|
+
tabs: quickTabStates?.show_list?.map((tab) => ({
|
|
60
|
+
tab_name: tab,
|
|
61
|
+
show_list: mappedColumns,
|
|
62
|
+
hide_list: [],
|
|
63
|
+
})),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
setColumnTabState(newColumnState);
|
|
67
|
+
}
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
// useEffect(() => {
|
|
71
|
+
// if (settingsData?.column) {
|
|
72
|
+
// const mappedColumns: ColumnItem[] =
|
|
73
|
+
// columnsData?.column_list?.map((col) => ({
|
|
74
|
+
// label: col.name,
|
|
75
|
+
// value: col.attribute_key,
|
|
76
|
+
// })) || [];
|
|
77
|
+
|
|
78
|
+
// const selectedTabNames: string[] =
|
|
79
|
+
// settingsData?.quick_tab?.show_list || [];
|
|
80
|
+
|
|
81
|
+
// const columnTabsMap: Record<string, TabData> = {};
|
|
82
|
+
// settingsData?.column?.tabs?.forEach((tab) => {
|
|
83
|
+
// columnTabsMap[tab.tab_name] = tab; // tab_name → TabData
|
|
84
|
+
// });
|
|
85
|
+
|
|
86
|
+
// const filteredTabs: TabData[] = selectedTabNames.map((name) => ({
|
|
87
|
+
// tab_name: name,
|
|
88
|
+
// show_list: columnTabsMap[name]?.show_list || [],
|
|
89
|
+
// hide_list: columnTabsMap[name]?.hide_list || [],
|
|
90
|
+
// }));
|
|
91
|
+
|
|
92
|
+
// console.log("filteredTabs", filteredTabs);
|
|
93
|
+
|
|
94
|
+
// setColumnTabState({
|
|
95
|
+
// isDefault: settingsData.column.isDefault ?? true,
|
|
96
|
+
// show_list: mappedColumns,
|
|
97
|
+
// hide_list: [],
|
|
98
|
+
// tabs: filteredTabs,
|
|
99
|
+
// });
|
|
100
|
+
// console.log("mappedColumns", mappedColumns);
|
|
101
|
+
// }
|
|
102
|
+
// }, [settingsData]);
|
|
103
|
+
|
|
104
|
+
const isColumnDefault = columnTabState?.isDefault;
|
|
105
|
+
|
|
106
|
+
const sensors = useSensors(
|
|
107
|
+
useSensor(MouseSensor),
|
|
108
|
+
useSensor(TouchSensor),
|
|
109
|
+
useSensor(KeyboardSensor)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Handle toggle between Default and Tab Wise
|
|
113
|
+
const handleToggleChange = (
|
|
114
|
+
_: React.MouseEvent<HTMLElement>,
|
|
115
|
+
newValue: boolean
|
|
116
|
+
) => {
|
|
117
|
+
if (newValue !== null) {
|
|
118
|
+
setColumnTabState({ ...columnTabState, isDefault: newValue });
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Get current show/hide lists based on mode
|
|
123
|
+
const getCurrentLists = () => {
|
|
124
|
+
if (columnTabState?.isDefault) {
|
|
125
|
+
return {
|
|
126
|
+
showList: columnTabState.show_list || [],
|
|
127
|
+
hideList: columnTabState.hide_list || [],
|
|
128
|
+
};
|
|
129
|
+
} else {
|
|
130
|
+
const currentTab = columnTabState?.tabs?.[selectedTabIndex];
|
|
131
|
+
return {
|
|
132
|
+
showList: currentTab?.show_list || [],
|
|
133
|
+
hideList: currentTab?.hide_list || [],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const { showList, hideList } = getCurrentLists();
|
|
139
|
+
|
|
140
|
+
// Convert to FilterValue format for ListingValues component
|
|
141
|
+
const showListValues = showList.map((item) => ({
|
|
142
|
+
id: item.value,
|
|
143
|
+
label: item.label,
|
|
144
|
+
visible: true,
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
const hideListValues = hideList.map((item) => ({
|
|
148
|
+
id: item.value,
|
|
149
|
+
label: item.label,
|
|
150
|
+
visible: false,
|
|
151
|
+
}));
|
|
152
|
+
|
|
153
|
+
const filteredListValues = hideListValues.filter((value) =>
|
|
154
|
+
value.label.toLowerCase().includes(searchTerm.toLowerCase())
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Update lists based on current mode
|
|
158
|
+
const updateLists = (
|
|
159
|
+
newShowList: ColumnItem[],
|
|
160
|
+
newHideList: ColumnItem[]
|
|
161
|
+
) => {
|
|
162
|
+
if (isColumnDefault) {
|
|
163
|
+
setColumnTabState({
|
|
164
|
+
...columnTabState,
|
|
165
|
+
show_list: newShowList,
|
|
166
|
+
hide_list: newHideList,
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
const updatedTabs = columnTabState?.tabs ? [...columnTabState.tabs] : [];
|
|
170
|
+
updatedTabs[selectedTabIndex] = {
|
|
171
|
+
...updatedTabs[selectedTabIndex],
|
|
172
|
+
show_list: newShowList,
|
|
173
|
+
hide_list: newHideList,
|
|
174
|
+
};
|
|
175
|
+
setColumnTabState({
|
|
176
|
+
...columnTabState,
|
|
177
|
+
tabs: updatedTabs,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Drag and drop logic
|
|
183
|
+
const handleDragEnd = (event: DragEndEvent) => {
|
|
184
|
+
const { active, over } = event;
|
|
185
|
+
if (!over) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const currentContainer = active.data.current?.containerId;
|
|
190
|
+
const overContainer = over.data.current?.containerId;
|
|
191
|
+
if (!currentContainer || !overContainer) return;
|
|
192
|
+
|
|
193
|
+
const activeItem = [...showList, ...hideList].find(
|
|
194
|
+
(item) => item.value === String(active.id)
|
|
195
|
+
);
|
|
196
|
+
if (!activeItem) return;
|
|
197
|
+
|
|
198
|
+
let newShowList = [...showList];
|
|
199
|
+
let newHideList = [...hideList];
|
|
200
|
+
|
|
201
|
+
if (currentContainer === overContainer) {
|
|
202
|
+
// Reorder within the same list
|
|
203
|
+
if (currentContainer === "list") {
|
|
204
|
+
const oldIndex = newHideList.findIndex(
|
|
205
|
+
(item) => item.value === String(active.id)
|
|
206
|
+
);
|
|
207
|
+
const newIndex = newHideList.findIndex(
|
|
208
|
+
(item) => item.value === String(over.id)
|
|
209
|
+
);
|
|
210
|
+
if (oldIndex !== -1 && newIndex !== -1) {
|
|
211
|
+
const [removed] = newHideList.splice(oldIndex, 1);
|
|
212
|
+
newHideList.splice(newIndex, 0, removed);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
const oldIndex = newShowList.findIndex(
|
|
216
|
+
(item) => item.value === String(active.id)
|
|
217
|
+
);
|
|
218
|
+
const newIndex = newShowList.findIndex(
|
|
219
|
+
(item) => item.value === String(over.id)
|
|
220
|
+
);
|
|
221
|
+
if (oldIndex !== -1 && newIndex !== -1) {
|
|
222
|
+
const [removed] = newShowList.splice(oldIndex, 1);
|
|
223
|
+
newShowList.splice(newIndex, 0, removed);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
// Move between lists
|
|
228
|
+
if (currentContainer === "list" && overContainer === "tabs") {
|
|
229
|
+
// Move from hide to show
|
|
230
|
+
const idx = newHideList.findIndex(
|
|
231
|
+
(item) => item.value === String(active.id)
|
|
232
|
+
);
|
|
233
|
+
if (idx !== -1) {
|
|
234
|
+
newHideList.splice(idx, 1);
|
|
235
|
+
newShowList.push(activeItem);
|
|
236
|
+
}
|
|
237
|
+
} else if (currentContainer === "tabs" && overContainer === "list") {
|
|
238
|
+
// Move from show to hide
|
|
239
|
+
const idx = newShowList.findIndex(
|
|
240
|
+
(item) => item.value === String(active.id)
|
|
241
|
+
);
|
|
242
|
+
if (idx !== -1) {
|
|
243
|
+
newShowList.splice(idx, 1);
|
|
244
|
+
newHideList.push(activeItem);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
updateLists(newShowList, newHideList);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// Show All/Hide All logic
|
|
253
|
+
const handleShowAll = () => {
|
|
254
|
+
const newShowList = [...showList, ...hideList];
|
|
255
|
+
const newHideList: ColumnItem[] = [];
|
|
256
|
+
updateLists(newShowList, newHideList);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const handleHideAll = () => {
|
|
260
|
+
const newShowList: ColumnItem[] = [];
|
|
261
|
+
const newHideList = [...hideList, ...showList];
|
|
262
|
+
updateLists(newShowList, newHideList);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Tab change handler
|
|
266
|
+
const handleTabChange = (_: React.SyntheticEvent, newValue: number) => {
|
|
267
|
+
setSelectedTabIndex(newValue);
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<Box sx={{ maxHeight: "600px" }}>
|
|
272
|
+
<Box sx={{ maxHeight: "500px", borderRadius: 1, bgcolor: "white" }}>
|
|
273
|
+
<Grid container spacing={2}>
|
|
274
|
+
<Grid size={12}>
|
|
275
|
+
<Box sx={{ mb: 2 }}>
|
|
276
|
+
<Typography
|
|
277
|
+
variant="subtitle2"
|
|
278
|
+
sx={{ mb: 1, fontWeight: 500, color: "#0E0C0BE5" }}
|
|
279
|
+
>
|
|
280
|
+
Customize column by
|
|
281
|
+
</Typography>
|
|
282
|
+
<CustomToggleSwitchButton
|
|
283
|
+
buttons={TOGGLE_BUTTON_TABS}
|
|
284
|
+
value={isColumnDefault}
|
|
285
|
+
onChange={handleToggleChange}
|
|
286
|
+
/>
|
|
287
|
+
</Box>
|
|
288
|
+
</Grid>
|
|
289
|
+
|
|
290
|
+
{!isColumnDefault && (
|
|
291
|
+
<Grid size={12}>
|
|
292
|
+
<Box sx={{ borderBottom: 1, borderColor: "divider", mb: 2 }}>
|
|
293
|
+
<CustomTabs value={selectedTabIndex} onChange={handleTabChange}>
|
|
294
|
+
{quickTabStates?.show_list?.map((tab) => (
|
|
295
|
+
<Tab key={tab} label={tab} />
|
|
296
|
+
))}
|
|
297
|
+
</CustomTabs>
|
|
298
|
+
</Box>
|
|
299
|
+
</Grid>
|
|
300
|
+
)}
|
|
301
|
+
|
|
302
|
+
<DndContext
|
|
303
|
+
sensors={sensors}
|
|
304
|
+
collisionDetection={closestCenter}
|
|
305
|
+
onDragEnd={handleDragEnd}
|
|
306
|
+
>
|
|
307
|
+
<Grid container spacing={2} size={12}>
|
|
308
|
+
<ListingValues
|
|
309
|
+
buttonText="Show All"
|
|
310
|
+
onClick={handleShowAll}
|
|
311
|
+
headerText="Hidden in List"
|
|
312
|
+
filteredValues={filteredListValues}
|
|
313
|
+
searchTerm={searchTerm}
|
|
314
|
+
setSearchTerm={setSearchTerm}
|
|
315
|
+
containerId="list"
|
|
316
|
+
/>
|
|
317
|
+
<ListingValues
|
|
318
|
+
buttonText="Hide All"
|
|
319
|
+
onClick={handleHideAll}
|
|
320
|
+
headerText="Shown in List"
|
|
321
|
+
filteredValues={showListValues}
|
|
322
|
+
containerId="tabs"
|
|
323
|
+
/>
|
|
324
|
+
</Grid>
|
|
325
|
+
</DndContext>
|
|
326
|
+
</Grid>
|
|
327
|
+
</Box>
|
|
328
|
+
</Box>
|
|
329
|
+
);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
export default ColumnTab;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Button, ButtonProps } from "@mui/material";
|
|
2
|
+
import { dialogStyles } from "../style";
|
|
3
|
+
interface CustomButtonProps extends ButtonProps {}
|
|
4
|
+
|
|
5
|
+
const CustomButton = ({ ...props }: CustomButtonProps) => {
|
|
6
|
+
const customSx = { ...dialogStyles.dialogActionsButton, ...props.sx };
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<Button variant="contained" {...props} sx={customSx}>
|
|
10
|
+
{props.children}
|
|
11
|
+
</Button>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default CustomButton;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Dialog, Slide, styled } from "@mui/material";
|
|
2
|
+
import { dialogStyles } from "../style";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { TransitionProps } from "@mui/material/transitions";
|
|
5
|
+
|
|
6
|
+
export const CustomDialog = styled(Dialog)(({ theme }) => ({
|
|
7
|
+
"& .MuiPaper-root": {
|
|
8
|
+
borderRadius: 0,
|
|
9
|
+
height: "100%",
|
|
10
|
+
},
|
|
11
|
+
"& .MuiDialogContent-root": {
|
|
12
|
+
...dialogStyles.dialogContent,
|
|
13
|
+
padding: theme.spacing(2),
|
|
14
|
+
},
|
|
15
|
+
"& .MuiDialogActions-root": {
|
|
16
|
+
padding: theme.spacing(2),
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
export const DialogTransition = React.forwardRef(function Transition(
|
|
21
|
+
props: TransitionProps & {
|
|
22
|
+
children: React.ReactElement<any, any>;
|
|
23
|
+
},
|
|
24
|
+
ref: React.Ref<unknown>
|
|
25
|
+
) {
|
|
26
|
+
return <Slide direction="down" ref={ref} {...props} />;
|
|
27
|
+
});
|