Skip to content

Commit 4cfeefb

Browse files
authored
Merge pull request #3441 from JohnDuprey/dev
table maintenance tweaks
2 parents c5a7891 + faa69ed commit 4cfeefb

File tree

1 file changed

+152
-23
lines changed

1 file changed

+152
-23
lines changed

src/pages/cipp/advanced/table-maintenance.js

Lines changed: 152 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,32 @@ import {
1717
SvgIcon,
1818
Tooltip,
1919
Typography,
20+
MenuItem,
21+
Select,
22+
Alert,
2023
} from "@mui/material";
2124
import { MagnifyingGlassIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
2225
import { Add, AddCircle, RemoveCircle, Sync, WarningAmber } from "@mui/icons-material";
2326
import CippFormComponent from "../../../components/CippComponents/CippFormComponent";
2427
import { useForm, useWatch } from "react-hook-form";
2528
import { CippApiDialog } from "../../../components/CippComponents/CippApiDialog";
2629
import { Grid } from "@mui/system";
30+
import CippButtonCard from "../../../components/CippCards/CippButtonCard";
2731

2832
const CustomAddEditRowDialog = ({ formControl, open, onClose, onSubmit, defaultValues }) => {
2933
const fields = useWatch({ control: formControl.control, name: "fields" });
3034

3135
useEffect(() => {
3236
if (open) {
33-
console.log(defaultValues);
3437
formControl.reset({
3538
fields: defaultValues.fields || [],
3639
});
3740
}
38-
}, [open, defaultValues]);
41+
}, [open, defaultValues, formControl]);
3942

4043
const addField = () => {
4144
formControl.reset({
42-
fields: [...fields, { name: "", value: "" }],
45+
fields: [...fields, { name: "", value: "", type: "textField" }],
4346
});
4447
};
4548

