qdadm 0.45.1 → 0.46.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qdadm",
3
- "version": "0.45.1",
3
+ "version": "0.46.1",
4
4
  "description": "Vue 3 framework for admin dashboards with PrimeVue",
5
5
  "author": "quazardous",
6
6
  "license": "MIT",
@@ -0,0 +1,120 @@
1
+ <script setup>
2
+ /**
3
+ * FormInput - Auto-renders the appropriate input based on field config
4
+ *
5
+ * Takes a field config object and renders the matching PrimeVue component.
6
+ * Supports hint override but field.type takes precedence if specified.
7
+ *
8
+ * Usage:
9
+ * <FormInput :field="f" v-model="form.data.value[f.name]" />
10
+ */
11
+ import { computed } from 'vue'
12
+ import InputText from 'primevue/inputtext'
13
+ import InputNumber from 'primevue/inputnumber'
14
+ import Textarea from 'primevue/textarea'
15
+ import Select from 'primevue/select'
16
+ import Checkbox from 'primevue/checkbox'
17
+ import Password from 'primevue/password'
18
+ import DatePicker from 'primevue/datepicker'
19
+
20
+ const props = defineProps({
21
+ field: { type: Object, required: true },
22
+ modelValue: { default: null },
23
+ hint: { type: String, default: null } // Optional type hint override
24
+ })
25
+
26
+ const emit = defineEmits(['update:modelValue'])
27
+
28
+ const value = computed({
29
+ get: () => props.modelValue,
30
+ set: (v) => emit('update:modelValue', v)
31
+ })
32
+
33
+ // Resolve component type: field.type > hint > 'text'
34
+ const inputType = computed(() => props.field?.type || props.hint || 'text')
35
+
36
+ // Date value with string ↔ Date conversion for DatePicker
37
+ const dateValue = computed({
38
+ get: () => {
39
+ const v = props.modelValue
40
+ if (!v) return null
41
+ if (v instanceof Date) return v
42
+ // Convert ISO string to Date
43
+ return new Date(v)
44
+ },
45
+ set: (v) => {
46
+ // Convert Date back to ISO string for storage
47
+ emit('update:modelValue', v ? v.toISOString() : null)
48
+ }
49
+ })
50
+ </script>
51
+
52
+ <template>
53
+ <InputText
54
+ v-if="inputType === 'text' || inputType === 'email'"
55
+ v-model="value"
56
+ :placeholder="field.placeholder"
57
+ :disabled="field.disabled"
58
+ :readonly="field.readonly"
59
+ class="w-full"
60
+ />
61
+ <Password
62
+ v-else-if="inputType === 'password'"
63
+ v-model="value"
64
+ :placeholder="field.placeholder"
65
+ :disabled="field.disabled"
66
+ :feedback="false"
67
+ toggleMask
68
+ class="w-full"
69
+ />
70
+ <InputNumber
71
+ v-else-if="inputType === 'number'"
72
+ v-model="value"
73
+ :placeholder="field.placeholder"
74
+ :disabled="field.disabled"
75
+ :readonly="field.readonly"
76
+ :useGrouping="false"
77
+ class="w-full"
78
+ />
79
+ <Textarea
80
+ v-else-if="inputType === 'textarea'"
81
+ v-model="value"
82
+ :placeholder="field.placeholder"
83
+ :disabled="field.disabled"
84
+ :readonly="field.readonly"
85
+ rows="3"
86
+ class="w-full"
87
+ />
88
+ <Select
89
+ v-else-if="inputType === 'select'"
90
+ v-model="value"
91
+ :options="field.options"
92
+ :optionLabel="field.optionLabel"
93
+ :optionValue="field.optionValue"
94
+ :placeholder="field.placeholder"
95
+ :disabled="field.disabled"
96
+ class="w-full"
97
+ />
98
+ <Checkbox
99
+ v-else-if="inputType === 'boolean'"
100
+ v-model="value"
101
+ :disabled="field.disabled"
102
+ binary
103
+ />
104
+ <DatePicker
105
+ v-else-if="inputType === 'date' || inputType === 'datetime'"
106
+ v-model="dateValue"
107
+ :placeholder="field.placeholder"
108
+ :disabled="field.disabled"
109
+ :showTime="inputType === 'datetime'"
110
+ class="w-full"
111
+ />
112
+ <!-- Fallback to text -->
113
+ <InputText
114
+ v-else
115
+ v-model="value"
116
+ :placeholder="field.placeholder"
117
+ :disabled="field.disabled"
118
+ class="w-full"
119
+ />
120
+ </template>
@@ -234,7 +234,7 @@ function onGuardStay() {
234
234
  <!-- Unsaved Changes Dialog -->
235
235
  <UnsavedChangesDialog
236
236
  v-if="guardDialog"
237
- v-model:visible="guardDialog.visible"
237
+ :visible="guardDialog.visible.value"
238
238
  :saving="saving"
239
239
  :hasOnSave="!!guardDialog.onSave"
240
240
  @saveAndLeave="onGuardSaveAndLeave"
@@ -22,6 +22,7 @@ export { default as DefaultToaster } from './layout/defaults/DefaultToaster.vue'
22
22
  // Forms
23
23
  export { default as FormPage } from './forms/FormPage.vue'
24
24
  export { default as FormField } from './forms/FormField.vue'
25
+ export { default as FormInput } from './forms/FormInput.vue'
25
26
  export { default as FormActions } from './forms/FormActions.vue'
26
27
  export { default as FormTabs } from './forms/FormTabs.vue'
27
28
  export { default as FormTab } from './forms/FormTab.vue'
@@ -495,9 +495,36 @@ export function useFormPageBuilder(config = {}) {
495
495
  fieldOrder.value.push(name)
496
496
  }
497
497
 
498
+ // Auto-resolve reference options (async, non-blocking)
499
+ resolveReferences()
500
+
498
501
  return builderApi
499
502
  }
