@docyrus/docyrus 0.0.67 → 0.0.68
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/main.js +136 -136
- package/main.js.map +3 -3
- package/package.json +3 -3
- package/resources/pi-agent/extensions/pi-bash-live-view/widget.ts +2 -17
- package/resources/pi-agent/skills/docyrus-app-dev-react/references/component-selection-guide.md +42 -5
- package/resources/pi-agent/skills/docyrus-data-grid-page-design/SKILL.md +58 -0
- package/resources/pi-agent/skills/docyrus-data-grid-page-design/references/advanced-saved-view-query-patterns.md +158 -0
- package/resources/pi-agent/skills/docyrus-data-grid-page-design/references/hook-pages.md +183 -0
- package/resources/pi-agent/skills/docyrus-data-grid-page-design/references/manual-pages.md +145 -0
- package/resources/pi-agent/skills/docyrus-data-grid-page-design/references/tenant-and-users-providers.md +290 -0
- package/resources/pi-agent/skills/docyrus-record-detail-form-design/SKILL.md +54 -0
- package/resources/pi-agent/skills/docyrus-record-detail-form-design/references/advanced-inline-edit-and-renderers.md +140 -0
- package/resources/pi-agent/skills/docyrus-record-detail-form-design/references/field-type-mapping-and-fallbacks.md +150 -0
- package/resources/pi-agent/skills/docyrus-record-detail-form-design/references/hook-form-view.md +127 -0
- package/resources/pi-agent/skills/docyrus-record-detail-form-design/references/manual-form-detail-patterns.md +125 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docyrus/docyrus",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.68",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Docyrus API CLI",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"@clack/prompts": "^0.11.0",
|
|
15
15
|
"@ff-labs/fff-node": "0.6.4",
|
|
16
16
|
"@hono/node-server": "^1.19.13",
|
|
17
|
-
"@mariozechner/pi-ai": "0.70.
|
|
18
|
-
"@mariozechner/pi-coding-agent": "0.70.
|
|
17
|
+
"@mariozechner/pi-ai": "0.70.6",
|
|
18
|
+
"@mariozechner/pi-coding-agent": "0.70.6",
|
|
19
19
|
"@modelcontextprotocol/ext-apps": "^1.2.2",
|
|
20
20
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
21
21
|
"@mozilla/readability": "^0.6.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionContext } from '@mariozechner/pi-coding-agent';
|
|
2
|
+
import { truncateToWidth } from '@mariozechner/pi-tui';
|
|
2
3
|
import { snapshotToAnsiContentLines } from './terminal-emulator.ts';
|
|
3
4
|
import type { PtyTerminalSession } from './pty-session.ts';
|
|
4
5
|
|
|
@@ -37,23 +38,7 @@ export function buildTopBorder(title: string, innerWidth: number, elapsedMs: num
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
function fitAnsiLine(line: string, width: number): string {
|
|
40
|
-
|
|
41
|
-
let visible = 0;
|
|
42
|
-
let i = 0;
|
|
43
|
-
while (i < line.length && visible < width) {
|
|
44
|
-
if (line[i] === '\x1b' && line[i + 1] === '[') {
|
|
45
|
-
const match = line.slice(i).match(/^\x1b\[[0-9;]*m/);
|
|
46
|
-
if (match) {
|
|
47
|
-
out += match[0];
|
|
48
|
-
i += match[0].length;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
out += line[i];
|
|
53
|
-
visible += 1;
|
|
54
|
-
i += 1;
|
|
55
|
-
}
|
|
56
|
-
return `${out}\x1b[0m${' '.repeat(Math.max(0, width - visible))}`;
|
|
41
|
+
return `${truncateToWidth(line, width, '', true)}\x1b[0m`;
|
|
57
42
|
}
|
|
58
43
|
|
|
59
44
|
export function buildWidgetAnsiLines({
|
package/resources/pi-agent/skills/docyrus-app-dev-react/references/component-selection-guide.md
CHANGED
|
@@ -30,6 +30,7 @@ Mobile-first form → container="drawer" side="bottom"
|
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
**AwesomeDialog** props reference:
|
|
33
|
+
|
|
33
34
|
- `container`: `'modal'` | `'sheet'` | `'drawer'` — determines the dialog presentation
|
|
34
35
|
- `side`: `'left'` | `'right'` | `'top'` | `'bottom'` — positioning for sheet/drawer
|
|
35
36
|
- `size`: `'sm'` | `'default'` | `'lg'` | `'xl'` | `'full'` — size preset
|
|
@@ -43,6 +44,7 @@ Mobile-first form → container="drawer" side="bottom"
|
|
|
43
44
|
**Sub-components**: `AwesomeDialogHeader`, `AwesomeDialogBody`, `AwesomeDialogFooter`, `AwesomeDialogToolbar`
|
|
44
45
|
|
|
45
46
|
**Example — Small create form (task):**
|
|
47
|
+
|
|
46
48
|
```tsx
|
|
47
49
|
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right">
|
|
48
50
|
<AwesomeDialogHeader title="Create Task" icon="far-plus" />
|
|
@@ -55,6 +57,7 @@ Mobile-first form → container="drawer" side="bottom"
|
|
|
55
57
|
```
|
|
56
58
|
|
|
57
59
|
**Example — Large create form (project):**
|
|
60
|
+
|
|
58
61
|
```tsx
|
|
59
62
|
<AwesomeDialog open={open} onOpenChange={setOpen} container="modal" size="lg" fullscreenable>
|
|
60
63
|
<AwesomeDialogHeader title="Create Project" icon="far-folder-plus" />
|
|
@@ -78,6 +81,7 @@ Small items (tasks, contacts, comments) → AwesomeDialog with container="s
|
|
|
78
81
|
```
|
|
79
82
|
|
|
80
83
|
**Decision tree:**
|
|
84
|
+
|
|
81
85
|
```
|
|
82
86
|
Does the item have:
|
|
83
87
|
- Multiple tabs/sections?
|
|
@@ -92,6 +96,7 @@ Does the item have:
|
|
|
92
96
|
```
|
|
93
97
|
|
|
94
98
|
**Example — Task detail in AwesomeDialog:**
|
|
99
|
+
|
|
95
100
|
```tsx
|
|
96
101
|
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right" size="lg" fullscreenable>
|
|
97
102
|
<AwesomeDialogHeader
|
|
@@ -117,11 +122,13 @@ Does the item have:
|
|
|
117
122
|
**All forms must use** TanStack Form with the Docyrus form field system. Never use plain HTML forms or React Hook Form directly.
|
|
118
123
|
|
|
119
124
|
**Key components:**
|
|
125
|
+
|
|
120
126
|
- `DynamicFormField` — Auto-dispatches to the correct field type based on `IField.type`
|
|
121
127
|
- 47+ field types: text, number, email, url, phone, date, dateTime, time, select, multiSelect, status, relation, file, image, code, docEditor, and more
|
|
122
128
|
- Each field type has a dedicated `*FormField` component (e.g., `TextFormField`, `SelectFormField`, `DateFormField`)
|
|
123
129
|
|
|
124
130
|
**Form field pattern:**
|
|
131
|
+
|
|
125
132
|
```tsx
|
|
126
133
|
import { useForm } from '@tanstack/react-form'
|
|
127
134
|
import { TextFormField, SelectFormField, DateFormField } from '@docyrus/ui/components/form-fields'
|
|
@@ -141,12 +148,14 @@ const form = useForm({ defaultValues: { title: '', status: '', dueDate: '' } })
|
|
|
141
148
|
Use `EditableRecordDetail` for detail views where users can edit individual fields inline without opening a full form page. **Always enable `trackChanges`** to highlight changed fields and show a floating ActionBar. Always include an **"Edit All"** button in the header to switch to a full form editing experience.
|
|
142
149
|
|
|
143
150
|
**Key components:**
|
|
151
|
+
|
|
144
152
|
- `EditableRecordDetail` — Provider/wrapper that manages field state, change tracking, and save/cancel
|
|
145
153
|
- `EditableRecordDetailField` — Individual field that reads config from context, renders label + inline-editable value
|
|
146
154
|
- `EditableValue` — Lower-level single-field inline editor (used internally by EditableRecordDetailField)
|
|
147
155
|
- `useEditableRecordDetail()` — Hook to access form, values, changes, and save/cancel from within the provider
|
|
148
156
|
|
|
149
157
|
**How it works (with `trackChanges` enabled):**
|
|
158
|
+
|
|
150
159
|
1. Fields render as read-only `DynamicValue` display
|
|
151
160
|
2. Click a field → switches to `DynamicFormField` editor inline
|
|
152
161
|
3. Changed fields get highlighted with amber background
|
|
@@ -156,6 +165,7 @@ Use `EditableRecordDetail` for detail views where users can edit individual fiel
|
|
|
156
165
|
**Important:** Always pass `trackChanges` prop when using `EditableRecordDetail` or `DataGrid` with cell editing. Without it, users have no visual feedback about which fields they've modified and no centralized Save/Cancel flow.
|
|
157
166
|
|
|
158
167
|
**Field change tracking types:**
|
|
168
|
+
|
|
159
169
|
```tsx
|
|
160
170
|
interface RecordDetailField {
|
|
161
171
|
field: IField // Field configuration (name, slug, type)
|
|
@@ -174,6 +184,7 @@ interface FieldChange {
|
|
|
174
184
|
```
|
|
175
185
|
|
|
176
186
|
**Example — Detail view with inline editing and "Edit All" button:**
|
|
187
|
+
|
|
177
188
|
```tsx
|
|
178
189
|
<AwesomeDialogHeader
|
|
179
190
|
title="Task Detail"
|
|
@@ -368,9 +379,11 @@ When using **Data Grid View Select**, back its `views`, `onViewCreate`, `onViewS
|
|
|
368
379
|
## Library-Specific Strengths
|
|
369
380
|
|
|
370
381
|
### shadcn (43 components)
|
|
382
|
+
|
|
371
383
|
**Best for**: Core UI primitives, forms, basic layout
|
|
372
384
|
|
|
373
385
|
**Strengths**:
|
|
386
|
+
|
|
374
387
|
- Well-tested, accessible components
|
|
375
388
|
- Great documentation
|
|
376
389
|
- Broad browser support
|
|
@@ -379,9 +392,11 @@ When using **Data Grid View Select**, back its `views`, `onViewCreate`, `onViewS
|
|
|
379
392
|
**Use when**: You need a standard, reliable component without special features
|
|
380
393
|
|
|
381
394
|
### diceui (42 components)
|
|
395
|
+
|
|
382
396
|
**Best for**: Advanced interactions, specialized data components
|
|
383
397
|
|
|
384
398
|
**Strengths**:
|
|
399
|
+
|
|
385
400
|
- Rich feature sets (filtering, sorting, virtualization)
|
|
386
401
|
- Advanced input types (phone, color, mask)
|
|
387
402
|
- Drag-drop capabilities
|
|
@@ -390,9 +405,11 @@ When using **Data Grid View Select**, back its `views`, `onViewCreate`, `onViewS
|
|
|
390
405
|
**Use when**: You need advanced functionality beyond basic components
|
|
391
406
|
|
|
392
407
|
### animate-ui (21 components)
|
|
408
|
+
|
|
393
409
|
**Best for**: Animated transitions, polished UX
|
|
394
410
|
|
|
395
411
|
**Strengths**:
|
|
412
|
+
|
|
396
413
|
- Smooth, professional animations
|
|
397
414
|
- Enhanced visual feedback
|
|
398
415
|
- Composable animated patterns
|
|
@@ -400,9 +417,11 @@ When using **Data Grid View Select**, back its `views`, `onViewCreate`, `onViewS
|
|
|
400
417
|
**Use when**: Animation/transitions are important to the UX
|
|
401
418
|
|
|
402
419
|
### docyrus (51 components)
|
|
420
|
+
|
|
403
421
|
**Best for**: Docyrus-specific data handling, forms, dialogs, inline editing, scheduling, chat, AI agents, and business logic
|
|
404
422
|
|
|
405
423
|
**Strengths**:
|
|
424
|
+
|
|
406
425
|
- Deep Docyrus platform integration
|
|
407
426
|
- AwesomeDialog system for item creation and detail views
|
|
408
427
|
- EditableRecordDetail for inline field editing with change tracking
|
|
@@ -419,9 +438,11 @@ When using **Data Grid View Select**, back its `views`, `onViewCreate`, `onViewS
|
|
|
419
438
|
**Use when**: Working with Docyrus data sources, building item create/detail flows, forms, scheduling, chat, AI features, or queries
|
|
420
439
|
|
|
421
440
|
### reui (2 components)
|
|
441
|
+
|
|
422
442
|
**Best for**: Specific utility needs
|
|
423
443
|
|
|
424
444
|
**Strengths**:
|
|
445
|
+
|
|
425
446
|
- Focused implementations
|
|
426
447
|
- Lightweight alternatives
|
|
427
448
|
|
|
@@ -466,25 +487,29 @@ These are the **recommended defaults** unless the user specifies otherwise:
|
|
|
466
487
|
|
|
467
488
|
## When to Use Each Library
|
|
468
489
|
|
|
469
|
-
### Use shadcn when
|
|
490
|
+
### Use shadcn when
|
|
491
|
+
|
|
470
492
|
- Building basic forms with standard inputs
|
|
471
493
|
- Creating simple layouts with cards, buttons, badges
|
|
472
494
|
- Need reliable, accessible primitives
|
|
473
495
|
- No special animation or advanced features required
|
|
474
496
|
|
|
475
|
-
### Use diceui when
|
|
497
|
+
### Use diceui when
|
|
498
|
+
|
|
476
499
|
- Building complex data tables with sorting/filtering
|
|
477
500
|
- Need advanced input types (phone, color, tags)
|
|
478
501
|
- Implementing drag-drop (kanban, sortable lists)
|
|
479
502
|
- Creating rich data visualizations (gauges, timelines)
|
|
480
503
|
|
|
481
|
-
### Use animate-ui when
|
|
504
|
+
### Use animate-ui when
|
|
505
|
+
|
|
482
506
|
- Animation/transitions are important to the design
|
|
483
507
|
- Building navigation with smooth interactions
|
|
484
508
|
- Creating polished dialog/overlay experiences
|
|
485
509
|
- Need animated feedback for user actions
|
|
486
510
|
|
|
487
|
-
### Use docyrus when
|
|
511
|
+
### Use docyrus when
|
|
512
|
+
|
|
488
513
|
- Building item create forms (AwesomeDialog, Create Record Dialog)
|
|
489
514
|
- Building item detail views (AwesomeDialog + EditableRecordDetail)
|
|
490
515
|
- Working directly with Docyrus data sources
|
|
@@ -499,7 +524,8 @@ These are the **recommended defaults** unless the user specifies otherwise:
|
|
|
499
524
|
- Need rich item selectors (Mega Select, Kanban)
|
|
500
525
|
- Need Docyrus-specific components (query builder, activity panel, notifications)
|
|
501
526
|
|
|
502
|
-
### Use reui when
|
|
527
|
+
### Use reui when
|
|
528
|
+
|
|
503
529
|
- The specific component (file upload or sortable) matches your exact need
|
|
504
530
|
- Want a lightweight alternative to diceui versions
|
|
505
531
|
|
|
@@ -524,6 +550,7 @@ These are the **recommended defaults** unless the user specifies otherwise:
|
|
|
524
550
|
- Use for: Fallback when neither hugeicons nor fontawesome have the icon
|
|
525
551
|
|
|
526
552
|
**Example**:
|
|
553
|
+
|
|
527
554
|
```tsx
|
|
528
555
|
import { HugeIconDollarCircle } from '@/components/icons/hugeicons'
|
|
529
556
|
import { FaLightChartLine } from '@/components/icons/fontawesome'
|
|
@@ -544,6 +571,7 @@ import { LucideActivity } from 'lucide-react'
|
|
|
544
571
|
## Quick Reference: Component Categories
|
|
545
572
|
|
|
546
573
|
### Dialogs & Item Flows
|
|
574
|
+
|
|
547
575
|
- Item create forms: **docyrus AwesomeDialog** (sheet for small, modal for large)
|
|
548
576
|
- Quick record create: **docyrus Create Record Dialog** (popover with subject/mentions)
|
|
549
577
|
- Item detail (small): **docyrus AwesomeDialog** (sheet right)
|
|
@@ -553,6 +581,7 @@ import { LucideActivity } from 'lucide-react'
|
|
|
553
581
|
- Responsive: diceui Responsive Dialog
|
|
554
582
|
|
|
555
583
|
### Data & Display
|
|
584
|
+
|
|
556
585
|
- Tables: docyrus Data Grid, diceui Data Table, shadcn Table
|
|
557
586
|
- Pivot table: docyrus PivotGrid (hierarchies, subtotals, drilldown, export)
|
|
558
587
|
- Grid saved views: docyrus Data Grid View Select + `DataViews` from `@docyrus/app-utils`
|
|
@@ -564,6 +593,7 @@ import { LucideActivity } from 'lucide-react'
|
|
|
564
593
|
- Tree: docyrus TreeView
|
|
565
594
|
|
|
566
595
|
### Forms & Input
|
|
596
|
+
|
|
567
597
|
- Dynamic forms: **docyrus Form Fields + TanStack Form** (always use)
|
|
568
598
|
- Inline editing: docyrus EditableRecordDetail, EditableValue
|
|
569
599
|
- Text: shadcn Input, Textarea
|
|
@@ -576,17 +606,20 @@ import { LucideActivity } from 'lucide-react'
|
|
|
576
606
|
- Special: diceui Phone Input, Color Picker, Tags Input
|
|
577
607
|
|
|
578
608
|
### Navigation
|
|
609
|
+
|
|
579
610
|
- Sidebar: animate-ui Sidebar
|
|
580
611
|
- Menus: animate-ui Dropdown Menu, shadcn Menubar
|
|
581
612
|
- Breadcrumbs: shadcn Breadcrumb
|
|
582
613
|
- Tabs: animate-ui Tabs
|
|
583
614
|
|
|
584
615
|
### Overlays
|
|
616
|
+
|
|
585
617
|
- Item forms/details: **docyrus AwesomeDialog** (preferred)
|
|
586
618
|
- Popovers: animate-ui Popover, Tooltip, Hover Card
|
|
587
619
|
- Drawers: shadcn Drawer, animate-ui Sheet
|
|
588
620
|
|
|
589
621
|
### Communication
|
|
622
|
+
|
|
590
623
|
- Team chat: docyrus Team Chat Channel (threads, reactions, mentions)
|
|
591
624
|
- Email composing: docyrus Email Composer (To/Cc/Bcc, toolbar, attachments)
|
|
592
625
|
- Comments: docyrus Comments Panel (threaded conversations)
|
|
@@ -594,21 +627,25 @@ import { LucideActivity } from 'lucide-react'
|
|
|
594
627
|
- Activity logging: docyrus Log Activity Form (calls, emails, meetings, tasks, statuses)
|
|
595
628
|
|
|
596
629
|
### Scheduling
|
|
630
|
+
|
|
597
631
|
- Project timelines: docyrus Gantt
|
|
598
632
|
- Resource scheduling: docyrus Resource Scheduler Panel (horizontal timeline)
|
|
599
633
|
- Appointment booking: docyrus Time Slot Scheduler (columns/month views)
|
|
600
634
|
- Calendar events: docyrus Calendar (month/week/day views)
|
|
601
635
|
|
|
602
636
|
### AI & Agents
|
|
637
|
+
|
|
603
638
|
- AI chat: docyrus Docyrus Agent (chat mode)
|
|
604
639
|
- AI actions: docyrus Docyrus Agent (action-panel mode)
|
|
605
640
|
- AI trigger: docyrus Docyrus Agent (floating trigger button)
|
|
606
641
|
|
|
607
642
|
### Business Logic
|
|
643
|
+
|
|
608
644
|
- Pricing/quoting: docyrus Pricing Engine Panel (line items, VAT, discounts)
|
|
609
645
|
- Record sharing: docyrus Record Sharing (permissions, users/teams/roles)
|
|
610
646
|
|
|
611
647
|
### Specialized
|
|
648
|
+
|
|
612
649
|
- Kanban: docyrus Kanban (drag-drop columns)
|
|
613
650
|
- Timeline: diceui Timeline
|
|
614
651
|
- Stepper / wizard: docyrus Stepper (6 variants, horizontal/vertical, animated)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docyrus-data-grid-page-design
|
|
3
|
+
description: Build Docyrus React data-grid and record-list pages with `DataGrid`, `DataGridViewSelect`, `useDataGrid`, `useDocyrusDataViewSelect`, and `useDocyrusDataGrid`. Use when asked to build or refactor a list page, records table, CRM or ERP grid, saved-view tabs, row actions, manual DataGrid toolbar composition, or Docyrus data-source grid queries with filtering, sorting, grouping, search, display modes, paging, and reload behavior.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Docyrus Data Grid Page Design
|
|
7
|
+
|
|
8
|
+
Build full Docyrus list pages around the web `DataGrid` stack.
|
|
9
|
+
|
|
10
|
+
## Choose the build mode
|
|
11
|
+
|
|
12
|
+
1. **Standard Docyrus page** → use `useDocyrusDataGrid`.
|
|
13
|
+
- Best when rows come from a Docyrus data source or generated collection.
|
|
14
|
+
- Gives you metadata-driven columns, saved views, toolbar wiring, search, filters (with async option search for relation/user fields), grouping, sorting, row-height, display mode, paging, and reload.
|
|
15
|
+
- Auto-wires reference field expansion, tenant-aware formatters, and a shared users list when supplied.
|
|
16
|
+
- Read `references/hook-pages.md`.
|
|
17
|
+
|
|
18
|
+
2. **Custom layout or custom row-query lifecycle** → use `useDocyrusDataViewSelect` + `useDataGrid`.
|
|
19
|
+
- Best when you need a custom toolbar arrangement, local/demo data, or a non-standard fetch cycle.
|
|
20
|
+
- Read `references/manual-pages.md`.
|
|
21
|
+
|
|
22
|
+
3. **No backend saved views** → use `useDataGrid` with local `SavedDataGridView[]` or `DataGridViewMenu`.
|
|
23
|
+
- Also covered in `references/manual-pages.md`.
|
|
24
|
+
|
|
25
|
+
4. **Complex Docyrus query payloads** → also load the `docyrus-api-dev` skill.
|
|
26
|
+
5. **Advanced saved-view persistence or manual view-driven queries** → read `references/advanced-saved-view-query-patterns.md`.
|
|
27
|
+
6. **Tenant-aware formatters and shared users list** → read `references/tenant-and-users-providers.md`.
|
|
28
|
+
|
|
29
|
+
## Default page workflow
|
|
30
|
+
|
|
31
|
+
1. Confirm the `appSlug`, `dataSourceSlug`, and whether a generated collection already exists.
|
|
32
|
+
2. Pick hook mode or manual mode.
|
|
33
|
+
3. App-level: ensure a `TenantProvider` (preferences → date/number utils) and `UsersProvider` (`/v1/users` cache) wrap the route, and pull `formatDate` / `formatDateTime` / `formatNumber` / `users` into the grid hook from those contexts.
|
|
34
|
+
4. Add reserved columns in this order: select first, actions second. They are pinned left automatically by `useDocyrusDataGrid`.
|
|
35
|
+
5. Keep the page in a flex column layout with the grid body wrapped in `min-h-0 flex-1`.
|
|
36
|
+
6. Add create/edit/view/delete dialogs around row actions.
|
|
37
|
+
7. Verify initial saved view, search, filters, grouping, sorting, paging, and reload behavior.
|
|
38
|
+
|
|
39
|
+
## Non-negotiables
|
|
40
|
+
|
|
41
|
+
- Render page-sized grids with the toolbar in a shrink-0 row and the grid inside `min-h-0 flex-1`.
|
|
42
|
+
- Prefer `<DataGrid table={table} {...gridProps} height="auto" />` for full-page layouts.
|
|
43
|
+
- Pass the TanStack `table` instance to every grid menu and to `DataGridViewSelect`.
|
|
44
|
+
- `useDocyrusDataViewSelect` manages view metadata only. It does **not** fetch rows and does **not** accept `table`.
|
|
45
|
+
- Manual Docyrus item queries must always send `columns`. Reference fields (`field-userSelect`, `field-userMultiSelect`, `field-relation`, `field-relatedField`, `field-select`, `field-radioGroup`, `field-enum`, `field-systemEnum`, `field-multiSelect`, `field-tagSelect`, `field-status`, `field-approvalStatus`) must also be added to the `expand` array so the API returns `{ id, name, ... }` payloads instead of bare IDs.
|
|
46
|
+
- Backend saved-view filters need enum options; `useDocyrusDataViewSelect` already fetches the data source with `expand=enums`.
|
|
47
|
+
- Manual pages must apply the initial active view with `applyViewToTable(table, activeView)` after views and columns are ready. User-triggered view switches through `DataGridViewSelect` are applied automatically.
|
|
48
|
+
- Prefer `useDocyrusDataGrid` unless you truly need custom row fetching or custom toolbar composition. The hook handles auto-expand, async filter options, formatters, and reserved-column pinning for you.
|
|
49
|
+
- When you wire manual view CRUD into `DataGridViewSelect`, pass `isSaving` and `isLoading` so the editor UX stays correct during saves and background fetches.
|
|
50
|
+
- For tenant-aware date/datetime/number formatting, fetch `getTenantPreferences(client)` once at app boot and pass the resulting `formatDate` / `formatDateTime` / `formatNumber` callbacks into `useDocyrusDataGrid`.
|
|
51
|
+
- For instant avatar + label rendering on user-typed cells, fetch `/v1/users` once at app boot and pass the resulting `CellUserOption[]` into `useDocyrusDataGrid` via the `users` option.
|
|
52
|
+
|
|
53
|
+
## References
|
|
54
|
+
|
|
55
|
+
- `references/hook-pages.md` — one-call Docyrus grid pages with direct API mode, collection mode, extension points, formatters, and shared-users wiring.
|
|
56
|
+
- `references/manual-pages.md` — local/manual grid composition, local views, backend view-select wiring, and initial-view handling.
|
|
57
|
+
- `references/advanced-saved-view-query-patterns.md` — saved-view persistence, system views, hidden views, paging ownership, and translating active views into manual server queries.
|
|
58
|
+
- `references/tenant-and-users-providers.md` — app-level providers for tenant preferences and the shared users list, plus how to plug them into `useDocyrusDataGrid`.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Advanced Saved-View and Query Patterns
|
|
2
|
+
|
|
3
|
+
## Read this when
|
|
4
|
+
|
|
5
|
+
- You need backend-saved views but do not want `useDocyrusDataGrid` to own row fetching.
|
|
6
|
+
- You want system views plus user-saved views in one selector.
|
|
7
|
+
- You need to debug why a saved view, grouping rule, or paging setting is not reflected in the grid.
|
|
8
|
+
- You need to translate `SavedDataGridView` into a custom Docyrus items query.
|
|
9
|
+
|
|
10
|
+
## Saved-view ownership model
|
|
11
|
+
|
|
12
|
+
- `DataGridViewSelect` applies the selected view to the TanStack table when the user clicks a tab or dropdown item.
|
|
13
|
+
- `useDocyrusDataGrid` also reapplies the active view on mount and whenever the active view changes, so the initial view works without extra code.
|
|
14
|
+
- Manual pages using `useDocyrusDataViewSelect` plus `useDataGrid` must still apply the initial active view with `applyViewToTable(table, activeView)`.
|
|
15
|
+
|
|
16
|
+
## System views, hidden views, and persistence
|
|
17
|
+
|
|
18
|
+
`useDocyrusDataViewSelect` supports three useful layers of view state:
|
|
19
|
+
|
|
20
|
+
1. `systemViews`
|
|
21
|
+
- Developer-defined static views.
|
|
22
|
+
- Automatically marked `isSystem: true`.
|
|
23
|
+
- Render before saved backend views.
|
|
24
|
+
- Cannot be edited or deleted through `DataGridViewSelect`, but can still be hidden.
|
|
25
|
+
|
|
26
|
+
2. active-view persistence
|
|
27
|
+
- Controlled by `persistActiveView` and `persistKey`.
|
|
28
|
+
- Default storage namespace: `docyrus:data-grid-view:appSlug:dataSourceSlug[:appId]`.
|
|
29
|
+
- Initial resolution order: current in-memory value, stored value, backend `is_default`, then first available view.
|
|
30
|
+
|
|
31
|
+
3. hidden-view persistence
|
|
32
|
+
- Managed through `hiddenViewIds`, `onViewHide`, and `onViewUnhide` in `gridViewSelectProps`.
|
|
33
|
+
- Stored separately from the active-view key.
|
|
34
|
+
- Useful when system views should exist but not always stay visible in the tab strip.
|
|
35
|
+
|
|
36
|
+
## Manual server-query translation from a saved view
|
|
37
|
+
|
|
38
|
+
If you keep custom row fetching, derive request params from the active view yourself. Don't forget the toolbar filter merge — `DataGridFilterMenu` writes to TanStack `columnFilters`, and a manual page must AND-merge those into the saved-view filter payload.
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const activeView = views.find(view => view.id === activeViewId);
|
|
42
|
+
|
|
43
|
+
const columns = buildColumnsFromView(fields, activeView);
|
|
44
|
+
const orderBy = (activeView?.sorting ?? []).map(sort => ({
|
|
45
|
+
field: sort.id,
|
|
46
|
+
direction: sort.desc ? 'desc' : 'asc'
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
// Auto-expand reference-type fields so the API returns `{ id, name, ... }` payloads.
|
|
50
|
+
const EXPANDABLE_FIELD_TYPES = new Set([
|
|
51
|
+
'field-userSelect', 'field-userMultiSelect',
|
|
52
|
+
'field-relation', 'field-relatedField',
|
|
53
|
+
'field-select', 'field-radioGroup',
|
|
54
|
+
'field-enum', 'field-systemEnum',
|
|
55
|
+
'field-multiSelect', 'field-tagSelect',
|
|
56
|
+
'field-status', 'field-approvalStatus'
|
|
57
|
+
]);
|
|
58
|
+
const expand = fields
|
|
59
|
+
.filter(field => columns.includes(field.slug) && EXPANDABLE_FIELD_TYPES.has(field.type))
|
|
60
|
+
.map(field => field.slug);
|
|
61
|
+
|
|
62
|
+
// Merge saved-view filters with toolbar filter state.
|
|
63
|
+
const viewFilter = activeView?.filterQuery?.rules?.length ? activeView.filterQuery : undefined;
|
|
64
|
+
const toolbarRules = (table.getState().columnFilters ?? [])
|
|
65
|
+
.map(filter => toServerRule(filter)) // import from @docyrus/ui/components/data-grid/lib/data-grid-server
|
|
66
|
+
.filter(Boolean);
|
|
67
|
+
|
|
68
|
+
let filters;
|
|
69
|
+
|
|
70
|
+
if (viewFilter && toolbarRules.length > 0) {
|
|
71
|
+
filters = { combinator: 'and', rules: [viewFilter, ...toolbarRules] };
|
|
72
|
+
} else if (viewFilter) {
|
|
73
|
+
filters = viewFilter;
|
|
74
|
+
} else if (toolbarRules.length > 0) {
|
|
75
|
+
filters = { combinator: 'and', rules: toolbarRules };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const params = {
|
|
79
|
+
columns,
|
|
80
|
+
orderBy: orderBy.length > 0 ? orderBy : undefined,
|
|
81
|
+
filters,
|
|
82
|
+
filterKeyword: keyword || undefined,
|
|
83
|
+
expand: expand.length > 0 ? expand : undefined,
|
|
84
|
+
limit: 50,
|
|
85
|
+
offset: 0
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Rules to preserve from the built-in hook behavior:
|
|
90
|
+
|
|
91
|
+
- Always include `id` in `columns`.
|
|
92
|
+
- When `columnOrder` is present, treat it as the ordered whitelist of visible field slugs.
|
|
93
|
+
- Otherwise use `columnVisibility` entries with `true` values.
|
|
94
|
+
- With no explicit saved-view visibility config, fetch all field slugs.
|
|
95
|
+
- If the active view groups by a field, make sure that field stays in `columns` even if the saved view hides it.
|
|
96
|
+
- Add reference-type field slugs to `expand` so user / relation / status / select / multi-select cells render with full data.
|
|
97
|
+
- AND-merge `view.filterQuery` with the toolbar filter rules; reset `pageIndex` to 0 when the merged filter changes.
|
|
98
|
+
- If you merge app-specific overrides, apply them last so they win.
|
|
99
|
+
|
|
100
|
+
## Reserved columns versus backend field slugs
|
|
101
|
+
|
|
102
|
+
There are two different conventions:
|
|
103
|
+
|
|
104
|
+
- Local/manual views can include reserved table columns like `select` and `actions` inside `columnOrder`.
|
|
105
|
+
- Backend Docyrus-saved views only know real data-source field slugs.
|
|
106
|
+
|
|
107
|
+
That difference matters when you build a hybrid page. If you manually persist local views, reserved columns are safe. If you round-trip views through Docyrus backend APIs, assume only real field slugs are persisted and prepend reserved UI columns in the page code.
|
|
108
|
+
|
|
109
|
+
## Paging ownership
|
|
110
|
+
|
|
111
|
+
Saved views can carry:
|
|
112
|
+
|
|
113
|
+
- `pagingEnabled`
|
|
114
|
+
- `pagingMode`
|
|
115
|
+
- `pageSize`
|
|
116
|
+
|
|
117
|
+
`useDocyrusDataGrid` reads those values and forwards them into `useDataGrid`, and `gridProps` then carries the resolved paging mode.
|
|
118
|
+
|
|
119
|
+
If you build the page manually and want the active view to own paging:
|
|
120
|
+
|
|
121
|
+
- read the values from `activeView`
|
|
122
|
+
- pass `pagingMode` and `pageSize` into `useDataGrid`
|
|
123
|
+
- ensure your own row query or pagination model stays compatible with that page size
|
|
124
|
+
|
|
125
|
+
If you ignore these properties in manual mode, the view editor can save paging settings that never affect the rendered grid.
|
|
126
|
+
|
|
127
|
+
## Good advanced combinations
|
|
128
|
+
|
|
129
|
+
### System starter views + backend user views
|
|
130
|
+
|
|
131
|
+
Use `systemViews` for non-editable defaults like:
|
|
132
|
+
|
|
133
|
+
- All records
|
|
134
|
+
- My records
|
|
135
|
+
- Needs attention
|
|
136
|
+
- Recently updated
|
|
137
|
+
|
|
138
|
+
Then let users create their own backend-saved views beside them.
|
|
139
|
+
|
|
140
|
+
### Hook-owned metadata + app-owned data fetching
|
|
141
|
+
|
|
142
|
+
Use `useDocyrusDataViewSelect` when you want:
|
|
143
|
+
|
|
144
|
+
- backend view CRUD
|
|
145
|
+
- field metadata for the filter editor
|
|
146
|
+
- active-view persistence
|
|
147
|
+
- hidden-view persistence
|
|
148
|
+
|
|
149
|
+
but you still want the page's existing query hook, export pipeline, or analytics request builder to own row fetching.
|
|
150
|
+
|
|
151
|
+
## Debug checklist
|
|
152
|
+
|
|
153
|
+
- **Wrong initial view?** Check `persistActiveView`, `persistKey`, and whether a stale value is still in local storage.
|
|
154
|
+
- **Grouping not working?** Make sure the grouping field is included in fetched `columns` and remains visible enough for the row model.
|
|
155
|
+
- **Filter builder missing?** Pass `fields` into `DataGridViewSelect`.
|
|
156
|
+
- **View tabs empty during loading?** Pass `isLoading` so the selector can render its loading state.
|
|
157
|
+
- **Editor closes too early on save?** Pass `isSaving` when the host owns async create or update.
|
|
158
|
+
- **Backend returns incomplete rows?** You probably forgot `columns`.
|