@@ -48,6 +51,11 @@ const CustomAddEditRowDialog = ({ formControl, open, onClose, onSubmit, defaultV
4851
formControl.reset({ fields: newFields });
4952
};
5053

54+
const handleTypeChange = (index, newType) => {
55+
const newFields = fields.map((field, i) => (i === index ? { ...field, type: newType } : field));
56+
formControl.reset({ fields: newFields });
57+
};
58+
5159
return (
5260
<Dialog fullWidth maxWidth="lg" open={open} onClose={onClose} width="xl">
5361
<DialogTitle>Add/Edit Row</DialogTitle>
@@ -65,14 +73,36 @@ const CustomAddEditRowDialog = ({ formControl, open, onClose, onSubmit, defaultV
6573
label="Name"
6674
/>
6775
</Box>
68-
<Box width="80%">
76+
<Box width="10%">
77+
<Select
78+
value={field.type}
79+
onChange={(e) => handleTypeChange(index, e.target.value)}
80+
fullWidth
81+
sx={{ py: 1 }}
82+
>
83+
<MenuItem value="textField">Text</MenuItem>
84+
<MenuItem value="number">Number</MenuItem>
85+
<MenuItem value="switch">Boolean</MenuItem>
86+
</Select>
87+
</Box>
88+
<Box width="50%">
6989
<CippFormComponent
70-
type="textField"
90+
type={field.type}
7191
name={`fields[${index}].value`}
7292
formControl={formControl}
7393
label="Value"
94+
sx={() => {
95+
if (field.type === "switch") {
96+
return { ml: 2 };
97+
} else if (field.type === "number") {
98+
return { width: "100%" };
99+
} else {
100+
return {};
101+
}
102+
}}
74103
/>
75104
</Box>
105+
76106
<IconButton onClick={() => removeField(index)}>
77107
<RemoveCircle />
78108
</IconButton>
@@ -86,8 +116,12 @@ const CustomAddEditRowDialog = ({ formControl, open, onClose, onSubmit, defaultV
86116
</Stack>
87117
</DialogContent>
88118
<DialogActions>
89-
<Button onClick={onClose}>Cancel</Button>
90-
<Button onClick={formControl.handleSubmit(onSubmit)}>Save</Button>
119+
<Button variant="outlined" onClick={onClose}>
120+
Cancel
121+
</Button>
122+
<Button variant="contained" onClick={formControl.handleSubmit(onSubmit)}>
123+
Save
124+
</Button>
91125
</DialogActions>
92126
</Dialog>
93127
);
@@ -103,14 +137,23 @@ const Page = () => {
103137
const deleteTableDialog = useDialog(); // Add dialog for deleting table
104138
const addEditRowDialog = useDialog(); // Add dialog for adding/editing row
105139
const [defaultAddEditValues, setDefaultAddEditValues] = useState({});
140+
const [tableFilterParams, setTableFilterParams] = useState({ First: 1000 });
106141
const formControl = useForm({
107142
mode: "onChange",
108143
});
144+
const [accordionExpanded, setAccordionExpanded] = useState(false);
109145

110146
const addEditFormControl = useForm({
111147
mode: "onChange",
112148
});
113149

150+
const filterFormControl = useForm({
151+
mode: "onChange",
152+
defaultValues: {
153+
First: 1000,
154+
},
155+
});
156+
114157
const tableFilter = useWatch({ control: formControl.control, name: "tableFilter" });
115158

116159
const fetchTables = ApiPostCall({
@@ -132,7 +175,7 @@ const Page = () => {
132175
data: {
133176
FunctionName: "Get-AzDataTableEntity",
134177
TableName: tableName,
135-
Parameters: { First: 1000 },
178+
Parameters: filterFormControl.getValues(),
136179
},
137180
});
138181
};
@@ -144,7 +187,7 @@ const Page = () => {
144187
data: {
145188
FunctionName: "Get-AzDataTableEntity",
146189
TableName: selectedTable,
147-
Parameters: { First: 1000 },
190+
Parameters: tableFilterParams,
148191
},
149192
});
150193
}
@@ -159,6 +202,20 @@ const Page = () => {
159202
fetchTables.mutate({ url: apiUrl, data: { FunctionName: "Get-AzDataTable", Parameters: {} } });
160203
};
161204

205+
const getSelectedProps = (data) => {
206+
if (data?.Property && data?.Property.length > 0) {
207+
var selectedProps = ["ETag", "PartitionKey", "RowKey"];
208+
data?.Property.map((prop) => {
209+
if (selectedProps.indexOf(prop.value) === -1) {
210+
selectedProps.push(prop.value);
211+
}
212+
});
213+
return selectedProps;
214+
} else {
215+
return [];
216+
}
217+
};
218+
162219
useEffect(() => {
163220
handleTableRefresh();
164221
}, []);
@@ -183,16 +240,11 @@ const Page = () => {
183240
{
184241
label: "",
185242
value: (
186-
<Stack direction="row" spacing={1} alignItems="center">
243+
<Stack direction="row" spacing={1} alignItems="center" sx={{ my: 1 }}>
187244
<SvgIcon fontSize="small">
188245
<MagnifyingGlassIcon />
189246
</SvgIcon>
190-
<CippFormComponent
191-
type="textField"
192-
name="tableFilter"
193-
formControl={formControl}
194-
label="Filter"
195-
/>
247+
<CippFormComponent type="textField" name="tableFilter" formControl={formControl} />
196248
</Stack>
197249
),
198250
},
@@ -203,19 +255,32 @@ const Page = () => {
203255
const sampleRow = tableData[0];
204256
return Object.keys(sampleRow)
205257
.filter((key) => key !== "ETag" && key !== "Timestamp")
206-
.map((key) => ({
207-
name: key,
208-
label: key,
209-
type: "textField",
210-
required: false,
211-
}));
258+
.map((key) => {
259+
const value = sampleRow[key];
260+
let type = "textField";
261+
if (typeof value === "number") {
262+
type = "number";
263+
} else if (typeof value === "boolean") {
264+
type = "switch";
265+
}
266+
return {
267+
name: key,
268+
label: key,
269+
type: type,
270+
required: false,
271+
};
272+
});
212273
};
213274

214275
return (
215276
<Container maxWidth="xl" sx={{ mt: 4 }}>
216277
<Typography variant="h4" gutterBottom>
217278
{pageTitle}
218279
</Typography>
280+
<Alert severity="warning" sx={{ mb: 2 }}>
281+
This page allows you to view and manage data in Azure Tables. This is advanced functionality
282+
that should only be used when directed by CyberDrain support.
283+
</Alert>
219284
<Grid container spacing={2}>
220285
<Grid item size={3}>
221286
<CippPropertyListCard
@@ -257,6 +322,60 @@ const Page = () => {
257322
<Grid item size={9}>
258323
{selectedTable && (
259324
<Box sx={{ width: "100%" }}>
325+
<CippButtonCard
326+
title="Table Filters"
327+
cardSx={{ mb: 2 }}
328+
accordionExpanded={accordionExpanded}
329+
component="accordion"
330+
CardButton={
331+
<Button
332+
variant="contained"
333+
color="primary"
334+
size="small"
335+
onClick={filterFormControl.handleSubmit((data) => {
336+
var properties = getSelectedProps(data);
337+
setTableFilterParams({ ...data, Property: properties });
338+
handleRefresh();
339+
setAccordionExpanded(false);
340+
})}
341+
>
342+
Apply Filters
343+
</Button>
344+
}
345+
>
346+
<Stack spacing={1}>
347+
<CippFormComponent
348+
type="textField"
349+
name="Filter"
350+
formControl={filterFormControl}
351+
label="OData Filter"
352+
/>
353+
<CippFormComponent
354+
type="autoComplete"
355+
name="Property"
356+
formControl={filterFormControl}
357+
label="Property"
358+
options={getTableFields().map((field) => ({
359+
label: field?.label,
360+
value: field?.name,
361+
}))}
362+
/>
363+
<Stack direction="row" spacing={1}>
364+
<CippFormComponent
365+
type="number"
366+
name="First"
367+
formControl={filterFormControl}
368+
label="First"
369+
/>
370+
<CippFormComponent
371+
type="number"
372+
name="Skip"
373+
formControl={filterFormControl}
374+
label="Skip"
375+
/>
376+
</Stack>
377+
</Stack>
378+
</CippButtonCard>
260379
<CippDataTable
261380
title={`${selectedTable}`}
262381
data={tableData}
@@ -273,6 +392,7 @@ const Page = () => {
273392
fields: getTableFields().map((field) => ({
274393
name: field?.name,
275394
value: "",
395+
type: field?.type,
276396
})),
277397
});
278398
addEditRowDialog.handleOpen();
@@ -313,7 +433,16 @@ const Page = () => {
313433
setDefaultAddEditValues({
314434
fields: Object.keys(row)
315435
.filter((key) => key !== "ETag" && key !== "Timestamp")
316-
.map((key) => ({ name: key, value: row[key] })),
436+
.map((key) => {
437+
const value = row[key];
438+
let type = "textField";
439+
if (typeof value === "number") {
440+
type = "number";
441+
} else if (typeof value === "boolean") {
442+
type = "switch";
443+
}
444+
return { name: key, value: value, type: type };
445+
}),
317446
});
318447
addEditRowDialog.handleOpen();
319448
},

0 commit comments

Comments
 (0)