@mohsinonxrm/pptb-fetchxml-studio 1.0.0 → 1.0.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.
Files changed (78) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +1 -1
  3. package/dist/assets/index-DD9fzkbz.js +232 -0
  4. package/dist/index.html +70 -0
  5. package/index.html +0 -1
  6. package/npm-shrinkwrap.json +6329 -0
  7. package/package.json +95 -51
  8. package/CHANGELOG.md +0 -120
  9. package/eslint.config.js +0 -23
  10. package/public/vite.svg +0 -1
  11. package/src/app/AppShell.tsx +0 -1733
  12. package/src/assets/20px-Microsoft_Office_Excel_(2025/342/200/223present).svg.png +0 -0
  13. package/src/assets/react.svg +0 -1
  14. package/src/features/fetchxml/api/dataverseMetadata.ts +0 -192
  15. package/src/features/fetchxml/api/excelExport.ts +0 -318
  16. package/src/features/fetchxml/api/formattedValues.ts +0 -107
  17. package/src/features/fetchxml/api/pptbClient.ts +0 -2635
  18. package/src/features/fetchxml/model/displaySettings.ts +0 -18
  19. package/src/features/fetchxml/model/fetchxml.ts +0 -346
  20. package/src/features/fetchxml/model/fetchxmlIntellisense.ts +0 -583
  21. package/src/features/fetchxml/model/fetchxmlParser.ts +0 -708
  22. package/src/features/fetchxml/model/layoutxml.ts +0 -372
  23. package/src/features/fetchxml/model/nodes.ts +0 -255
  24. package/src/features/fetchxml/model/operators.ts +0 -624
  25. package/src/features/fetchxml/model/treeUtils.ts +0 -174
  26. package/src/features/fetchxml/state/builderStore.tsx +0 -1160
  27. package/src/features/fetchxml/state/cache.ts +0 -393
  28. package/src/features/fetchxml/ui/Dialogs/BulkDeleteDialog.tsx +0 -352
  29. package/src/features/fetchxml/ui/Dialogs/DeleteConfirmDialog.tsx +0 -396
  30. package/src/features/fetchxml/ui/Dialogs/SaveViewDialog.tsx +0 -612
  31. package/src/features/fetchxml/ui/Dialogs/SolutionPicker.tsx +0 -114
  32. package/src/features/fetchxml/ui/Dialogs/WorkflowPickerDialog.tsx +0 -437
  33. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/AttributeEditor.tsx +0 -214
  34. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ConditionEditor.tsx +0 -533
  35. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FetchOptionsEditor.tsx +0 -296
  36. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FilterEditor.tsx +0 -106
  37. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/LinkEntityEditor.tsx +0 -433
  38. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/OrderEditor.tsx +0 -161
  39. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ValueOfPicker.tsx +0 -194
  40. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel.tsx +0 -225
  41. package/src/features/fetchxml/ui/LeftPane/TreeView.tsx +0 -604
  42. package/src/features/fetchxml/ui/RightPane/AddColumnsPanel.tsx +0 -800
  43. package/src/features/fetchxml/ui/RightPane/ColumnConfigDialog.tsx +0 -170
  44. package/src/features/fetchxml/ui/RightPane/DataGridCellRenderers.tsx +0 -356
  45. package/src/features/fetchxml/ui/RightPane/EditColumnsPanel.tsx +0 -372
  46. package/src/features/fetchxml/ui/RightPane/FetchXmlEditor.tsx +0 -399
  47. package/src/features/fetchxml/ui/RightPane/FormattedValueUtils.ts +0 -189
  48. package/src/features/fetchxml/ui/RightPane/LayoutXmlViewer.tsx +0 -171
  49. package/src/features/fetchxml/ui/RightPane/PreviewTabs.tsx +0 -471
  50. package/src/features/fetchxml/ui/RightPane/ResultsCommandBar.tsx +0 -430
  51. package/src/features/fetchxml/ui/RightPane/ResultsGrid.tsx +0 -983
  52. package/src/features/fetchxml/ui/RightPane/XmlTextArea.tsx +0 -65
  53. package/src/features/fetchxml/ui/Settings/SettingsDrawer.tsx +0 -175
  54. package/src/features/fetchxml/ui/Toolbar/EntitySelector.tsx +0 -788
  55. package/src/features/fetchxml/ui/Toolbar/LoadViewPicker.tsx +0 -274
  56. package/src/features/fetchxml/ui/Toolbar/SaveViewButton.tsx +0 -174
  57. package/src/main.tsx +0 -11
  58. package/src/shared/components/AttributePicker.tsx +0 -138
  59. package/src/shared/components/BetweenInputPicker.tsx +0 -120
  60. package/src/shared/components/BooleanValuePicker.tsx +0 -165
  61. package/src/shared/components/DateTimeInputPicker.tsx +0 -170
  62. package/src/shared/components/DynamicValueList.tsx +0 -128
  63. package/src/shared/components/ExcelIcon.tsx +0 -30
  64. package/src/shared/components/MultiValuePicker.tsx +0 -178
  65. package/src/shared/components/NumericInputPicker.tsx +0 -156
  66. package/src/shared/components/OptionSetValuePicker.tsx +0 -150
  67. package/src/shared/components/RelationshipPicker.tsx +0 -268
  68. package/src/shared/contexts/ThemeContext.tsx +0 -19
  69. package/src/shared/hooks/useAccessMode.ts +0 -77
  70. package/src/shared/hooks/useLazyMetadata.ts +0 -132
  71. package/src/shared/hooks/usePptbContext.ts +0 -170
  72. package/src/shared/hooks/usePublisherFilter.ts +0 -214
  73. package/src/shared/hooks/useSolutionFilter.ts +0 -162
  74. package/src/shared/utils/debug.ts +0 -87
  75. package/tsconfig.app.json +0 -28
  76. package/tsconfig.json +0 -7
  77. package/tsconfig.node.json +0 -26
  78. package/vite.config.ts +0 -7