500
503
 
504
+ /**
505
+ * Resolve reference options for all fields with reference config
506
+ *
507
+ * Called automatically by generateFields(). Loads options from
508
+ * referenced entities and updates field configs reactively.
509
+ *
510
+ * @returns {Promise<void>}
511
+ */
512
+ async function resolveReferences() {
513
+ for (const [name, config] of fieldsMap.value.entries()) {
514
+ // Skip if field has static options or no reference
515
+ if (config.options || !config.reference) continue
516
+
517
+ try {
518
+ const options = await manager.resolveReferenceOptions(name)
519
+ // Update field config reactively
520
+ const updatedConfig = { ...config, options }
521
+ fieldsMap.value.set(name, updatedConfig)
522
+ } catch (error) {
523
+ console.warn(`[useFormPageBuilder] Failed to resolve options for field '${name}':`, error)
524
+ }
525
+ }
526
+ }
527
+
501
528
  /**
502
529
  * Resolve field configuration from schema definition
503
530
  *
@@ -512,6 +539,8 @@ export function useFormPageBuilder(config = {}) {
512
539
  required = false,
513
540
  default: defaultValue,
514
541
  options = null,
542
+ optionLabel = 'label',
543
+ optionValue = 'value',
515
544
  placeholder = null,
516
545
  disabled = false,
517
546
  readonly = false,
@@ -532,6 +561,8 @@ export function useFormPageBuilder(config = {}) {
532
561
  required,
533
562
  default: defaultValue,
534
563
  options,
564
+ optionLabel,
565
+ optionValue,
535
566
  placeholder,
536
567
  disabled,
537
568
  readonly,
@@ -1108,6 +1139,7 @@ export function useFormPageBuilder(config = {}) {
1108
1139
  // Field management
1109
1140
  fields,
1110
1141
  generateFields,
1142
+ resolveReferences,
1111
1143
  addField,
1112
1144
  removeField,
1113
1145
  excludeField,