Skip to content

Commit fb751c5

Browse files
authored
Merge pull request #997 from amitamrutiya/update-workspace
update workspace's design and teams table
2 parents 80ccb65 + d3e08f1 commit fb751c5

File tree

10 files changed

+503
-82
lines changed

10 files changed

+503
-82
lines changed

src/custom/CustomColumnVisibilityControl/CustomColumnVisibilityControl.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,14 @@ export function CustomColumnVisibilityControl({
5050
setOpen(false);
5151
};
5252

53-
const handleColumnVisibilityChange = (columnName: string, isVisible: boolean) => {
53+
const handleColumnVisibilityChange = (
54+
e: React.ChangeEvent<HTMLInputElement>,
55+
columnName: string
56+
) => {
57+
e.stopPropagation();
5458
customToolsProps.setColumnVisibility((prevState) => ({
5559
...prevState,
56-
[columnName]: isVisible
60+
[columnName]: e.target.checked
5761
}));
5862
};
5963

@@ -67,7 +71,7 @@ export function CustomColumnVisibilityControl({
6771
arrow
6872
/>
6973
<PopperListener
70-
style={style}
74+
style={{ ...style, zIndex: 1350 }}
7175
open={Boolean(anchorEl)}
7276
anchorEl={anchorEl}
7377
placement="bottom-end"
@@ -107,7 +111,7 @@ export function CustomColumnVisibilityControl({
107111
<Checkbox
108112
checked={customToolsProps.columnVisibility[col.name]}
109113
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
110-
handleColumnVisibilityChange(col.name, e.target.checked)
114+
handleColumnVisibilityChange(e, col.name)
111115
}
112116
/>
113117
}

src/custom/TransferModal/TransferList/TransferList.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,30 +180,34 @@ function TransferList({
180180
setChecked(newChecked);
181181
};
182182

183-
const handleAllRight = () => {
183+
const handleAllRight = (e: React.MouseEvent) => {
184+
e.stopPropagation();
184185
setRight(right.concat(left));
185186
setLeft([]);
186187
setLeftCount(0);
187188
setRightCount((prevRightCount: number) => prevRightCount + leftCount);
188189
};
189190

190-
const handleCheckedRight = () => {
191+
const handleCheckedRight = (e: React.MouseEvent) => {
192+
e.stopPropagation();
191193
setRight(right.concat(leftChecked));
192194
setLeft(not(left, leftChecked));
193195
setChecked(not(checked, leftChecked));
194196
setLeftCount((prevLeftCount: number) => prevLeftCount - leftChecked.length);
195197
setRightCount((prevRightCount: number) => prevRightCount + leftChecked.length);
196198
};
197199

198-
const handleCheckedLeft = () => {
200+
const handleCheckedLeft = (e: React.MouseEvent) => {
201+
e.stopPropagation();
199202
setLeft(left.concat(rightChecked));
200203
setRight(not(right, rightChecked));
201204
setChecked(not(checked, rightChecked));
202205
setRightCount((prevRightCount: number) => prevRightCount - rightChecked.length);
203206
setLeftCount((prevLeftCount: number) => prevLeftCount + rightChecked.length);
204207
};
205208

206-
const handleAllLeft = () => {
209+
const handleAllLeft = (e: React.MouseEvent) => {
210+
e.stopPropagation();
207211
setLeft(left.concat(right));
208212
setRight([]);
209213
setRightCount(0);

src/custom/Workspaces/DesignTable.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
33
import _ from 'lodash';
44
import React, { useEffect, useRef, useState } from 'react';
5-
import { Accordion, AccordionDetails, AccordionSummary, Typography } from '../../base';
5+
import { Accordion, AccordionDetails, AccordionSummary, Box, Typography } from '../../base';
66
import { DesignIcon } from '../../icons';
77
import { publishCatalogItemSchema } from '../../schemas';
88
import { useTheme } from '../../theme';
@@ -154,7 +154,7 @@ const DesignTable: React.FC<DesignTableProps> = ({
154154
return initialVisibility;
155155
});
156156

157-
const [expanded, setExpanded] = useState<boolean>(false);
157+
const [expanded, setExpanded] = useState<boolean>(true);
158158
const handleAccordionChange = () => {
159159
setExpanded(!expanded);
160160
};
@@ -187,9 +187,12 @@ const DesignTable: React.FC<DesignTableProps> = ({
187187

188188
const tableHeaderContent = (
189189
<TableHeader>
190-
<Typography variant="body1" fontWeight={'bold'}>
191-
Assigned Designs
192-
</Typography>
190+
<Box display={'flex'} alignItems="center" gap={1} width="100%">
191+
<DesignIcon height="1.5rem" width="1.5rem" />
192+
<Typography variant="body1" fontWeight={'bold'}>
193+
Assigned Designs
194+
</Typography>
195+
</Box>
193196
<TableRightActionHeader>
194197
<SearchBar
195198
onSearch={(value) => {
@@ -256,7 +259,7 @@ const DesignTable: React.FC<DesignTableProps> = ({
256259
open={designAssignment.assignModal}
257260
onClose={designAssignment.handleAssignModalClose}
258261
title={`Assign Designs to ${workspaceName}`}
259-
headerIcon={<DesignIcon height="40" width="40" secondaryFill="white" />}
262+
headerIcon={<DesignIcon height="40" width="40" />}
260263
name="Designs"
261264
assignableData={designAssignment.data}
262265
handleAssignedData={designAssignment.handleAssignData}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
/* eslint-disable @typescript-eslint/ban-ts-comment */
3+
import { FunctionComponent } from 'react';
4+
import { Autocomplete, Chip, TextField } from '../../base';
5+
6+
interface Environment {
7+
id: string;
8+
name: string;
9+
}
10+
11+
interface EnvironmentOption {
12+
label: string;
13+
value: string;
14+
}
15+
16+
interface WorkspaceEnvironmentSelectionProps {
17+
workspaceId: string;
18+
useAssignEnvironmentToWorkspaceMutation: any;
19+
useGetEnvironmentsOfWorkspaceQuery: any;
20+
useUnassignEnvironmentFromWorkspaceMutation: any;
21+
useNotificationHandlers: () => {
22+
handleSuccess: (message: string) => void;
23+
handleError: (message: string) => void;
24+
};
25+
isAssignedEnvironmentAllowed: boolean;
26+
}
27+
28+
const WorkspaceEnvironmentSelection: FunctionComponent<WorkspaceEnvironmentSelectionProps> = ({
29+
workspaceId,
30+
useAssignEnvironmentToWorkspaceMutation,
31+
useGetEnvironmentsOfWorkspaceQuery,
32+
useUnassignEnvironmentFromWorkspaceMutation,
33+
useNotificationHandlers,
34+
isAssignedEnvironmentAllowed
35+
}) => {
36+
const { handleSuccess, handleError } = useNotificationHandlers();
37+
38+
const { data: environmentsResponse, isLoading } = useGetEnvironmentsOfWorkspaceQuery({
39+
workspaceId,
40+
page: 0,
41+
pagesize: 'all',
42+
filter: '{"assigned":false}'
43+
});
44+
45+
const { data: environmentsOfWorkspace, isLoading: isEnvLoading } =
46+
useGetEnvironmentsOfWorkspaceQuery({
47+
workspaceId,
48+
page: 0,
49+
pagesize: 'all'
50+
});
51+
52+
const _environmentOptions: EnvironmentOption[] =
53+
environmentsResponse?.environments?.map((env: Environment) => ({
54+
label: env.name,
55+
value: env.id
56+
})) || [];
57+
58+
const _environmentValues: EnvironmentOption[] =
59+
environmentsOfWorkspace?.environments?.map((env: Environment) => ({
60+
label: env.name,
61+
value: env.id
62+
})) || [];
63+
64+
const [assignEnvironmentToWorkspace] = useAssignEnvironmentToWorkspaceMutation();
65+
const [unassignEnvironmentFromWorkspace] = useUnassignEnvironmentFromWorkspaceMutation();
66+
67+
const handleEnvironmentSelect = (
68+
selectedValues: EnvironmentOption[],
69+
unselectedValues: EnvironmentOption[]
70+
): void => {
71+
const selectedEnvs = selectedValues.map((env) => env.value);
72+
const unselectedEnvs = unselectedValues.map((env) => env.value);
73+
74+
if (unselectedEnvs.length > 0) {
75+
unselectedEnvs.forEach((envId) => {
76+
// Find environment name for the unassigned environment
77+
const envName =
78+
environmentsOfWorkspace?.environments?.find((env: Environment) => env.id === envId)
79+
?.name || 'Unknown';
80+
81+
unassignEnvironmentFromWorkspace({
82+
workspaceId,
83+
environmentId: envId
84+
})
85+
.unwrap()
86+
.then(() => handleSuccess(`Environment "${envName}" unassigned`))
87+
.catch((error: { data: string }) =>
88+
handleError(`Environment "${envName}" Unassign Error: ${error?.data}`)
89+
);
90+
});
91+
return;
92+
}
93+
94+
if (selectedEnvs.length > 0) {
95+
selectedEnvs.forEach((envId) => {
96+
if (_environmentValues.find((env) => env.value === envId)) {
97+
return;
98+
}
99+
100+
// Find environment name for the assigned environment
101+
const envName =
102+
environmentsResponse?.environments?.find((env: Environment) => env.id === envId)?.name ||
103+
'Unknown';
104+
105+
assignEnvironmentToWorkspace({
106+
workspaceId,
107+
environmentId: envId
108+
})
109+
.unwrap()
110+
.then(() => handleSuccess(`Environment "${envName}" assigned`))
111+
.catch((error: { data: string }) =>
112+
handleError(`Environment "${envName}" Assign Error: ${error?.data}`)
113+
);
114+
});
115+
return;
116+
}
117+
};
118+
119+
// Handle select change
120+
const handleChange = (
121+
_event: React.SyntheticEvent,
122+
selectedOptions: EnvironmentOption[]
123+
): void => {
124+
const currentValues = _environmentValues || [];
125+
const selectedValues = selectedOptions || [];
126+
127+
// Determine which items were selected and which were unselected
128+
const newlySelected = selectedValues.filter(
129+
(option) => !currentValues.some((item) => item.value === option.value)
130+
);
131+
132+
const newlyUnselected = currentValues.filter(
133+
(item) => !selectedValues.some((option) => option.value === item.value)
134+
);
135+
136+
handleEnvironmentSelect(newlySelected, newlyUnselected);
137+
};
138+
139+
return (
140+
<div onClick={(e) => e.stopPropagation()} style={{ marginBlock: '1rem', maxWidth: '15rem' }}>
141+
<Autocomplete
142+
//@ts-ignore
143+
multiple
144+
options={_environmentOptions}
145+
value={_environmentValues}
146+
loading={isLoading || isEnvLoading}
147+
//@ts-ignore
148+
onChange={handleChange}
149+
size="small"
150+
disableCloseOnSelect
151+
getOptionLabel={(option: unknown) => (option as EnvironmentOption).label}
152+
renderTags={(value: unknown) =>
153+
(value as EnvironmentOption[]).map((option) => (
154+
<Chip
155+
key={option.value}
156+
label={option.label}
157+
size="small"
158+
style={{
159+
margin: '0.15rem',
160+
borderRadius: '0.2rem'
161+
}}
162+
onDelete={() => {
163+
unassignEnvironmentFromWorkspace({
164+
workspaceId,
165+
environmentId: option.value
166+
});
167+
}}
168+
/>
169+
))
170+
}
171+
renderInput={(params) => <TextField {...params} placeholder="Assigned Environment" />}
172+
popupIcon={null}
173+
disabled={!isAssignedEnvironmentAllowed}
174+
/>
175+
</div>
176+
);
177+
};
178+
179+
export default WorkspaceEnvironmentSelection;

0 commit comments

Comments
 (0)