@mohsinonxrm/pptb-fetchxml-studio 1.0.0 → 1.0.1

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 (77) hide show
  1. package/LICENSE +661 -0
  2. package/dist/assets/index-DD9fzkbz.js +232 -0
  3. package/dist/index.html +70 -0
  4. package/index.html +0 -1
  5. package/npm-shrinkwrap.json +6329 -0
  6. package/package.json +95 -51
  7. package/CHANGELOG.md +0 -120
  8. package/eslint.config.js +0 -23
  9. package/public/vite.svg +0 -1
  10. package/src/app/AppShell.tsx +0 -1733
  11. package/src/assets/20px-Microsoft_Office_Excel_(2025/342/200/223present).svg.png +0 -0
  12. package/src/assets/react.svg +0 -1
  13. package/src/features/fetchxml/api/dataverseMetadata.ts +0 -192
  14. package/src/features/fetchxml/api/excelExport.ts +0 -318
  15. package/src/features/fetchxml/api/formattedValues.ts +0 -107
  16. package/src/features/fetchxml/api/pptbClient.ts +0 -2635
  17. package/src/features/fetchxml/model/displaySettings.ts +0 -18
  18. package/src/features/fetchxml/model/fetchxml.ts +0 -346
  19. package/src/features/fetchxml/model/fetchxmlIntellisense.ts +0 -583
  20. package/src/features/fetchxml/model/fetchxmlParser.ts +0 -708
  21. package/src/features/fetchxml/model/layoutxml.ts +0 -372
  22. package/src/features/fetchxml/model/nodes.ts +0 -255
  23. package/src/features/fetchxml/model/operators.ts +0 -624
  24. package/src/features/fetchxml/model/treeUtils.ts +0 -174
  25. package/src/features/fetchxml/state/builderStore.tsx +0 -1160
  26. package/src/features/fetchxml/state/cache.ts +0 -393
  27. package/src/features/fetchxml/ui/Dialogs/BulkDeleteDialog.tsx +0 -352
  28. package/src/features/fetchxml/ui/Dialogs/DeleteConfirmDialog.tsx +0 -396
  29. package/src/features/fetchxml/ui/Dialogs/SaveViewDialog.tsx +0 -612
  30. package/src/features/fetchxml/ui/Dialogs/SolutionPicker.tsx +0 -114
  31. package/src/features/fetchxml/ui/Dialogs/WorkflowPickerDialog.tsx +0 -437
  32. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/AttributeEditor.tsx +0 -214
  33. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ConditionEditor.tsx +0 -533
  34. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FetchOptionsEditor.tsx +0 -296
  35. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FilterEditor.tsx +0 -106
  36. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/LinkEntityEditor.tsx +0 -433
  37. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/OrderEditor.tsx +0 -161
  38. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ValueOfPicker.tsx +0 -194
  39. package/src/features/fetchxml/ui/LeftPane/PropertiesPanel.tsx +0 -225
  40. package/src/features/fetchxml/ui/LeftPane/TreeView.tsx +0 -604
  41. package/src/features/fetchxml/ui/RightPane/AddColumnsPanel.tsx +0 -800
  42. package/src/features/fetchxml/ui/RightPane/ColumnConfigDialog.tsx +0 -170
  43. package/src/features/fetchxml/ui/RightPane/DataGridCellRenderers.tsx +0 -356
  44. package/src/features/fetchxml/ui/RightPane/EditColumnsPanel.tsx +0 -372
  45. package/src/features/fetchxml/ui/RightPane/FetchXmlEditor.tsx +0 -399
  46. package/src/features/fetchxml/ui/RightPane/FormattedValueUtils.ts +0 -189
  47. package/src/features/fetchxml/ui/RightPane/LayoutXmlViewer.tsx +0 -171
  48. package/src/features/fetchxml/ui/RightPane/PreviewTabs.tsx +0 -471
  49. package/src/features/fetchxml/ui/RightPane/ResultsCommandBar.tsx +0 -430
  50. package/src/features/fetchxml/ui/RightPane/ResultsGrid.tsx +0 -983
  51. package/src/features/fetchxml/ui/RightPane/XmlTextArea.tsx +0 -65
  52. package/src/features/fetchxml/ui/Settings/SettingsDrawer.tsx +0 -175
  53. package/src/features/fetchxml/ui/Toolbar/EntitySelector.tsx +0 -788
  54. package/src/features/fetchxml/ui/Toolbar/LoadViewPicker.tsx +0 -274
  55. package/src/features/fetchxml/ui/Toolbar/SaveViewButton.tsx +0 -174
  56. package/src/main.tsx +0 -11
  57. package/src/shared/components/AttributePicker.tsx +0 -138
  58. package/src/shared/components/BetweenInputPicker.tsx +0 -120
  59. package/src/shared/components/BooleanValuePicker.tsx +0 -165
  60. package/src/shared/components/DateTimeInputPicker.tsx +0 -170
  61. package/src/shared/components/DynamicValueList.tsx +0 -128
  62. package/src/shared/components/ExcelIcon.tsx +0 -30
  63. package/src/shared/components/MultiValuePicker.tsx +0 -178
  64. package/src/shared/components/NumericInputPicker.tsx +0 -156
  65. package/src/shared/components/OptionSetValuePicker.tsx +0 -150
  66. package/src/shared/components/RelationshipPicker.tsx +0 -268
  67. package/src/shared/contexts/ThemeContext.tsx +0 -19
  68. package/src/shared/hooks/useAccessMode.ts +0 -77
  69. package/src/shared/hooks/useLazyMetadata.ts +0 -132
  70. package/src/shared/hooks/usePptbContext.ts +0 -170
  71. package/src/shared/hooks/usePublisherFilter.ts +0 -214
  72. package/src/shared/hooks/useSolutionFilter.ts +0 -162
  73. package/src/shared/utils/debug.ts +0 -87
  74. package/tsconfig.app.json +0 -28
  75. package/tsconfig.json +0 -7
  76. package/tsconfig.node.json +0 -26
  77. 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
- }