@@ -1,352 +0,0 @@
1
- /**
2
- * Bulk Delete Dialog
3
- * Shows confirmation and progress for bulk delete operations
4
- * Supports both selected records and "all records from view" scenarios
5
- */
6
-
7
- import { useCallback, useState } from "react";
8
- import {
9
- Dialog,
10
- DialogSurface,
11
- DialogTitle,
12
- DialogBody,
13
- DialogContent,
14
- DialogActions,
15
- Button,
16
- Text,
17
- Input,
18
- Spinner,
19
- Link,
20
- makeStyles,
21
- tokens,
22
- Field,
23
- MessageBar,
24
- MessageBarBody,
25
- MessageBarTitle,
26
- Checkbox,
27
- } from "@fluentui/react-components";
28
- import {
29
- Warning20Regular,
30
- CheckmarkCircle20Regular,
31
- Copy20Regular,
32
- ErrorCircle20Regular,
33
- } from "@fluentui/react-icons";
34
-
35
- const useStyles = makeStyles({
36
- content: {
37
- display: "flex",
38
- flexDirection: "column",
39
- gap: tokens.spacingVerticalM,
40
- },
41
- warningRow: {
42
- display: "flex",
43
- alignItems: "center",
44
- gap: tokens.spacingHorizontalS,
45
- color: tokens.colorPaletteRedForeground1,
46
- },
47
- dangerWarning: {
48
- backgroundColor: tokens.colorPaletteRedBackground1,
49
- padding: tokens.spacingVerticalM,
50
- borderRadius: tokens.borderRadiusMedium,
51
- border: `1px solid ${tokens.colorPaletteRedBorder1}`,
52
- },
53
- successRow: {
54
- display: "flex",
55
- alignItems: "center",
56
- gap: tokens.spacingHorizontalS,
57
- color: tokens.colorPaletteGreenForeground1,
58
- },
59
- infoBox: {
60
- backgroundColor: tokens.colorNeutralBackground3,
61
- padding: tokens.spacingVerticalM,
62
- borderRadius: tokens.borderRadiusMedium,
63
- },
64
- jobUrlRow: {
65
- display: "flex",
66
- alignItems: "center",
67
- gap: tokens.spacingHorizontalS,
68
- marginTop: tokens.spacingVerticalS,
69
- },
70
- errorMessage: {
71
- color: tokens.colorPaletteRedForeground1,
72
- marginTop: tokens.spacingVerticalS,
73
- },
74
- confirmCheckbox: {
75
- marginTop: tokens.spacingVerticalS,
76
- },
77
- });
78
-
79
- export interface BulkDeleteDialogProps {
80
- /** Whether the dialog is open */
81
- open: boolean;
82
- /** Number of records to delete (0 means ALL from view) */
83
- recordCount: number;
84
- /** Entity display name */
85
- entityDisplayName?: string;
86
- /** Whether this is deleting ALL records from view (no selection) */
87
- isAllRecords?: boolean;
88
- /** Total records in view (when isAllRecords=true) */
89
- totalViewRecords?: number;
90
- /** Called when dialog is closed */
91
- onClose: () => void;
92
- /** Called when bulk delete is confirmed */
93
- onConfirm: (jobName: string) => Promise<{ asyncOperationId: string; jobUrl: string }>;
94
- }
95
-
96
- type DialogState = "confirm" | "submitting" | "success" | "error";
97
-
98
- export function BulkDeleteDialog({
99
- open,
100
- recordCount,
101
- entityDisplayName,
102
- isAllRecords = false,
103
- totalViewRecords: _totalViewRecords, // Intentionally unused - we don't show count for "all records"
104
- onClose,
105
- onConfirm,
106
- }: BulkDeleteDialogProps) {
107
- const styles = useStyles();
108
- const [state, setState] = useState<DialogState>("confirm");
109
- const [jobName, setJobName] = useState(
110
- `Bulk Delete ${entityDisplayName || "Records"} - ${new Date().toLocaleString()}`
111
- );
112
- const [error, setError] = useState<string | null>(null);
113
- const [result, setResult] = useState<{ asyncOperationId: string; jobUrl: string } | null>(null);
114
- const [copied, setCopied] = useState(false);
115
- const [confirmAllRecords, setConfirmAllRecords] = useState(false);
116
-
117
- const handleConfirm = useCallback(async () => {
118
- setState("submitting");
119
- setError(null);
120
- try {
121
- const res = await onConfirm(jobName);
122
- setResult(res);
123
- setState("success");
124
- } catch (err) {
125
- setError(err instanceof Error ? err.message : "Failed to submit bulk delete job");
126
- setState("error");
127
- }
128
- }, [onConfirm, jobName]);
129
-
130
- const handleClose = useCallback(() => {
131
- if (state !== "submitting") {
132
- setState("confirm");
133
- setError(null);
134
- setResult(null);
135
- setCopied(false);
136
- setConfirmAllRecords(false);
137
- onClose();
138
- }
139
- }, [state, onClose]);
140
-
141
- const handleCopyUrl = useCallback(async () => {
142
- if (result?.jobUrl) {
143
- try {
144
- await navigator.clipboard.writeText(result.jobUrl);
145
- setCopied(true);
146
- setTimeout(() => setCopied(false), 2000);
147
- } catch {
148
- // Fallback for older browsers
149
- const textArea = document.createElement("textarea");
150
- textArea.value = result.jobUrl;
151
- document.body.appendChild(textArea);
152
- textArea.select();
153
- document.execCommand("copy");
154
- document.body.removeChild(textArea);
155
- setCopied(true);
156
- setTimeout(() => setCopied(false), 2000);
157
- }
158
- }
159
- }, [result]);
160
-
161
- const handleOpenJob = useCallback(() => {
162
- if (result?.jobUrl) {
163
- window.open(result.jobUrl, "_blank");
164
- }
165
- }, [result]);
166
-
167
- const renderContent = () => {
168
- switch (state) {
169
- case "confirm":
170
- return (
171
- <>
172
- {isAllRecords ? (
173
- <>
174
- <MessageBar intent="error">
175
- <MessageBarBody>
176
- <MessageBarTitle>Danger Zone</MessageBarTitle>
177
- This will delete ALL records matching your current FetchXML query!
178
- </MessageBarBody>
179
- </MessageBar>
180
-
181
- <div className={styles.dangerWarning}>
182
- <div className={styles.warningRow}>
183
- <ErrorCircle20Regular />
184
- <Text weight="semibold">
185
- You have not selected any records. This will delete ALL records returned from
186
- the view.
187
- </Text>
188
- </div>
189
- <Text style={{ marginTop: tokens.spacingVerticalS, display: "block" }}>
190
- This is a destructive operation that cannot be undone. The bulk delete job will
191
- delete every record that matches your FetchXML query.
192
- </Text>
193
- </div>
194
-
195
- <Checkbox
196
- className={styles.confirmCheckbox}
197
- checked={confirmAllRecords}
198
- onChange={(_, data) => setConfirmAllRecords(data.checked === true)}
199
- label="I understand that this will delete ALL records from the view"
200
- />
201
- </>
202
- ) : (
203
- <>
204
- <div className={styles.warningRow}>
205
- <Warning20Regular />
206
- <Text weight="semibold">This action cannot be undone.</Text>
207
- </div>
208
-
209
- <Text>
210
- You are about to delete {recordCount} {entityDisplayName || "records"}. This will
211
- create a background job to process the deletion.
212
- </Text>
213
- </>
214
- )}
215
-
216
- <Field label="Job Name" required>
217
- <Input
218
- value={jobName}
219
- onChange={(_, data) => setJobName(data.value)}
220
- placeholder="Enter a name for the bulk delete job"
221
- />
222
- </Field>
223
-
224
- <Text size={200} style={{ color: tokens.colorNeutralForeground3 }}>
225
- You can track the progress of the job in the System Jobs area.
226
- </Text>
227
- </>
228
- );
229
-
230
- case "submitting":
231
- return (
232
- <div className={styles.infoBox}>
233
- <div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}>
234
- <Spinner size="small" />
235
- <Text>Submitting bulk delete job...</Text>
236
- </div>
237
- </div>
238
- );
239
-
240
- case "success":
241
- return (
242
- <>
243
- <div className={styles.successRow}>
244
- <CheckmarkCircle20Regular />
245
- <Text weight="semibold">Bulk delete job submitted successfully!</Text>
246
- </div>
247
-
248
- <div className={styles.infoBox}>
249
- <Text>
250
- The bulk delete job has been submitted and will run in the background. You can track
251
- its progress using the link below.
252
- </Text>
253
-
254
- {result?.jobUrl && (
255
- <div className={styles.jobUrlRow}>
256
- <Link onClick={handleOpenJob}>Open Job Status</Link>
257
- <Button
258
- appearance="subtle"
259
- size="small"
260
- icon={<Copy20Regular />}
261
- onClick={handleCopyUrl}
262
- >
263
- {copied ? "Copied!" : "Copy URL"}
264
- </Button>
265
- </div>
266
- )}
267
-
268
- {result?.asyncOperationId && (
269
- <Text
270
- size={200}
271
- style={{
272
- marginTop: tokens.spacingVerticalS,
273
- color: tokens.colorNeutralForeground3,
274
- }}
275
- >
276
- Job ID: {result.asyncOperationId}
277
- </Text>
278
- )}
279
- </div>
280
- </>
281
- );
282
-
283
- case "error":
284
- return (
285
- <>
286
- <div className={styles.warningRow}>
287
- <Warning20Regular />
288
- <Text weight="semibold">Failed to submit bulk delete job</Text>
289
- </div>
290
-
291
- <Text className={styles.errorMessage}>{error}</Text>
292
-
293
- <Text size={200}>
294
- Please check your permissions and try again. You need the prvBulkDelete privilege to
295
- submit bulk delete jobs.
296
- </Text>
297
- </>
298
- );
299
- }
300
- };
301
-
302
- const renderActions = () => {
303
- switch (state) {
304
- case "confirm":
305
- return (
306
- <>
307
- <Button appearance="secondary" onClick={handleClose}>
308
- Cancel
309
- </Button>
310
- <Button
311
- appearance="primary"
312
- onClick={handleConfirm}
313
- disabled={!jobName.trim() || (isAllRecords && !confirmAllRecords)}
314
- >
315
- Submit Bulk Delete
316
- </Button>
317
- </>
318
- );
319
-
320
- case "submitting":
321
- return (
322
- <Button appearance="secondary" disabled>
323
- Cancel
324
- </Button>
325
- );
326
-
327
- case "success":
328
- case "error":
329
- return (
330
- <Button appearance="primary" onClick={handleClose}>
331
- Close
332
- </Button>
333
- );
334
- }
335
- };
336
-
337
- return (
338
- <Dialog open={open} onOpenChange={(_, data) => !data.open && handleClose()}>
339
- <DialogSurface>
340
- <DialogTitle>
341
- {isAllRecords
342
- ? `Bulk Delete ALL ${entityDisplayName || "Records"} from View`
343
- : `Bulk Delete ${recordCount} Records`}
344
- </DialogTitle>
345
- <DialogBody>
346
- <DialogContent className={styles.content}>{renderContent()}</DialogContent>
347
- </DialogBody>
348
- <DialogActions>{renderActions()}</DialogActions>
349
- </DialogSurface>
350
- </Dialog>
351
- );
352
- }