@mohsinonxrm/pptb-fetchxml-studio 1.0.0
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.
- package/CHANGELOG.md +120 -0
- package/README.md +250 -0
- package/eslint.config.js +23 -0
- package/index.html +71 -0
- package/package.json +53 -0
- package/public/vite.svg +1 -0
- package/src/app/AppShell.tsx +1733 -0
- package/src/assets/20px-Microsoft_Office_Excel_(2025/342/200/223present).svg.png +0 -0
- package/src/assets/react.svg +1 -0
- package/src/features/fetchxml/api/dataverseMetadata.ts +192 -0
- package/src/features/fetchxml/api/excelExport.ts +318 -0
- package/src/features/fetchxml/api/formattedValues.ts +107 -0
- package/src/features/fetchxml/api/pptbClient.ts +2635 -0
- package/src/features/fetchxml/model/displaySettings.ts +18 -0
- package/src/features/fetchxml/model/fetchxml.ts +346 -0
- package/src/features/fetchxml/model/fetchxmlIntellisense.ts +583 -0
- package/src/features/fetchxml/model/fetchxmlParser.ts +708 -0
- package/src/features/fetchxml/model/layoutxml.ts +372 -0
- package/src/features/fetchxml/model/nodes.ts +255 -0
- package/src/features/fetchxml/model/operators.ts +624 -0
- package/src/features/fetchxml/model/treeUtils.ts +174 -0
- package/src/features/fetchxml/state/builderStore.tsx +1160 -0
- package/src/features/fetchxml/state/cache.ts +393 -0
- package/src/features/fetchxml/ui/Dialogs/BulkDeleteDialog.tsx +352 -0
- package/src/features/fetchxml/ui/Dialogs/DeleteConfirmDialog.tsx +396 -0
- package/src/features/fetchxml/ui/Dialogs/SaveViewDialog.tsx +612 -0
- package/src/features/fetchxml/ui/Dialogs/SolutionPicker.tsx +114 -0
- package/src/features/fetchxml/ui/Dialogs/WorkflowPickerDialog.tsx +437 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/AttributeEditor.tsx +214 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ConditionEditor.tsx +533 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FetchOptionsEditor.tsx +296 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/FilterEditor.tsx +106 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/LinkEntityEditor.tsx +433 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/OrderEditor.tsx +161 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel/editors/ValueOfPicker.tsx +194 -0
- package/src/features/fetchxml/ui/LeftPane/PropertiesPanel.tsx +225 -0
- package/src/features/fetchxml/ui/LeftPane/TreeView.tsx +604 -0
- package/src/features/fetchxml/ui/RightPane/AddColumnsPanel.tsx +800 -0
- package/src/features/fetchxml/ui/RightPane/ColumnConfigDialog.tsx +170 -0
- package/src/features/fetchxml/ui/RightPane/DataGridCellRenderers.tsx +356 -0
- package/src/features/fetchxml/ui/RightPane/EditColumnsPanel.tsx +372 -0
- package/src/features/fetchxml/ui/RightPane/FetchXmlEditor.tsx +399 -0
- package/src/features/fetchxml/ui/RightPane/FormattedValueUtils.ts +189 -0
- package/src/features/fetchxml/ui/RightPane/LayoutXmlViewer.tsx +171 -0
- package/src/features/fetchxml/ui/RightPane/PreviewTabs.tsx +471 -0
- package/src/features/fetchxml/ui/RightPane/ResultsCommandBar.tsx +430 -0
- package/src/features/fetchxml/ui/RightPane/ResultsGrid.tsx +983 -0
- package/src/features/fetchxml/ui/RightPane/XmlTextArea.tsx +65 -0
- package/src/features/fetchxml/ui/Settings/SettingsDrawer.tsx +175 -0
- package/src/features/fetchxml/ui/Toolbar/EntitySelector.tsx +788 -0
- package/src/features/fetchxml/ui/Toolbar/LoadViewPicker.tsx +274 -0
- package/src/features/fetchxml/ui/Toolbar/SaveViewButton.tsx +174 -0
- package/src/main.tsx +11 -0
- package/src/shared/components/AttributePicker.tsx +138 -0
- package/src/shared/components/BetweenInputPicker.tsx +120 -0
- package/src/shared/components/BooleanValuePicker.tsx +165 -0
- package/src/shared/components/DateTimeInputPicker.tsx +170 -0
- package/src/shared/components/DynamicValueList.tsx +128 -0
- package/src/shared/components/ExcelIcon.tsx +30 -0
- package/src/shared/components/MultiValuePicker.tsx +178 -0
- package/src/shared/components/NumericInputPicker.tsx +156 -0
- package/src/shared/components/OptionSetValuePicker.tsx +150 -0
- package/src/shared/components/RelationshipPicker.tsx +268 -0
- package/src/shared/contexts/ThemeContext.tsx +19 -0
- package/src/shared/hooks/useAccessMode.ts +77 -0
- package/src/shared/hooks/useLazyMetadata.ts +132 -0
- package/src/shared/hooks/usePptbContext.ts +170 -0
- package/src/shared/hooks/usePublisherFilter.ts +214 -0
- package/src/shared/hooks/useSolutionFilter.ts +162 -0
- package/src/shared/utils/debug.ts +87 -0
- package/tsconfig.app.json +28 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +7 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to FetchXML Studio will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-12-15
|
|
9
|
+
|
|
10
|
+
### 🎉 Initial Release
|
|
11
|
+
|
|
12
|
+
FetchXML Studio v1.0.0 - A powerful FetchXML query builder for PowerPlatform Toolbox.
|
|
13
|
+
|
|
14
|
+
### ✨ Features
|
|
15
|
+
|
|
16
|
+
#### Query Builder
|
|
17
|
+
- Tree-based visual query builder with hierarchical FetchXML structure
|
|
18
|
+
- Full entity, attribute, filter, order, and link-entity support
|
|
19
|
+
- Context-aware properties panel for each node type
|
|
20
|
+
- Nested filter groups with AND/OR logic
|
|
21
|
+
- Support for all FetchXML operators (60+ operators)
|
|
22
|
+
- Aggregate queries with groupby and distinct
|
|
23
|
+
- Query hints for performance optimization
|
|
24
|
+
|
|
25
|
+
#### Relationships & Joins
|
|
26
|
+
- Relationship picker with 1:N, N:1, N:N categorization
|
|
27
|
+
- Inner and outer join support
|
|
28
|
+
- Filter link-entity for any/all/not any/not all scenarios
|
|
29
|
+
- Value-of conditions for cross-entity comparisons
|
|
30
|
+
- Entity name conditions for outer join filtering
|
|
31
|
+
|
|
32
|
+
#### Results Grid
|
|
33
|
+
- Virtualized DataGrid for large datasets (react-window)
|
|
34
|
+
- Rich cell rendering for lookups, option sets, dates, currency
|
|
35
|
+
- Multi-column sorting (click + Shift+click)
|
|
36
|
+
- Row selection (single and multi-select)
|
|
37
|
+
- Resizable and reorderable columns
|
|
38
|
+
- Formatted values with raw value toggle
|
|
39
|
+
|
|
40
|
+
#### FetchXML Editor
|
|
41
|
+
- Monaco editor with XML syntax highlighting
|
|
42
|
+
- Bi-directional editing (visual ↔ XML)
|
|
43
|
+
- Parse FetchXML to visual builder
|
|
44
|
+
- Copy to clipboard
|
|
45
|
+
- LayoutXML preview tab
|
|
46
|
+
|
|
47
|
+
#### Views
|
|
48
|
+
- Load system and personal views
|
|
49
|
+
- Optimized view execution via SavedQuery/UserQuery APIs
|
|
50
|
+
- Save queries as personal views
|
|
51
|
+
- Update existing views
|
|
52
|
+
- Solution-aware save (add to solution)
|
|
53
|
+
|
|
54
|
+
#### Data Operations
|
|
55
|
+
- Export to Excel with native data types
|
|
56
|
+
- Delete selected records
|
|
57
|
+
- Bulk delete jobs (async)
|
|
58
|
+
- Run on-demand workflows on selection
|
|
59
|
+
- Batch progress tracking with ETA
|
|
60
|
+
|
|
61
|
+
#### User Experience
|
|
62
|
+
- Dark/Light theme support (follows PPTB theme)
|
|
63
|
+
- Lazy metadata loading
|
|
64
|
+
- Intelligent caching (per-session)
|
|
65
|
+
- Resizable split panes
|
|
66
|
+
- Keyboard shortcuts (Ctrl+Enter to execute)
|
|
67
|
+
|
|
68
|
+
#### Security
|
|
69
|
+
- Privilege-aware operations
|
|
70
|
+
- Export/Delete privilege checks
|
|
71
|
+
- Bulk delete privilege validation
|
|
72
|
+
- Workflow execution privilege checks
|
|
73
|
+
|
|
74
|
+
### 🏗️ Technical
|
|
75
|
+
|
|
76
|
+
- Built with React 19 and TypeScript 5.9
|
|
77
|
+
- Fluent UI v9 components
|
|
78
|
+
- Monaco Editor integration
|
|
79
|
+
- ExcelJS for native Excel export
|
|
80
|
+
- Vite build tooling
|
|
81
|
+
- PowerPlatform Toolbox integration via @pptb/types
|
|
82
|
+
|
|
83
|
+
### 📚 Documentation
|
|
84
|
+
|
|
85
|
+
- Comprehensive README with feature overview
|
|
86
|
+
- Debug logging system documentation
|
|
87
|
+
- Project structure guide
|
|
88
|
+
- Contributing guidelines
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Development History
|
|
93
|
+
|
|
94
|
+
### Pre-release commits (dev branch)
|
|
95
|
+
|
|
96
|
+
- `feat: Beta release enhancements - Settings, Export, and UX improvements`
|
|
97
|
+
- `feat(preview): add LayoutXML tab to preview pane`
|
|
98
|
+
- `feat(commands): add record action commands - delete, bulk delete, workflow`
|
|
99
|
+
- `feat(columns): Add/Edit Columns panels with related entity support`
|
|
100
|
+
- `feat(export): add Export to Excel with status feedback and privilege check`
|
|
101
|
+
- `feat(paging): fix paging with cookies and page size support`
|
|
102
|
+
- `feat(grid): multi-entity metadata & column display name fixes`
|
|
103
|
+
- `feat(builder): Sprint 1 - Foundation & Layout improvements`
|
|
104
|
+
- `feat(save): implement Save View functionality`
|
|
105
|
+
- `feat(sort): Add multi-column sort with FetchXML integration`
|
|
106
|
+
- `feat(results): Add Column from Results Grid`
|
|
107
|
+
- `feat(views): Load view LayoutXML for column configuration`
|
|
108
|
+
- `feat(layout): Add column resize and reorder`
|
|
109
|
+
- `feat(layout): Add LayoutXML foundation`
|
|
110
|
+
- `feat(filter): Add filter link-entity support for any/not any/all scenarios`
|
|
111
|
+
- `feat(condition): Add valueof cross-entity comparison`
|
|
112
|
+
- `feat(condition): Add valueof same-row column comparison`
|
|
113
|
+
- `feat(condition): Add entityname support for outer join filtering`
|
|
114
|
+
- `feat(views): Add Load View picker and optimized view execution`
|
|
115
|
+
- `feat(parser): Add FetchXML parser with Monaco editor dialog`
|
|
116
|
+
- `feat: Implement Phases 1-4 - DataGrid UI polish`
|
|
117
|
+
- `feat: add filter consistency, cascading validation, and global metadata caching`
|
|
118
|
+
- `feat(entity-selector): implement advanced filtering with publisher/solution multiselect`
|
|
119
|
+
- `feat(ui): add resizable panes with visual grip indicators and command bar`
|
|
120
|
+
- `Initial commit - setup main branch`
|
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# FetchXML Studio for PowerPlatform Toolbox
|
|
2
|
+
|
|
3
|
+
A powerful, modern FetchXML query builder and data explorer for [PowerPlatform Toolbox](https://github.com/PowerPlatformToolBox/desktop-app). Inspired by the XrmToolBox FetchXML Builder, reimagined with React 19, Fluent UI v9, and seamless Dataverse integration.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## ✨ Features
|
|
11
|
+
|
|
12
|
+
### 🔧 Visual Query Builder
|
|
13
|
+
- **Tree-based hierarchy** — Build FetchXML queries visually with entities, attributes, filters, orders, and link-entities
|
|
14
|
+
- **Smart property editors** — Context-aware panels for each node type (fetch options, conditions, relationships)
|
|
15
|
+
- **Full FetchXML support** — Aggregate queries, grouping, distinct, top/count, paging, and advanced hints
|
|
16
|
+
- **Nested filters** — Create complex AND/OR filter groups with unlimited nesting
|
|
17
|
+
- **Link-entity relationships** — Browse and add 1:N, N:1, and N:N relationships with inner/outer joins
|
|
18
|
+
|
|
19
|
+
### 📊 Results Grid
|
|
20
|
+
- **Virtualized DataGrid** — Handle large result sets with smooth scrolling (powered by react-window)
|
|
21
|
+
- **Rich cell rendering** — Power Apps-style display for lookups, option sets, dates, currency, and more
|
|
22
|
+
- **Multi-column sorting** — Click headers to sort; Shift+click for multi-column sort
|
|
23
|
+
- **Row selection** — Select single or multiple records for bulk operations
|
|
24
|
+
- **Resizable & reorderable columns** — Customize your view with drag-and-drop columns
|
|
25
|
+
- **Formatted values** — Display OData formatted values or raw values (configurable)
|
|
26
|
+
|
|
27
|
+
### 📝 FetchXML Editor
|
|
28
|
+
- **Monaco editor** — Full-featured XML editor with syntax highlighting and line numbers
|
|
29
|
+
- **Bi-directional editing** — Edit XML directly and parse back to the visual builder
|
|
30
|
+
- **Copy to clipboard** — One-click copy of generated FetchXML
|
|
31
|
+
- **LayoutXML preview** — See the column layout configuration
|
|
32
|
+
|
|
33
|
+
### 📥 Load & Save Views
|
|
34
|
+
- **Load system/personal views** — Browse and load existing Dataverse views
|
|
35
|
+
- **Optimized view execution** — Uses SavedQuery/UserQuery APIs for better performance
|
|
36
|
+
- **Save to Dataverse** — Save your queries as new personal views or update existing ones
|
|
37
|
+
- **Solution-aware** — Add views to solutions during save
|
|
38
|
+
|
|
39
|
+
### 📤 Export & Data Operations
|
|
40
|
+
- **Export to Excel** — Native Excel export with proper data types (numbers, dates, currencies)
|
|
41
|
+
- **Formatted value options** — Export formatted, raw, or both value types
|
|
42
|
+
- **Record deletion** — Delete selected records with confirmation
|
|
43
|
+
- **Bulk delete jobs** — Submit async bulk delete operations to Dataverse
|
|
44
|
+
- **Run workflows** — Execute on-demand workflows on selected records
|
|
45
|
+
|
|
46
|
+
### 🎨 User Experience
|
|
47
|
+
- **Dark/Light themes** — Follows PowerPlatform Toolbox theme with Fluent UI tokens
|
|
48
|
+
- **Lazy metadata loading** — Loads only what's needed, when it's needed
|
|
49
|
+
- **Intelligent caching** — In-memory cache prevents duplicate API calls
|
|
50
|
+
- **Resizable panes** — Adjust the layout to your preference
|
|
51
|
+
- **Keyboard shortcuts** — Execute queries, copy XML, and more
|
|
52
|
+
|
|
53
|
+
### 🔒 Privilege-Aware
|
|
54
|
+
- **Security checks** — Validates user privileges before operations
|
|
55
|
+
- **Export privilege check** — Only shows export option if user has access
|
|
56
|
+
- **Delete privilege check** — Validates delete permissions per entity
|
|
57
|
+
|
|
58
|
+
## 🖼️ Interface Overview
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
62
|
+
│ [Entity Selector ▼] [Load View ▼] [Save View] [⚙ Settings]│
|
|
63
|
+
├──────────────────────┬──────────────────────────────────────────────────┤
|
|
64
|
+
│ │ [FetchXML] [LayoutXML] [Results] [▶ Execute]│
|
|
65
|
+
│ Query Tree ├──────────────────────────────────────────────────┤
|
|
66
|
+
│ │ │
|
|
67
|
+
│ 📁 fetch │ Results Grid / Monaco Editor │
|
|
68
|
+
│ └─📁 entity │ │
|
|
69
|
+
│ ├─📋 attribute │ ┌────────────┬────────────┬──────────────┐ │
|
|
70
|
+
│ ├─📋 attribute │ │ Column 1 │ Column 2 │ Column 3 │ │
|
|
71
|
+
│ ├─🔽 order │ ├────────────┼────────────┼──────────────┤ │
|
|
72
|
+
│ ├─🔍 filter │ │ Value │ Value │ Value │ │
|
|
73
|
+
│ │ └─ condition │ │ Value │ Value │ Value │ │
|
|
74
|
+
│ └─🔗 link-entity│ └────────────┴────────────┴──────────────┘ │
|
|
75
|
+
│ │ │
|
|
76
|
+
├──────────────────────┤ [◀ Prev] Page 1 of 10 [Next ▶] 100 records │
|
|
77
|
+
│ │ │
|
|
78
|
+
│ Properties Panel │ [+ Add Columns] [✎ Edit Columns] [⬇ Export] │
|
|
79
|
+
│ (context-aware) │ [🗑 Delete] [Bulk Delete] [⚡ Run Workflow] │
|
|
80
|
+
│ │ │
|
|
81
|
+
└──────────────────────┴──────────────────────────────────────────────────┘
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 🚀 Getting Started
|
|
85
|
+
|
|
86
|
+
### Prerequisites
|
|
87
|
+
- [PowerPlatform Toolbox](https://github.com/PowerPlatformToolBox/desktop-app) desktop application
|
|
88
|
+
- Connection to a Dataverse environment
|
|
89
|
+
|
|
90
|
+
### Installation
|
|
91
|
+
FetchXML Studio is available as a tool in PowerPlatform Toolbox. Install it from the tool gallery or load as a custom tool.
|
|
92
|
+
|
|
93
|
+
## 🛠️ Development
|
|
94
|
+
|
|
95
|
+
### Setup
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Clone the repository
|
|
99
|
+
git clone https://github.com/mohsinonxrm/pptb-fetchxml-studio.git
|
|
100
|
+
cd pptb-fetchxml-studio
|
|
101
|
+
|
|
102
|
+
# Install dependencies
|
|
103
|
+
npm install
|
|
104
|
+
|
|
105
|
+
# Start development server
|
|
106
|
+
npm run dev
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Building
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Production build
|
|
113
|
+
npm run build
|
|
114
|
+
|
|
115
|
+
# Preview production build
|
|
116
|
+
npm run preview
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Debug Logging
|
|
120
|
+
|
|
121
|
+
Enable debug logging in the browser console:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// Enable specific category
|
|
125
|
+
enableDebug("metadataAPI"); // API calls and responses
|
|
126
|
+
enableDebug("treeExpansion"); // Tree node operations
|
|
127
|
+
enableDebug("relationshipPicker"); // Relationship loading
|
|
128
|
+
enableDebug("linkEntityEditor"); // Link-entity configuration
|
|
129
|
+
enableDebug("propertiesPanel"); // Property editor routing
|
|
130
|
+
|
|
131
|
+
// Enable all
|
|
132
|
+
enableAllDebug();
|
|
133
|
+
|
|
134
|
+
// Disable
|
|
135
|
+
disableDebug("metadataAPI");
|
|
136
|
+
disableAllDebug();
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 📦 Tech Stack
|
|
140
|
+
|
|
141
|
+
| Technology | Purpose |
|
|
142
|
+
|------------|---------|
|
|
143
|
+
| **React 19** | UI framework with latest features (transitions, actions) |
|
|
144
|
+
| **TypeScript 5.9** | Type-safe development |
|
|
145
|
+
| **Vite** | Fast build tooling and HMR |
|
|
146
|
+
| **Fluent UI v9** | Microsoft's design system (Tree, DataGrid, Tabs, etc.) |
|
|
147
|
+
| **Monaco Editor** | VS Code's editor for XML editing |
|
|
148
|
+
| **react-window** | Virtualized list rendering for large datasets |
|
|
149
|
+
| **exceljs** | Native Excel file generation |
|
|
150
|
+
| **@pptb/types** | PowerPlatform Toolbox API types |
|
|
151
|
+
|
|
152
|
+
## 📁 Project Structure
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
src/
|
|
156
|
+
├── app/
|
|
157
|
+
│ └── AppShell.tsx # Main layout with split panes
|
|
158
|
+
├── features/fetchxml/
|
|
159
|
+
│ ├── api/
|
|
160
|
+
│ │ ├── pptbClient.ts # Dataverse API wrapper
|
|
161
|
+
│ │ ├── dataverseMetadata.ts # Metadata fetching
|
|
162
|
+
│ │ ├── excelExport.ts # Excel export logic
|
|
163
|
+
│ │ └── formattedValues.ts # OData formatted value handling
|
|
164
|
+
│ ├── model/
|
|
165
|
+
│ │ ├── nodes.ts # TypeScript node definitions
|
|
166
|
+
│ │ ├── fetchxml.ts # FetchXML generation
|
|
167
|
+
│ │ ├── fetchxmlParser.ts # FetchXML parsing
|
|
168
|
+
│ │ ├── layoutxml.ts # LayoutXML generation
|
|
169
|
+
│ │ └── operators.ts # Operator definitions by type
|
|
170
|
+
│ ├── state/
|
|
171
|
+
│ │ ├── builderStore.tsx # React context state management
|
|
172
|
+
│ │ └── cache.ts # Metadata caching
|
|
173
|
+
│ └── ui/
|
|
174
|
+
│ ├── LeftPane/ # Tree view and properties
|
|
175
|
+
│ ├── RightPane/ # Tabs, editor, grid
|
|
176
|
+
│ ├── Toolbar/ # Entity selector, view picker
|
|
177
|
+
│ ├── Dialogs/ # Delete, bulk delete, workflow
|
|
178
|
+
│ └── Settings/ # Display preferences
|
|
179
|
+
└── shared/
|
|
180
|
+
├── components/ # Reusable pickers
|
|
181
|
+
├── hooks/ # Custom React hooks
|
|
182
|
+
└── utils/ # Debug utilities
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 🔧 FetchXML Features Support
|
|
186
|
+
|
|
187
|
+
| Feature | Status |
|
|
188
|
+
|---------|--------|
|
|
189
|
+
| Basic queries | ✅ |
|
|
190
|
+
| Attributes (select columns) | ✅ |
|
|
191
|
+
| All-attributes | ✅ |
|
|
192
|
+
| Filters (and/or) | ✅ |
|
|
193
|
+
| Nested filters | ✅ |
|
|
194
|
+
| All condition operators | ✅ |
|
|
195
|
+
| Link-entity (joins) | ✅ |
|
|
196
|
+
| Inner/outer joins | ✅ |
|
|
197
|
+
| N:N relationships | ✅ |
|
|
198
|
+
| Orders (sorting) | ✅ |
|
|
199
|
+
| Multi-column sort | ✅ |
|
|
200
|
+
| Aggregate queries | ✅ |
|
|
201
|
+
| Groupby | ✅ |
|
|
202
|
+
| Distinct | ✅ |
|
|
203
|
+
| Top/Count | ✅ |
|
|
204
|
+
| Paging with cookies | ✅ |
|
|
205
|
+
| Value-of conditions | ✅ |
|
|
206
|
+
| Entity name on conditions | ✅ |
|
|
207
|
+
| Filter link-entity (any/all) | ✅ |
|
|
208
|
+
| Query hints | ✅ |
|
|
209
|
+
|
|
210
|
+
## 🤝 Contributing
|
|
211
|
+
|
|
212
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
213
|
+
|
|
214
|
+
1. Fork the repository
|
|
215
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
216
|
+
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
217
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
218
|
+
5. Open a Pull Request
|
|
219
|
+
|
|
220
|
+
### Commit Convention
|
|
221
|
+
This project follows [Conventional Commits](https://www.conventionalcommits.org/):
|
|
222
|
+
- `feat:` New feature
|
|
223
|
+
- `fix:` Bug fix
|
|
224
|
+
- `refactor:` Code refactoring
|
|
225
|
+
- `docs:` Documentation
|
|
226
|
+
- `chore:` Maintenance
|
|
227
|
+
|
|
228
|
+
## 📋 Roadmap
|
|
229
|
+
|
|
230
|
+
- [ ] Import/export query definitions (JSON)
|
|
231
|
+
- [ ] Quick query templates
|
|
232
|
+
- [ ] Query history
|
|
233
|
+
- [ ] Web API code generation
|
|
234
|
+
- [ ] Query performance insights
|
|
235
|
+
- [ ] Syntax validation in Monaco
|
|
236
|
+
|
|
237
|
+
## 📄 License
|
|
238
|
+
|
|
239
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
240
|
+
|
|
241
|
+
## 🙏 Acknowledgments
|
|
242
|
+
|
|
243
|
+
- [XrmToolBox FetchXML Builder](https://github.com/rappen/FetchXMLBuilder) - Original inspiration
|
|
244
|
+
- [PowerPlatform Toolbox](https://github.com/PowerPlatformToolBox/desktop-app) - Host platform
|
|
245
|
+
- [Fluent UI](https://react.fluentui.dev/) - UI component library
|
|
246
|
+
- [Monaco Editor](https://microsoft.github.io/monaco-editor/) - Code editor
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
Built with ❤️ for the Power Platform community
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
+
import tseslint from 'typescript-eslint'
|
|
6
|
+
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
globalIgnores(['dist']),
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.{ts,tsx}'],
|
|
12
|
+
extends: [
|
|
13
|
+
js.configs.recommended,
|
|
14
|
+
tseslint.configs.recommended,
|
|
15
|
+
reactHooks.configs['recommended-latest'],
|
|
16
|
+
reactRefresh.configs.vite,
|
|
17
|
+
],
|
|
18
|
+
languageOptions: {
|
|
19
|
+
ecmaVersion: 2020,
|
|
20
|
+
globals: globals.browser,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
])
|
package/index.html
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>FetchXML Studio</title>
|
|
8
|
+
<style>
|
|
9
|
+
/* Reset browser defaults for PPTB iframe */
|
|
10
|
+
* {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
html,
|
|
17
|
+
body {
|
|
18
|
+
margin: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
position: fixed;
|
|
24
|
+
top: 0;
|
|
25
|
+
left: 0;
|
|
26
|
+
right: 0;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#root {
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
position: absolute;
|
|
35
|
+
top: 0;
|
|
36
|
+
left: 0;
|
|
37
|
+
right: 0;
|
|
38
|
+
bottom: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Modern scrollbar styling */
|
|
42
|
+
::-webkit-scrollbar {
|
|
43
|
+
width: 8px;
|
|
44
|
+
height: 8px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::-webkit-scrollbar-track {
|
|
48
|
+
background: transparent;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar-thumb {
|
|
52
|
+
background: rgba(128, 128, 128, 0.4);
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
::-webkit-scrollbar-thumb:hover {
|
|
57
|
+
background: rgba(128, 128, 128, 0.6);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Firefox scrollbar */
|
|
61
|
+
* {
|
|
62
|
+
scrollbar-width: thin;
|
|
63
|
+
scrollbar-color: rgba(128, 128, 128, 0.4) transparent;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
</head>
|
|
67
|
+
<body>
|
|
68
|
+
<div id="root"></div>
|
|
69
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
70
|
+
</body>
|
|
71
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mohsinonxrm/pptb-fetchxml-studio",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"cspExceptions": {
|
|
6
|
+
"connect-src": [
|
|
7
|
+
"https://*.dynamics.com",
|
|
8
|
+
"https://*.crm*.dynamics.com"
|
|
9
|
+
],
|
|
10
|
+
"script-src": [
|
|
11
|
+
"https://cdn.jsdelivr.net"
|
|
12
|
+
],
|
|
13
|
+
"style-src": [
|
|
14
|
+
"https://cdn.jsdelivr.net"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "vite",
|
|
19
|
+
"build": "tsc -b && vite build",
|
|
20
|
+
"lint": "eslint .",
|
|
21
|
+
"preview": "vite preview"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@fluentui-contrib/react-data-grid-react-window": "^1.4.1",
|
|
25
|
+
"@fluentui/react-calendar-compat": "^0.3.14",
|
|
26
|
+
"@fluentui/react-components": "^9.72.4",
|
|
27
|
+
"@fluentui/react-datepicker-compat": "^0.6.19",
|
|
28
|
+
"@fluentui/react-icons": "^2.0.313",
|
|
29
|
+
"@fluentui/react-timepicker-compat": "^0.4.24",
|
|
30
|
+
"@monaco-editor/react": "^4.7.0",
|
|
31
|
+
"exceljs": "^4.4.0",
|
|
32
|
+
"react": "^19.1.1",
|
|
33
|
+
"react-dom": "^19.1.1",
|
|
34
|
+
"react-window": "^2.2.3"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@eslint/js": "^9.36.0",
|
|
38
|
+
"@pptb/types": "^1.0.7",
|
|
39
|
+
"@types/node": "^24.6.0",
|
|
40
|
+
"@types/react": "^19.1.16",
|
|
41
|
+
"@types/react-dom": "^19.1.9",
|
|
42
|
+
"@types/react-window": "^1.8.8",
|
|
43
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
44
|
+
"eslint": "^9.36.0",
|
|
45
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
46
|
+
"eslint-plugin-react-refresh": "^0.4.22",
|
|
47
|
+
"globals": "^16.4.0",
|
|
48
|
+
"monaco-editor": "^0.54.0",
|
|
49
|
+
"typescript": "~5.9.3",
|
|
50
|
+
"typescript-eslint": "^8.45.0",
|
|
51
|
+
"vite": "^7.1.12"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/public/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|