Skip to content

Commit 30fd40e

Browse files
authored
Merge pull request #823 from amitamrutiya/amit/workspace-sistent
Convert workspace data table into sistent component
2 parents d8f2d65 + 034da1f commit 30fd40e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+3216
-51
lines changed

src/constants/constants.ts

+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ export const CARIBBEAN_GREEN_FILL = '#00D3A9';
77
export const DEFAULT_STROKE = '#000';
88
export const DEFAULT_STROKE_WIDTH = '2';
99
export const CLOUD_URL = 'https://cloud.layer5.io';
10+
export const PLAYGROUND_MODES = {
11+
DESIGNER: 'design',
12+
OPERATOR: 'operator'
13+
} as const;

src/custom/CatalogDesignTable/CatalogDesignTable.tsx

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import _ from 'lodash';
3+
import { MUIDataTableColumn } from 'mui-datatables';
34
import { useCallback, useMemo, useRef } from 'react';
45
import { PublishIcon } from '../../icons';
56
import { CHARCOAL, useTheme } from '../../theme';
67
import { Pattern } from '../CustomCatalog/CustomCard';
78
import { ErrorBoundary } from '../ErrorBoundary';
9+
import { ColView } from '../Helpers/ResponsiveColumns/responsive-coulmns.tsx/responsive-column';
810
import PromptComponent from '../Prompt';
911
import { PromptRef } from '../Prompt/promt-component';
1012
import ResponsiveDataTable from '../ResponsiveDataTable';
@@ -13,7 +15,7 @@ import UnpublishTooltipIcon from './UnpublishTooltipIcon';
1315
interface CatalogDesignsTableProps {
1416
patterns: Pattern[];
1517
filter: any;
16-
columns: Array<any>;
18+
columns: MUIDataTableColumn[];
1719
totalCount: number;
1820
sortOrder: string;
1921
setSortOrder: (order: string) => void;
@@ -22,8 +24,9 @@ interface CatalogDesignsTableProps {
2224
page: number;
2325
setPage: (page: number) => void;
2426
columnVisibility: Record<string, boolean>;
25-
colViews: Record<string, boolean> | undefined;
27+
colViews: ColView[];
2628
handleBulkDeleteModal: (patterns: Pattern[], modalRef: React.RefObject<PromptRef>) => void;
29+
setSearch?: (search: string) => void;
2730
handleBulkpatternsDataUnpublishModal: (
2831
selected: any,
2932
patterns: Pattern[],
@@ -43,8 +46,9 @@ export const CatalogDesignsTable: React.FC<CatalogDesignsTableProps> = ({
4346
page = 0,
4447
setPage,
4548
columnVisibility = {},
46-
colViews = {},
49+
colViews = [],
4750
handleBulkDeleteModal,
51+
setSearch,
4852
handleBulkpatternsDataUnpublishModal
4953
}) => {
5054
const theme = useTheme();
@@ -60,7 +64,7 @@ export const CatalogDesignsTable: React.FC<CatalogDesignsTableProps> = ({
6064
return new Date(date).toLocaleDateString('en-US', dateOptions);
6165
}, []);
6266

63-
const processedColumns = useMemo(() => {
67+
const processedColumns: MUIDataTableColumn[] = useMemo(() => {
6468
return columns.map((col) => {
6569
const newCol = { ...col };
6670
if (!newCol.options) newCol.options = {};
@@ -105,6 +109,9 @@ export const CatalogDesignsTable: React.FC<CatalogDesignsTableProps> = ({
105109
case 'changeRowsPerPage':
106110
setPageSize(tableState.rowsPerPage);
107111
break;
112+
case 'search':
113+
setSearch && setSearch(tableState.searchText !== null ? tableState.searchText : '');
114+
break;
108115
case 'sort':
109116
if (
110117
sortInfo.length === 2 &&
@@ -123,7 +130,7 @@ export const CatalogDesignsTable: React.FC<CatalogDesignsTableProps> = ({
123130
break;
124131
}
125132
},
126-
[columns, setPage, setPageSize, setSortOrder, sortOrder]
133+
[columns, setPage, setSearch, setPageSize, setSortOrder, sortOrder]
127134
);
128135

129136
const options = useMemo(
@@ -136,6 +143,11 @@ export const CatalogDesignsTable: React.FC<CatalogDesignsTableProps> = ({
136143
rowsPerPage: pageSize,
137144
page,
138145
elevation: 0,
146+
sortOrder: {
147+
name: 'updated_at',
148+
direction: 'desc'
149+
},
150+
139151
onTableChange: handleTableChange,
140152
customToolbarSelect: _.isNil(filter)
141153
? (selected: any) => (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
import { MUIDataTableColumn, MUIDataTableMeta } from 'mui-datatables';
2+
import { PLAYGROUND_MODES } from '../../constants/constants';
3+
import { ChainIcon, CopyIcon, KanvasIcon, PublishIcon } from '../../icons';
4+
import Download from '../../icons/Download/Download';
5+
import { CHARCOAL } from '../../theme';
6+
import { downloadYaml, slugify } from '../CatalogDetail/helper';
7+
import { RESOURCE_TYPES } from '../CatalogDetail/types';
8+
import { Pattern } from '../CustomCatalog/CustomCard';
9+
import { ConditionalTooltip } from '../Helpers/CondtionalTooltip';
10+
import { ColView } from '../Helpers/ResponsiveColumns/responsive-coulmns.tsx';
11+
import { DataTableEllipsisMenu } from '../ResponsiveDataTable';
12+
import AuthorCell from './AuthorCell';
13+
import { getColumnValue } from './helper';
14+
import { L5DeleteIcon, NameDiv } from './style';
15+
16+
interface TableMeta extends MUIDataTableMeta {
17+
rowIndex: number;
18+
tableData: Pattern[];
19+
}
20+
21+
interface ColumnConfigProps {
22+
handleDeleteModal: (data: Pattern) => () => void;
23+
handlePublishModal: (data: Pattern) => void;
24+
handleUnpublishModal: (data: Pattern) => () => void;
25+
handleCopyUrl: (type: string, name: string, id: string) => void;
26+
handleClone: (name: string, id: string) => void;
27+
handleShowDetails: (designId: string, designName: string) => void;
28+
isDownloadAllowed: boolean;
29+
isCopyLinkAllowed: boolean;
30+
isDeleteAllowed: boolean;
31+
isPublishAllowed: boolean;
32+
isUnpublishAllowed: boolean;
33+
// for workspace designs table page only
34+
isFromWorkspaceTable?: boolean;
35+
isRemoveAllowed?: boolean;
36+
}
37+
38+
export const colViews: ColView[] = [
39+
['id', 'na'],
40+
['name', 'xs'],
41+
['first_name', 'xs'],
42+
['created_at', 'na'],
43+
['updated_at', 'l'],
44+
['visibility', 'l'],
45+
['user_id', 'na'],
46+
['actions', 'xs']
47+
];
48+
49+
export const createDesignsColumnsConfig = ({
50+
handleDeleteModal,
51+
handlePublishModal,
52+
handleUnpublishModal,
53+
handleCopyUrl,
54+
handleClone,
55+
handleShowDetails,
56+
isUnpublishAllowed,
57+
isCopyLinkAllowed,
58+
isDeleteAllowed,
59+
isPublishAllowed,
60+
isDownloadAllowed,
61+
isRemoveAllowed,
62+
isFromWorkspaceTable = false
63+
}: ColumnConfigProps): MUIDataTableColumn[] => {
64+
return [
65+
{
66+
name: 'id',
67+
label: 'ID',
68+
options: {
69+
filter: false,
70+
customBodyRender: (value: string) => <ConditionalTooltip value={value} maxLength={10} />
71+
}
72+
},
73+
{
74+
name: 'name',
75+
label: 'Pattern Name',
76+
options: {
77+
filter: false,
78+
sort: true,
79+
searchable: true,
80+
customBodyRender: (value: string, tableMeta: MUIDataTableMeta) => {
81+
const designId = (tableMeta as TableMeta).tableData[tableMeta.rowIndex]?.id ?? '';
82+
const designName = (tableMeta as TableMeta).tableData[tableMeta.rowIndex]?.name ?? '';
83+
84+
return <NameDiv onClick={() => handleShowDetails(designId, designName)}>{value}</NameDiv>;
85+
}
86+
}
87+
},
88+
{
89+
name: 'first_name',
90+
label: 'Author',
91+
options: {
92+
filter: false,
93+
sort: true,
94+
searchable: true,
95+
customBodyRender: (_, tableMeta: MUIDataTableMeta) => {
96+
const firstName = getColumnValue(tableMeta as TableMeta, 'first_name');
97+
const lastName = getColumnValue(tableMeta as TableMeta, 'last_name');
98+
const avatar_url = getColumnValue(tableMeta as TableMeta, 'avatar_url');
99+
const user_id = getColumnValue(tableMeta as TableMeta, 'user_id');
100+
101+
return (
102+
<AuthorCell
103+
firstName={firstName}
104+
lastName={lastName}
105+
avatarUrl={avatar_url}
106+
userId={user_id}
107+
/>
108+
);
109+
}
110+
}
111+
},
112+
{
113+
name: 'created_at',
114+
label: 'Created At',
115+
options: {
116+
filter: false,
117+
sort: true,
118+
searchable: true,
119+
setCellHeaderProps: () => {
120+
return { align: 'center' };
121+
}
122+
}
123+
},
124+
{
125+
name: 'updated_at',
126+
label: 'Updated At',
127+
options: {
128+
filter: false,
129+
sort: true,
130+
searchable: true,
131+
setCellHeaderProps: () => {
132+
return { align: 'center' };
133+
}
134+
}
135+
},
136+
{
137+
name: 'visibility',
138+
label: 'Visibility',
139+
options: {
140+
filter: false,
141+
sort: false,
142+
searchable: true
143+
}
144+
},
145+
{
146+
name: 'user_id',
147+
label: 'User ID',
148+
options: {
149+
filter: false,
150+
sort: false,
151+
searchable: false
152+
}
153+
},
154+
{
155+
name: 'actions',
156+
label: 'Actions',
157+
options: {
158+
filter: false,
159+
sort: false,
160+
searchable: false,
161+
setCellHeaderProps: () => ({ align: 'center' as const }),
162+
setCellProps: () => ({ align: 'center' as const }),
163+
customBodyRender: function CustomBody(_, tableMeta: MUIDataTableMeta) {
164+
const rowIndex = (tableMeta as TableMeta).rowIndex;
165+
const rowData = (tableMeta as TableMeta).tableData[rowIndex];
166+
167+
const actionsList = [
168+
{
169+
title: 'Download',
170+
onClick: () => downloadYaml(rowData?.pattern_file, rowData?.name),
171+
disabled: !isDownloadAllowed,
172+
icon: <Download width={24} height={24} fill={CHARCOAL} />
173+
},
174+
{
175+
title: 'Copy Link',
176+
disabled: rowData.visibility === 'private' || !isCopyLinkAllowed,
177+
onClick: () => {
178+
handleCopyUrl(RESOURCE_TYPES.DESIGNS, rowData?.name, rowData?.id);
179+
},
180+
icon: <ChainIcon width={'24'} height={'24'} fill={CHARCOAL} />
181+
},
182+
{
183+
title: 'Open in playground',
184+
onClick: () => {
185+
window.open(
186+
`https://playground.meshery.io/extension/meshmap?mode=${
187+
PLAYGROUND_MODES.DESIGNER
188+
}&type=${RESOURCE_TYPES.DESIGNS}&id=${rowData?.id}&name=${slugify(
189+
rowData?.name
190+
)}`,
191+
'_blank'
192+
);
193+
},
194+
icon: <KanvasIcon width={24} height={24} primaryFill={CHARCOAL} />
195+
},
196+
{
197+
title: isFromWorkspaceTable ? 'Remove Design' : 'Delete',
198+
disabled: isFromWorkspaceTable ? !isRemoveAllowed : !isDeleteAllowed,
199+
onClick: () => handleDeleteModal(rowData)(),
200+
icon: <L5DeleteIcon />
201+
}
202+
];
203+
204+
const publishAction = {
205+
title: 'Publish',
206+
disabled: !isPublishAllowed,
207+
onClick: () => handlePublishModal(rowData),
208+
icon: <PublishIcon width={24} height={24} fill={CHARCOAL} />
209+
};
210+
211+
const unpublishAction = {
212+
title: 'Unpublish',
213+
onClick: () => handleUnpublishModal(rowData)(),
214+
disabled: !isUnpublishAllowed,
215+
icon: <PublishIcon width={24} height={24} fill={CHARCOAL} />
216+
};
217+
218+
const cloneAction = {
219+
title: 'Clone',
220+
onClick: () => handleClone(rowData?.name, rowData?.id),
221+
icon: <CopyIcon width={24} height={24} fill={CHARCOAL} />
222+
};
223+
224+
if (rowData.visibility === 'published') {
225+
actionsList.splice(0, 0, cloneAction);
226+
actionsList.splice(2, 0, unpublishAction);
227+
} else {
228+
actionsList.splice(1, 0, publishAction);
229+
}
230+
231+
return <DataTableEllipsisMenu actionsList={actionsList} />;
232+
}
233+
}
234+
}
235+
];
236+
};

src/custom/CatalogDesignTable/columnConfig.tsx

+2-8
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import { downloadFilter, downloadYaml } from '../CatalogDetail/helper';
1717
import { RESOURCE_TYPES } from '../CatalogDetail/types';
1818
import { Pattern } from '../CustomCatalog/CustomCard';
1919
import { ConditionalTooltip } from '../Helpers/CondtionalTooltip';
20+
import { ColView } from '../Helpers/ResponsiveColumns/responsive-coulmns.tsx/responsive-column';
2021
import { DataTableEllipsisMenu } from '../ResponsiveDataTable';
2122
import AuthorCell from './AuthorCell';
23+
import { getColumnValue } from './helper';
2224
import { NameDiv } from './style';
2325

24-
export type ColView = [string, 'na' | 'xs' | 'l'];
25-
2626
export const colViews: ColView[] = [
2727
['id', 'na'],
2828
['name', 'xs'],
@@ -83,12 +83,6 @@ export const createDesignColumns = ({
8383
showOpenPlayground
8484
}: ColumnConfigProps): MUIDataTableColumn[] => {
8585
const cleanedType = type?.replace('my-', '').replace(/s$/, '');
86-
const getColumnValue = (tableMeta: MUIDataTableMeta, targetColumn: string): any => {
87-
//@ts-ignore
88-
const rowData = tableMeta.tableData[tableMeta.rowIndex] as Pattern;
89-
return (rowData as any)[targetColumn] || '';
90-
};
91-
9286
return [
9387
{
9488
name: 'id',
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
3+
export const getColumnValue = (tableMeta: any, targetColumn: string): any => {
4+
const rowData = tableMeta.tableData[tableMeta.rowIndex];
5+
return (rowData as any)[targetColumn] || '';
6+
};
+12-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import AuthorCell from './AuthorCell';
22
import CatalogDesignsTable from './CatalogDesignTable';
33
import { colViews, createDesignColumns } from './columnConfig';
4+
import {
5+
createDesignsColumnsConfig,
6+
colViews as designColumnsColViews
7+
} from './DesignTableColumnConfig';
48
export { TableVisibilityControl } from './TableVisibilityControl';
59
export { ViewSwitch } from './ViewSwitch';
6-
export { AuthorCell, CatalogDesignsTable, colViews, createDesignColumns };
10+
export {
11+
AuthorCell,
12+
CatalogDesignsTable,
13+
colViews,
14+
createDesignColumns,
15+
createDesignsColumnsConfig,
16+
designColumnsColViews
17+
};

0 commit comments

Comments
 (0)