formue-crud 0.1.77 → 0.1.79

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/README.md CHANGED
@@ -1,46 +1,795 @@
1
- # formue-crud
1
+ # Formue CRUD - Complete Documentation
2
2
 
3
- This template should help get you started developing with Vue 3 in Vite.
3
+ ## Table of Contents
4
4
 
5
- ## Recommended IDE Setup
5
+ 1. [Overview](#overview)
6
+ 2. [Installation & Setup](#installation--setup)
7
+ 3. [Core Components](#core-components)
8
+ 4. [Architecture](#architecture)
9
+ 5. [API Reference](#api-reference)
10
+ 6. [Usage Examples](#usage-examples)
11
+ 7. [Advanced Features](#advanced-features)
12
+ 8. [Customization](#customization)
13
+ 9. [Best Practices](#best-practices)
14
+ 10. [Troubleshooting](#troubleshooting)
6
15
 
7
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
16
+ ## Overview
8
17
 
9
- ## Type Support for `.vue` Imports in TS
18
+ Formue CRUD is a comprehensive Vue.js 3 framework designed for building data-driven applications with advanced CRUD operations. It provides a complete solution for managing data tables, forms, filtering, sorting, pagination, and user permissions.
10
19
 
11
- TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
20
+ ### Key Features
12
21
 
13
- If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
22
+ - **Dynamic Data Tables**: Tabulator.js integration with advanced sorting and filtering
23
+ - **Form Management**: Vueform integration for dynamic form generation
24
+ - **Permission System**: Role-based access control for CRUD operations
25
+ - **Advanced Filtering**: Multi-field filtering with save/load functionality
26
+ - **Export Capabilities**: Excel export with customizable data
27
+ - **Responsive Design**: Mobile-friendly interface with Tailwind CSS
28
+ - **State Management**: Pinia-based reactive state management
29
+ - **Real-time Updates**: Event-driven architecture for live data updates
14
30
 
15
- 1. Disable the built-in TypeScript Extension
16
- 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
17
- 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
18
- 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
31
+ ### Dependencies
19
32
 
20
- ## Customize configuration
33
+ ```json
34
+ {
35
+ "@vueform/vueform": "^1.5.3",
36
+ "@vueuse/core": "^10.4.0",
37
+ "axios": "^1.6.2",
38
+ "lodash": "^4.17.21",
39
+ "mitt": "^3.0.1",
40
+ "pinia": "^2.1.6",
41
+ "qs": "^6.11.2",
42
+ "tabulator-tables": "^6.2.1",
43
+ "vue": "^3.3.4"
44
+ }
45
+ ```
21
46
 
22
- See [Vite Configuration Reference](https://vitejs.dev/config/).
47
+ ## Installation & Setup
23
48
 
24
- ## Project Setup
49
+ ### 1. Install the Package
25
50
 
26
- ```sh
27
- npm install
51
+ ```bash
52
+ npm install formue-crud
53
+ ```
54
+
55
+ ### 2. Import and Configure
56
+
57
+ ```javascript
58
+ import { createApp } from 'vue'
59
+ import { createPinia } from 'pinia'
60
+ import FormueCrud from 'formue-crud'
61
+
62
+ const app = createApp(App)
63
+ app.use(createPinia())
64
+ app.use(FormueCrud)
65
+ ```
66
+
67
+ ### 3. Basic Setup
68
+
69
+ ```vue
70
+ <template>
71
+ <MCrud
72
+ :fields="fields"
73
+ :options="options"
74
+ :route="route"
75
+ :hidden-actions="hiddenActions"
76
+ @mounted="onMounted"
77
+ />
78
+ </template>
79
+
80
+ <script setup>
81
+ import { MCrud } from 'formue-crud'
82
+
83
+ const fields = {
84
+ name: {
85
+ type: 'text',
86
+ title: 'Name',
87
+ placeholder: 'Enter name'
88
+ },
89
+ email: {
90
+ type: 'email',
91
+ title: 'Email',
92
+ placeholder: 'Enter email'
93
+ }
94
+ }
95
+
96
+ const options = {
97
+ formMode: 'dialog' // or 'tab'
98
+ }
99
+
100
+ const route = {
101
+ index: '/api/users',
102
+ create: '/api/users',
103
+ update: '/api/users',
104
+ delete: '/api/users'
105
+ }
106
+
107
+ const hiddenActions = [] // ['create', 'update', 'delete', 'show']
108
+ </script>
109
+ ```
110
+
111
+ ## Core Components
112
+
113
+ ### MCrud (Main Component)
114
+
115
+ The primary component that orchestrates all CRUD operations.
116
+
117
+ **Props:**
118
+
119
+ - `fields`: Object defining form fields and table columns
120
+ - `options`: Configuration object for behavior customization
121
+ - `structure`: Additional form structure configuration
122
+ - `hiddenActions`: Array of actions to hide from UI
123
+ - `tableOptions`: Tabulator-specific options
124
+ - `route`: API endpoints configuration
125
+ - `dir`: Text direction ('ltr' or 'rtl')
126
+
127
+ **Events:**
128
+
129
+ - `mounted`: Emitted when component is fully initialized
130
+
131
+ ### MTable
132
+
133
+ Advanced data table component with sorting, filtering, and pagination.
134
+
135
+ **Features:**
136
+
137
+ - Column sorting with visual indicators
138
+ - Row selection with batch operations
139
+ - Custom column visibility
140
+ - Loading states and empty data handling
141
+ - Responsive design
142
+
143
+ ### MFilter
144
+
145
+ Dynamic filtering system with save/load functionality.
146
+
147
+ **Features:**
148
+
149
+ - Field-specific filter types (text, date, select)
150
+ - Multiple filter combinations
151
+ - Save/load filter presets
152
+ - Real-time filter application
153
+
154
+ ### FormCore
155
+
156
+ Dynamic form generation component using Vueform.
157
+
158
+ **Features:**
159
+
160
+ - Auto-generated forms from field definitions
161
+ - Validation integration
162
+ - Conditional field display
163
+ - Multi-step form support
164
+
165
+ ### MButtonBox
166
+
167
+ Action toolbar with permissions-based button visibility.
168
+
169
+ **Features:**
170
+
171
+ - Create, export, reload, column selection buttons
172
+ - Permission-based visibility
173
+ - Batch operation support
174
+ - Search integration
175
+
176
+ ## Architecture
177
+
178
+ ### State Management (Pinia Store)
179
+
180
+ The framework uses a dynamic store system for managing application state:
181
+
182
+ ```javascript
183
+ // Store Structure
184
+ {
185
+ mainKey: '', // Current data model key
186
+ form: {}, // Current form data
187
+ items: {}, // Data collections by key
188
+ query: '', // Additional query parameters
189
+ routes: {}, // API endpoints
190
+ fields: [], // Field definitions
191
+ options: [], // Configuration options
192
+ filters: [], // Active filters
193
+ loadings: {}, // Loading states
194
+ dialog: false, // Dialog visibility
195
+ structure: {}, // Form structure
196
+ paginations: {}, // Pagination data
197
+ searchParam: '', // Search query
198
+ isEditing: false, // Edit mode flag
199
+ selected: new Set([]) // Selected items
200
+ }
201
+ ```
202
+
203
+ ### Event System
204
+
205
+ Uses mitt.js for event communication between components:
206
+
207
+ ```javascript
208
+ import { emitter } from '@/helpers/emitter'
209
+
210
+ // Listen to events
211
+ emitter.listen('saveForm', () => {
212
+ // Handle form save
213
+ })
214
+
215
+ // Emit events
216
+ emitter.event('alert', { text: 'Success!', color: 'green' })
217
+ ```
218
+
219
+ ### Permission System
220
+
221
+ Role-based access control for UI elements:
222
+
223
+ ```javascript
224
+ import { usePermission } from '@/composables/usePermission'
225
+
226
+ const { can } = usePermission()
227
+
228
+ // Check permissions
229
+ if (can('create')) {
230
+ // Show create button
231
+ }
232
+ ```
233
+
234
+ ## API Reference
235
+
236
+ ### Field Types
237
+
238
+ #### Text Field
239
+
240
+ ```javascript
241
+ {
242
+ type: 'text',
243
+ title: 'Field Name',
244
+ placeholder: 'Enter value',
245
+ required: true,
246
+ validation: 'required|min:3'
247
+ }
248
+ ```
249
+
250
+ #### Select Field
251
+
252
+ ```javascript
253
+ {
254
+ type: 'select',
255
+ title: 'Category',
256
+ items: [
257
+ { value: 1, text: 'Option 1' },
258
+ { value: 2, text: 'Option 2' }
259
+ ],
260
+ 'label-prop': 'text',
261
+ 'value-prop': 'value',
262
+ search: true
263
+ }
264
+ ```
265
+
266
+ #### Date Field
267
+
268
+ ```javascript
269
+ {
270
+ type: 'date',
271
+ title: 'Date',
272
+ placeholder: 'Select date',
273
+ format: 'YYYY-MM-DD'
274
+ }
275
+ ```
276
+
277
+ ### Store Actions
278
+
279
+ #### Data Operations
280
+
281
+ ```javascript
282
+ // Load items
283
+ store.loadItems(key, page)
284
+
285
+ // Add new item
286
+ store.addItem(data)
287
+
288
+ // Edit existing item
289
+ store.editItem(data)
290
+
291
+ // Remove item
292
+ store.remove(id)
293
+
294
+ // Reload data
295
+ store.reloadData()
296
+ ```
297
+
298
+ #### Filtering
299
+
300
+ ```javascript
301
+ // Apply filters
302
+ store.loadItems()
303
+
304
+ // Clear all filters
305
+ store.filters = []
306
+
307
+ // Generate filter query
308
+ store.convertToFilterForm()
309
+ ```
310
+
311
+ ### Composables
312
+
313
+ #### useDynamicStore
314
+
315
+ ```javascript
316
+ import { useDynamicStore } from '@/composables/useDynamicStore'
317
+
318
+ const store = useDynamicStore('MyStore')
319
+ ```
320
+
321
+ #### usePermission
322
+
323
+ ```javascript
324
+ import { usePermission } from '@/composables/usePermission'
325
+
326
+ const { can, setPermissions } = usePermission()
327
+
328
+ setPermissions(['create', 'update', 'delete'])
28
329
  ```
29
330
 
30
- ### Compile and Hot-Reload for Development
331
+ #### useFetch
31
332
 
32
- ```sh
333
+ ```javascript
334
+ import { useFetch } from '@/composables/useFetch'
335
+
336
+ const { get, post, patch, remove } = useFetch()
337
+
338
+ const response = await get('/api/users')
339
+ ```
340
+
341
+ ## Usage Examples
342
+
343
+ ### Basic CRUD Setup
344
+
345
+ ```vue
346
+ <template>
347
+ <MCrud :fields="userFields" :route="userRoutes" :options="{ formMode: 'dialog' }" />
348
+ </template>
349
+
350
+ <script setup>
351
+ const userFields = {
352
+ name: {
353
+ type: 'text',
354
+ title: 'Full Name',
355
+ required: true,
356
+ showIn: ['create', 'edit', 'list']
357
+ },
358
+ email: {
359
+ type: 'email',
360
+ title: 'Email Address',
361
+ required: true
362
+ },
363
+ role: {
364
+ type: 'select',
365
+ title: 'Role',
366
+ items: [
367
+ { value: 'admin', text: 'Administrator' },
368
+ { value: 'user', text: 'Regular User' }
369
+ ]
370
+ },
371
+ created_at: {
372
+ type: 'date',
373
+ title: 'Created Date',
374
+ showIn: ['list']
375
+ }
376
+ }
377
+
378
+ const userRoutes = {
379
+ index: '/api/users',
380
+ create: '/api/users',
381
+ update: '/api/users',
382
+ delete: '/api/users'
383
+ }
384
+ </script>
385
+ ```
386
+
387
+ ### Custom Field with API Integration
388
+
389
+ ```javascript
390
+ const productFields = {
391
+ category_id: {
392
+ type: 'select',
393
+ title: 'Category',
394
+ items: async (search) => {
395
+ const response = await axios.get(`/api/categories?search=${search}`)
396
+ return response.data.data
397
+ },
398
+ 'label-prop': 'name',
399
+ 'value-prop': 'id',
400
+ search: true
401
+ }
402
+ }
403
+ ```
404
+
405
+ ### Advanced Filtering Setup
406
+
407
+ ```javascript
408
+ const advancedFields = {
409
+ status: {
410
+ type: 'select',
411
+ title: 'Status',
412
+ items: [
413
+ { value: 'active', text: 'Active' },
414
+ { value: 'inactive', text: 'Inactive' }
415
+ ],
416
+ filterItems: [
417
+ { value: 'active', text: 'Active Only' },
418
+ { value: 'inactive', text: 'Inactive Only' }
419
+ ]
420
+ },
421
+ created_at: {
422
+ type: 'date',
423
+ title: 'Created Date',
424
+ filterable: true
425
+ }
426
+ }
427
+ ```
428
+
429
+ ### Custom Actions
430
+
431
+ ```vue
432
+ <template>
433
+ <MCrud :fields="fields" :route="route" @mounted="setupCustomActions">
434
+ <template #extra>
435
+ <CustomActionButtons />
436
+ </template>
437
+ </MCrud>
438
+ </template>
439
+
440
+ <script setup>
441
+ import { emitter } from '@/helpers/emitter'
442
+
443
+ const setupCustomActions = () => {
444
+ emitter.listen('customAction', (data) => {
445
+ // Handle custom action
446
+ console.log('Custom action triggered:', data)
447
+ })
448
+ }
449
+ </script>
450
+ ```
451
+
452
+ ## Advanced Features
453
+
454
+ ### Batch Operations
455
+
456
+ ```javascript
457
+ // Select multiple items
458
+ store.selected.add(itemId)
459
+
460
+ // Batch delete
461
+ const selectedIds = Array.from(store.selected)
462
+ store.remove(selectedIds)
463
+
464
+ // Custom batch operation
465
+ emitter.listen('batchUpdate', (data) => {
466
+ const selectedItems = store.mainItems.filter((item) => store.selected.has(item.id))
467
+ // Process selected items
468
+ })
469
+ ```
470
+
471
+ ### Export Functionality
472
+
473
+ ```javascript
474
+ // Export filtered data
475
+ function exportData() {
476
+ const exportUrl = store.generateQuery() + '/export'
477
+ window.open(exportUrl)
478
+ }
479
+
480
+ // Custom export format
481
+ function exportCustom() {
482
+ const selectedData = store.mainItems.filter((item) => store.selected.has(item.id))
483
+ // Process and export selected data
484
+ }
485
+ ```
486
+
487
+ ### Custom Column Rendering
488
+
489
+ ```javascript
490
+ const customFields = {
491
+ avatar: {
492
+ type: 'image',
493
+ title: 'Avatar',
494
+ formatter: (value) => {
495
+ return `<img src="${value}" alt="Avatar" class="w-8 h-8 rounded-full">`
496
+ }
497
+ },
498
+ status: {
499
+ type: 'select',
500
+ title: 'Status',
501
+ formatter: (value) => {
502
+ const color = value === 'active' ? 'green' : 'red'
503
+ return `<span class="px-2 py-1 text-xs rounded bg-${color}-100 text-${color}-800">${value}</span>`
504
+ }
505
+ }
506
+ }
507
+ ```
508
+
509
+ ### Conditional Field Display
510
+
511
+ ```javascript
512
+ const conditionalFields = {
513
+ type: {
514
+ type: 'select',
515
+ title: 'User Type',
516
+ items: [
517
+ { value: 'individual', text: 'Individual' },
518
+ { value: 'company', text: 'Company' }
519
+ ],
520
+ onChange: (value, formData) => {
521
+ // Show/hide fields based on selection
522
+ if (value === 'company') {
523
+ // Show company-specific fields
524
+ }
525
+ }
526
+ },
527
+ company_name: {
528
+ type: 'text',
529
+ title: 'Company Name',
530
+ showIf: (formData) => formData.type === 'company'
531
+ }
532
+ }
533
+ ```
534
+
535
+ ## Customization
536
+
537
+ ### Styling
538
+
539
+ The framework uses Tailwind CSS for styling. You can customize the appearance by:
540
+
541
+ 1. **Override CSS Classes:**
542
+
543
+ ```css
544
+ .fc-header-icon-btn {
545
+ @apply bg-blue-500 hover:bg-blue-600 text-white;
546
+ }
547
+
548
+ .fc-table-row:hover {
549
+ @apply bg-blue-50;
550
+ }
551
+ ```
552
+
553
+ 2. **Custom Themes:**
554
+
555
+ ```javascript
556
+ const customOptions = {
557
+ theme: {
558
+ primary: 'blue',
559
+ secondary: 'gray',
560
+ success: 'green',
561
+ danger: 'red'
562
+ }
563
+ }
564
+ ```
565
+
566
+ ### Custom Components
567
+
568
+ ```vue
569
+ <!-- CustomField.vue -->
570
+ <template>
571
+ <div class="custom-field">
572
+ <label>{{ field.title }}</label>
573
+ <input v-model="modelValue" :type="field.type" :placeholder="field.placeholder" />
574
+ </div>
575
+ </template>
576
+
577
+ <script setup>
578
+ import { registerFields } from 'formue-crud'
579
+
580
+ registerFields({
581
+ 'custom-field': CustomField
582
+ })
583
+ </script>
584
+ ```
585
+
586
+ ### API Response Format
587
+
588
+ Expected API response format:
589
+
590
+ ```json
591
+ {
592
+ "data": [
593
+ {
594
+ "id": 1,
595
+ "name": "John Doe",
596
+ "email": "john@example.com"
597
+ }
598
+ ],
599
+ "current_page": 1,
600
+ "last_page": 5,
601
+ "total": 50,
602
+ "per_page": 10
603
+ }
604
+ ```
605
+
606
+ ## Best Practices
607
+
608
+ ### 1. Field Organization
609
+
610
+ ```javascript
611
+ // Group related fields
612
+ const userFields = {
613
+ // Personal Information
614
+ first_name: { type: 'text', title: 'First Name', group: 'personal' },
615
+ last_name: { type: 'text', title: 'Last Name', group: 'personal' },
616
+
617
+ // Contact Information
618
+ email: { type: 'email', title: 'Email', group: 'contact' },
619
+ phone: { type: 'tel', title: 'Phone', group: 'contact' }
620
+ }
621
+ ```
622
+
623
+ ### 2. Performance Optimization
624
+
625
+ ```javascript
626
+ // Use lazy loading for large datasets
627
+ const lazyFields = {
628
+ category: {
629
+ type: 'select',
630
+ items: async (search) => {
631
+ // Only load when needed
632
+ if (search.length < 2) return []
633
+ return await fetchCategories(search)
634
+ }
635
+ }
636
+ }
637
+ ```
638
+
639
+ ### 3. Error Handling
640
+
641
+ ```javascript
642
+ // Global error handling
643
+ emitter.listen('error', (error) => {
644
+ console.error('CRUD Error:', error)
645
+ // Show user-friendly message
646
+ showNotification(error.message, 'error')
647
+ })
648
+ ```
649
+
650
+ ### 4. Validation
651
+
652
+ ```javascript
653
+ const validatedFields = {
654
+ email: {
655
+ type: 'email',
656
+ title: 'Email',
657
+ rules: ['required', 'email'],
658
+ messages: {
659
+ required: 'Email is required',
660
+ email: 'Please enter a valid email'
661
+ }
662
+ }
663
+ }
664
+ ```
665
+
666
+ ## Troubleshooting
667
+
668
+ ### Common Issues
669
+
670
+ #### 1. Data Not Loading
671
+
672
+ ```javascript
673
+ // Check API endpoint
674
+ console.log('API URL:', store.generateRoute())
675
+
676
+ // Verify response format
677
+ axios.get('/api/users').then((response) => {
678
+ console.log('Response structure:', response.data)
679
+ })
680
+ ```
681
+
682
+ #### 2. Form Validation Errors
683
+
684
+ ```javascript
685
+ // Debug form validation
686
+ emitter.listen('validation-error', (errors) => {
687
+ console.log('Validation errors:', errors)
688
+ })
689
+ ```
690
+
691
+ #### 3. Permission Issues
692
+
693
+ ```javascript
694
+ // Check permission setup
695
+ const { permissions } = usePermission()
696
+ console.log('Available permissions:', permissions.value)
697
+ ```
698
+
699
+ #### 4. Filter Not Working
700
+
701
+ ```javascript
702
+ // Debug filter generation
703
+ console.log('Filter query:', store.convertToFilterForm())
704
+ ```
705
+
706
+ ### Debug Mode
707
+
708
+ Enable debug mode for detailed logging:
709
+
710
+ ```javascript
711
+ const debugOptions = {
712
+ debug: true,
713
+ logging: {
714
+ api: true,
715
+ events: true,
716
+ state: true
717
+ }
718
+ }
719
+ ```
720
+
721
+ ### Performance Monitoring
722
+
723
+ ```javascript
724
+ // Monitor API calls
725
+ axios.interceptors.request.use((request) => {
726
+ console.time(`API: ${request.url}`)
727
+ return request
728
+ })
729
+
730
+ axios.interceptors.response.use((response) => {
731
+ console.timeEnd(`API: ${response.config.url}`)
732
+ return response
733
+ })
734
+ ```
735
+
736
+ ## Migration Guide
737
+
738
+ ### From Version 0.1.x to 0.2.x
739
+
740
+ 1. **Update field definitions:**
741
+
742
+ ```javascript
743
+ // Old format
744
+ const fields = [{ field: 'name', type: 'text', title: 'Name' }]
745
+
746
+ // New format
747
+ const fields = {
748
+ name: { type: 'text', title: 'Name' }
749
+ }
750
+ ```
751
+
752
+ 2. **Update event listeners:**
753
+
754
+ ```javascript
755
+ // Old format
756
+ this.$emit('update', data)
757
+
758
+ // New format
759
+ emitter.event('update', data)
760
+ ```
761
+
762
+ ## Contributing
763
+
764
+ ### Development Setup
765
+
766
+ ```bash
767
+ git clone https://github.com/your-repo/formue-crud
768
+ cd formue-crud
769
+ npm install
33
770
  npm run dev
34
771
  ```
35
772
 
36
- ### Type-Check, Compile and Minify for Production
773
+ ### Build Process
37
774
 
38
- ```sh
775
+ ```bash
39
776
  npm run build
777
+ npm run type-check
778
+ npm run lint
40
779
  ```
41
780
 
42
- ### Lint with [ESLint](https://eslint.org/)
781
+ ### Testing
43
782
 
44
- ```sh
45
- npm run lint
783
+ ```bash
784
+ npm run test
785
+ npm run test:unit
786
+ npm run test:e2e
46
787
  ```
788
+
789
+ ---
790
+
791
+ **Version:** 0.1.77
792
+ **Last Updated:** 2024
793
+ **License:** MIT
794
+
795
+ For more information, visit the [GitHub repository](https://github.com/your-repo/formue-crud) or contact the maintainers.