@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,396 +0,0 @@
1
- /**
2
- * Delete Confirmation Dialog
3
- * Shows confirmation before deleting records
4
- * Supports batch delete with progress tracking and ETA
5
- */
6
-
7
- import { useCallback, useState, useEffect } from "react";
8
- import {
9
- Dialog,
10
- DialogSurface,
11
- DialogTitle,
12
- DialogBody,
13
- DialogContent,
14
- DialogActions,
15
- Button,
16
- Text,
17
- Spinner,
18
- makeStyles,
19
- tokens,
20
- ProgressBar,
21
- MessageBar,
22
- MessageBarBody,
23
- MessageBarTitle,
24
- } from "@fluentui/react-components";
25
- import {
26
- Warning20Regular,
27
- CheckmarkCircle20Regular,
28
- DismissCircle20Regular,
29
- } from "@fluentui/react-icons";
30
- import type { BatchDeleteProgress, BatchDeleteResult } from "../../api/pptbClient";
31
-
32
- const useStyles = makeStyles({
33
- content: {
34
- display: "flex",
35
- flexDirection: "column",
36
- gap: tokens.spacingVerticalM,
37
- },
38
- warningRow: {
39
- display: "flex",
40
- alignItems: "center",
41
- gap: tokens.spacingHorizontalS,
42
- color: tokens.colorPaletteRedForeground1,
43
- },
44
- successRow: {
45
- display: "flex",
46
- alignItems: "center",
47
- gap: tokens.spacingHorizontalS,
48
- color: tokens.colorPaletteGreenForeground1,
49
- },
50
- recordInfo: {
51
- backgroundColor: tokens.colorNeutralBackground3,
52
- padding: tokens.spacingVerticalS,
53
- borderRadius: tokens.borderRadiusMedium,
54
- },
55
- errorMessage: {
56
- color: tokens.colorPaletteRedForeground1,
57
- marginTop: tokens.spacingVerticalS,
58
- },
59
- progressSection: {
60
- display: "flex",
61
- flexDirection: "column",
62
- gap: tokens.spacingVerticalS,
63
- },
64
- progressStats: {
65
- display: "flex",
66
- justifyContent: "space-between",
67
- alignItems: "center",
68
- marginTop: tokens.spacingVerticalXS,
69
- },
70
- eta: {
71
- color: tokens.colorNeutralForeground3,
72
- fontSize: tokens.fontSizeBase200,
73
- },
74
- resultSummary: {
75
- display: "flex",
76
- flexDirection: "column",
77
- gap: tokens.spacingVerticalXS,
78
- },
79
- });
80
-
81
- export interface DeleteConfirmDialogProps {
82
- /** Whether the dialog is open */
83
- open: boolean;
84
- /** Record display name or description */
85
- recordName?: string;
86
- /** Entity display name */
87
- entityDisplayName?: string;
88
- /** Number of records to delete (for multi-select) */
89
- recordCount: number;
90
- /** Called when dialog is closed */
91
- onClose: () => void;
92
- /** Called when delete is confirmed - returns batch result for batch deletes */
93
- onConfirm: () => Promise<BatchDeleteResult | void>;
94
- /** Progress callback for batch deletes */
95
- onProgress?: BatchDeleteProgress;
96
- }
97
-
98
- type DialogState = "confirm" | "deleting" | "success" | "partial" | "error";
99
-
100
- export function DeleteConfirmDialog({
101
- open,
102
- recordName,
103
- entityDisplayName,
104
- recordCount,
105
- onClose,
106
- onConfirm,
107
- onProgress,
108
- }: DeleteConfirmDialogProps) {
109
- const styles = useStyles();
110
- const [state, setState] = useState<DialogState>("confirm");
111
- const [error, setError] = useState<string | null>(null);
112
- const [result, setResult] = useState<BatchDeleteResult | null>(null);
113
- const [progress, setProgress] = useState<BatchDeleteProgress | null>(null);
114
-
115
- // Update progress from prop
116
- useEffect(() => {
117
- if (onProgress) {
118
- setProgress(onProgress);
119
- }
120
- }, [onProgress]);
121
-
122
- const handleConfirm = useCallback(async () => {
123
- setState("deleting");
124
- setError(null);
125
- setProgress(null);
126
- setResult(null);
127
- try {
128
- const res = await onConfirm();
129
- if (res) {
130
- // Batch delete result
131
- setResult(res);
132
- if (res.failed === 0) {
133
- setState("success");
134
- } else if (res.succeeded === 0) {
135
- setState("error");
136
- setError(`All ${res.failed} delete(s) failed`);
137
- } else {
138
- setState("partial");
139
- }
140
- } else {
141
- // Simple delete (void return)
142
- setState("success");
143
- }
144
- } catch (err) {
145
- setError(err instanceof Error ? err.message : "Failed to delete record(s)");
146
- setState("error");
147
- }
148
- }, [onConfirm]);
149
-
150
- const handleClose = useCallback(() => {
151
- if (state !== "deleting") {
152
- setState("confirm");
153
- setError(null);
154
- setResult(null);
155
- setProgress(null);
156
- onClose();
157
- }
158
- }, [state, onClose]);
159
-
160
- /**
161
- * Intelligently format ETA based on duration:
162
- * - < 1 minute: show seconds
163
- * - < 1 hour: show minutes and seconds
164
- * - < 12 hours: show hours and minutes
165
- * - >= 12 hours: show estimated completion date/time
166
- */
167
- const formatEta = (seconds: number): string => {
168
- if (seconds < 60) {
169
- return `~${seconds}s remaining`;
170
- }
171
-
172
- const minutes = Math.floor(seconds / 60);
173
- const hours = Math.floor(minutes / 60);
174
-
175
- if (minutes < 60) {
176
- const secs = seconds % 60;
177
- return `~${minutes}m ${secs}s remaining`;
178
- }
179
-
180
- if (hours < 12) {
181
- const mins = minutes % 60;
182
- return `~${hours}h ${mins}m remaining`;
183
- }
184
-
185
- // >= 12 hours: show estimated completion date/time
186
- const completionDate = new Date(Date.now() + seconds * 1000);
187
- const isToday = completionDate.toDateString() === new Date().toDateString();
188
- const isTomorrow =
189
- completionDate.toDateString() === new Date(Date.now() + 86400000).toDateString();
190
-
191
- const timeStr = completionDate.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
192
-
193
- if (isToday) {
194
- return `Est. completion: today at ${timeStr}`;
195
- } else if (isTomorrow) {
196
- return `Est. completion: tomorrow at ${timeStr}`;
197
- } else {
198
- const dateStr = completionDate.toLocaleDateString([], { month: "short", day: "numeric" });
199
- return `Est. completion: ${dateStr} at ${timeStr}`;
200
- }
201
- };
202
-
203
- const isSingle = recordCount === 1;
204
- const title = isSingle ? "Delete Record" : `Delete ${recordCount} Records`;
205
- const message = isSingle
206
- ? `Are you sure you want to delete this ${entityDisplayName || "record"}?`
207
- : `Are you sure you want to delete ${recordCount} ${entityDisplayName || "records"}?`;
208
-
209
- const renderContent = () => {
210
- switch (state) {
211
- case "confirm":
212
- return (
213
- <>
214
- <div className={styles.warningRow}>
215
- <Warning20Regular />
216
- <Text weight="semibold">This action cannot be undone.</Text>
217
- </div>
218
-
219
- <Text>{message}</Text>
220
-
221
- {isSingle && recordName && (
222
- <div className={styles.recordInfo}>
223
- <Text weight="semibold">{recordName}</Text>
224
- </div>
225
- )}
226
- </>
227
- );
228
-
229
- case "deleting":
230
- return (
231
- <div className={styles.progressSection}>
232
- <MessageBar intent="info">
233
- <MessageBarBody>
234
- <MessageBarTitle>Deleting records...</MessageBarTitle>
235
- {progress && (
236
- <>
237
- Processing batch {progress.batchesCompleted} of {progress.totalBatches}
238
- </>
239
- )}
240
- </MessageBarBody>
241
- </MessageBar>
242
-
243
- {progress && (
244
- <>
245
- <ProgressBar value={progress.completed / progress.total} max={1} />
246
- <div className={styles.progressStats}>
247
- <Text size={200}>
248
- {progress.completed} of {progress.total} ({progress.succeeded} succeeded,{" "}
249
- {progress.failed} failed)
250
- </Text>
251
- {progress.estimatedSecondsRemaining !== undefined &&
252
- progress.estimatedSecondsRemaining > 0 && (
253
- <Text className={styles.eta}>
254
- {formatEta(progress.estimatedSecondsRemaining)}
255
- </Text>
256
- )}
257
- </div>
258
- </>
259
- )}
260
-
261
- {!progress && (
262
- <div
263
- style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}
264
- >
265
- <Spinner size="small" />
266
- <Text>Deleting...</Text>
267
- </div>
268
- )}
269
- </div>
270
- );
271
-
272
- case "success":
273
- return (
274
- <>
275
- <div className={styles.successRow}>
276
- <CheckmarkCircle20Regular />
277
- <Text weight="semibold">
278
- {result
279
- ? `Successfully deleted ${result.succeeded} record(s)!`
280
- : "Record(s) deleted successfully!"}
281
- </Text>
282
- </div>
283
- </>
284
- );
285
-
286
- case "partial":
287
- return (
288
- <>
289
- <MessageBar intent="warning">
290
- <MessageBarBody>
291
- <MessageBarTitle>Partial Success</MessageBarTitle>
292
- {result && (
293
- <>
294
- {result.succeeded} of {result.succeeded + result.failed} records deleted.
295
- {result.failed} failed.
296
- </>
297
- )}
298
- </MessageBarBody>
299
- </MessageBar>
300
-
301
- {result && result.errors.length > 0 && (
302
- <div className={styles.resultSummary}>
303
- <Text weight="semibold" size={200}>
304
- Errors:
305
- </Text>
306
- {result.errors.slice(0, 5).map((err, i) => (
307
- <Text key={i} size={200} className={styles.errorMessage}>
308
- {err}
309
- </Text>
310
- ))}
311
- {result.errors.length > 5 && (
312
- <Text size={200} className={styles.errorMessage}>
313
- ...and {result.errors.length - 5} more errors
314
- </Text>
315
- )}
316
- </div>
317
- )}
318
- </>
319
- );
320
-
321
- case "error":
322
- return (
323
- <>
324
- <div className={styles.warningRow}>
325
- <DismissCircle20Regular />
326
- <Text weight="semibold">Delete Failed</Text>
327
- </div>
328
-
329
- <Text className={styles.errorMessage}>{error}</Text>
330
-
331
- {result && result.errors.length > 0 && (
332
- <div className={styles.resultSummary}>
333
- <Text weight="semibold" size={200}>
334
- Errors:
335
- </Text>
336
- {result.errors.slice(0, 5).map((err, i) => (
337
- <Text key={i} size={200} className={styles.errorMessage}>
338
- {err}
339
- </Text>
340
- ))}
341
- {result.errors.length > 5 && (
342
- <Text size={200} className={styles.errorMessage}>
343
- ...and {result.errors.length - 5} more errors
344
- </Text>
345
- )}
346
- </div>
347
- )}
348
- </>
349
- );
350
- }
351
- };
352
-
353
- const renderActions = () => {
354
- switch (state) {
355
- case "confirm":
356
- return (
357
- <>
358
- <Button appearance="secondary" onClick={handleClose}>
359
- Cancel
360
- </Button>
361
- <Button appearance="primary" onClick={handleConfirm}>
362
- Delete
363
- </Button>
364
- </>
365
- );
366
-
367
- case "deleting":
368
- return (
369
- <Button appearance="secondary" disabled>
370
- Cancel
371
- </Button>
372
- );
373
-
374
- case "success":
375
- case "partial":
376
- case "error":
377
- return (
378
- <Button appearance="primary" onClick={handleClose}>
379
- Close
380
- </Button>
381
- );
382
- }
383
- };
384
-
385
- return (
386
- <Dialog open={open} onOpenChange={(_, data) => !data.open && handleClose()}>
387
- <DialogSurface>
388
- <DialogTitle>{title}</DialogTitle>
389
- <DialogBody>
390
- <DialogContent className={styles.content}>{renderContent()}</DialogContent>
391
- </DialogBody>
392
- <DialogActions>{renderActions()}</DialogActions>
393
- </DialogSurface>
394
- </Dialog>
395
- );
396
- }