@ramathibodi/nuxt-commons 0.1.35 → 0.1.36

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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.1.35",
7
+ "version": "0.1.36",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.3",
10
10
  "unbuild": "2.0.0"
@@ -31,7 +31,7 @@ const resize = (event: MouseEvent) => {
31
31
  <v-card :="$attrs">
32
32
  <v-sheet
33
33
  border
34
- :height="height"
34
+ :height="props.height"
35
35
  >
36
36
  <div
37
37
  ref="containerRef"
@@ -73,10 +73,14 @@ async function convertToAdvanceMode() {
73
73
  }
74
74
  }
75
75
 
76
- const inputTypeChoice = ref(['VTextField', 'VTextarea', 'VSelect', 'VAutocomplete', 'FormDate', 'FormTime', 'FormDateTime', 'VCombobox', 'VRadio', 'VRadioInline', 'VCheckbox', 'VSwitch', 'MasterAutocomplete', 'Header', 'Separator', 'CustomCode'])
76
+ const inputTypeChoice = ref(['VTextField', 'VTextarea', 'VSelect', 'VAutocomplete', 'FormDate', 'FormTime', 'FormDateTime', 'VCombobox', 'VRadio', 'VRadioInline', 'VCheckbox', 'VSwitch', 'MasterAutocomplete', 'Header', 'Separator', 'CustomCode', 'FormTable', 'FormHidden', 'FormFile', 'FormSignPad'])
77
77
  const requireOption = ref(['VSelect', 'VAutocomplete', 'VCombobox', 'VRadio', 'VRadioInline', 'MasterAutocomplete'])
78
78
  const notRequireVariable = ref(['Header', 'Separator', 'CustomCode'])
79
- const notRequireLabel = ref(['Separator', 'CustomCode'])
79
+ const notRequireLabel = ref(['Separator', 'CustomCode', 'FormFile', 'FormSignPad', 'FormTable', 'FormHidden'])
80
+ const notRequireOptions = ref(['CustomCode', 'FormSignPad', 'FormFile', 'FormTable'])
81
+ const notRequireRules = ref(['CustomCode', 'FormSignPad', 'FormFile', 'FormTable' ,'FormHidden'])
82
+ const notRequireInputAttributes = ref(['CustomCode', 'FormHidden'])
83
+ const notRequireColumnAttributes = ref(['Separator', 'FormHidden'])
80
84
 
81
85
  const choiceOption = ref(['VSelect', 'VRadio', 'VRadioInline'])
82
86
 
@@ -128,25 +132,23 @@ const ruleOptions = (inputType: string) => (value: any) => {
128
132
  type="number"
129
133
  />
130
134
  </v-col>
131
- <v-col cols="4">
135
+ <v-col cols="4" v-if="!notRequireLabel.includes(data.inputType)">
132
136
  <v-text-field
133
- v-if="!notRequireLabel.includes(data.inputType)"
134
- v-model="data.inputLabel"
135
- label="Input Label"
136
- :rules="[rules.require()]"
137
+ v-model="data.inputLabel"
138
+ label="Input Label"
139
+ :rules="[rules.require()]"
137
140
  />
138
141
  </v-col>
139
- <v-col cols="4">
142
+ <v-col cols="4" v-if="!notRequireVariable.includes(data.inputType)">
140
143
  <v-text-field
141
- v-if="!notRequireVariable.includes(data.inputType)"
142
- v-model="data.variableName"
143
- label="Variable Name"
144
- :rules="[rules.require()]"
144
+ v-model="data.variableName"
145
+ label="Variable Name"
146
+ :rules="[rules.require()]"
145
147
  />
146
148
  </v-col>
147
149
  <v-col
148
- v-if="data.inputType!='CustomCode'"
149
- cols="12"
150
+ v-if="!notRequireOptions.includes(data.inputType)"
151
+ cols="12"
150
152
  >
151
153
  <v-textarea
152
154
  v-model="data.inputOptions"
@@ -179,9 +181,29 @@ const ruleOptions = (inputType: string) => (value: any) => {
179
181
  cols="12"
180
182
  >
181
183
  <FormCodeEditor
182
- v-model="data.inputCustomCode"
183
- label="Custom Code"
184
- :rules="[rules.require()]"
184
+ v-model="data.inputCustomCode"
185
+ label="Custom Code"
186
+ :rules="[rules.require()]"
187
+ />
188
+ </v-col>
189
+ <v-col
190
+ v-if="data.inputType=='FormTable'"
191
+ cols="12"
192
+ >
193
+ <FormCodeEditor
194
+ v-model="data.inputFormTable"
195
+ label="Form Table"
196
+ :rules="[rules.require()]"
197
+ />
198
+ </v-col>
199
+ <v-col
200
+ v-if="data.inputType=='FormHidden'"
201
+ cols="12"
202
+ >
203
+ <FormCodeEditor
204
+ v-model="data.inputFormHidden"
205
+ label="Form Table"
206
+ :rules="[rules.require()]"
185
207
  />
186
208
  </v-col>
187
209
  </v-row>
@@ -201,10 +223,18 @@ const ruleOptions = (inputType: string) => (value: any) => {
201
223
  <template v-if="props.item.inputAttributes">
202
224
  <b>Input Attributes :</b> {{ props.item.inputAttributes }}<br>
203
225
  </template>
226
+ <template v-if="props.item.inputType=='FormTable'">
227
+ <b>Form Table :</b><br>
228
+ <span style="white-space: pre-line">{{ props.item.inputFormTable }}</span>
229
+ </template>
230
+ <template v-if="props.item.inputType=='FormHidden'">
231
+ <b>Form Hidden :</b><br>
232
+ <span style="white-space: pre-line">{{ props.item.inputFormHidden }}</span>
233
+ </template>
204
234
  </template>
205
235
  </FormTable>
206
236
  <FormCodeEditor
207
- v-else
208
- v-model="modelValue"
237
+ v-else
238
+ v-model="modelValue"
209
239
  />
210
240
  </template>
@@ -0,0 +1,133 @@
1
+ <script lang="ts" setup>
2
+ import {computed, defineExpose, ref, watchEffect} from 'vue'
3
+ import {cloneDeep, isEqual} from 'lodash-es'
4
+ import type {FormDialogCallback} from '../../types/formDialog'
5
+
6
+ interface Props {
7
+ title?: string
8
+ initialData?: object
9
+ createCaption?: string
10
+ updateCaption?: string
11
+ cancelCaption?: string
12
+ showTitle?: boolean
13
+ }
14
+
15
+ const props = withDefaults(defineProps<Props>(), {
16
+ createCaption: 'Add',
17
+ updateCaption: 'Save',
18
+ cancelCaption: 'Cancel',
19
+ showTitle: false,
20
+ })
21
+
22
+ const isSaving = ref<boolean>(false)
23
+ const formPadRef = ref()
24
+ const formOriginalData = ref<object>()
25
+ const formData = ref<object>({})
26
+
27
+ const emit = defineEmits(['create', 'update'])
28
+
29
+ function save() {
30
+ if (formPadRef.value.isValid) {
31
+ isSaving.value = true
32
+ emit((isCreating.value) ? 'create' : 'update', cloneDeep(formData.value), callback)
33
+ }
34
+ }
35
+
36
+ function cancel() {
37
+ reset()
38
+ }
39
+
40
+ function reset() {
41
+ formOriginalData.value = undefined
42
+ loadFormData()
43
+ }
44
+
45
+ const callback: FormDialogCallback = {
46
+ done: function () {
47
+ isSaving.value = false
48
+ reset()
49
+ },
50
+ error: function () {
51
+ isSaving.value = false
52
+ },
53
+ }
54
+
55
+ const isDataChange = computed(() => {
56
+ return !((isCreating.value) ? isEqual(formData.value, createOriginalValue.value) : isEqual(formData.value, formOriginalData.value))
57
+ })
58
+
59
+ const isCreating = computed(() => {
60
+ return !formOriginalData.value
61
+ })
62
+
63
+ const createOriginalValue = computed(() => {
64
+ return Object.assign({}, props.initialData)
65
+ })
66
+
67
+ const loadFormData = () => {
68
+ if (formOriginalData.value) {
69
+ formData.value = cloneDeep(formOriginalData.value)
70
+ }
71
+ else {
72
+ formData.value = Object.assign({}, props.initialData)
73
+ }
74
+ }
75
+
76
+ watchEffect(loadFormData)
77
+
78
+ function setOriginalData(originalData?: object) {
79
+ formOriginalData.value = originalData
80
+ }
81
+
82
+ defineExpose({setOriginalData,reset})
83
+ </script>
84
+
85
+ <template>
86
+ <VCard flat>
87
+ <VToolbar v-if="showTitle">
88
+ <VToolbarTitle>
89
+ <slot name="title">
90
+ {{ (isCreating) ? "New" : "Edit" }} {{ title }}
91
+ </slot>
92
+ </VToolbarTitle>
93
+ <VSpacer />
94
+ </VToolbar>
95
+ <VCardText>
96
+ <form-pad
97
+ ref="formPadRef"
98
+ v-model="formData"
99
+ isolated
100
+ >
101
+ <template #default="slotData">
102
+ <slot
103
+ v-bind="slotData"
104
+ :is-creating="isCreating"
105
+ :is-data-change="isDataChange"
106
+ />
107
+ </template>
108
+ </form-pad>
109
+ </VCardText>
110
+ <VCardActions>
111
+ <slot name="action" :save="save" :cancel="cancel">
112
+ <VSpacer />
113
+ <VBtn
114
+ color="primary"
115
+ variant="flat"
116
+ :loading="isSaving"
117
+ :disabled="!isDataChange"
118
+ @click="save"
119
+ >
120
+ {{ (isCreating) ? createCaption : updateCaption }}
121
+ </VBtn>
122
+ <VBtn
123
+ color="error"
124
+ variant="flat"
125
+ :disabled="isSaving"
126
+ @click="cancel"
127
+ >
128
+ {{ cancelCaption }}
129
+ </VBtn>
130
+ </slot>
131
+ </VCardActions>
132
+ </VCard>
133
+ </template>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import {VDataTable} from 'vuetify/components/VDataTable'
3
- import {computed, defineOptions,defineExpose, nextTick, ref, useAttrs, watch} from 'vue'
3
+ import {computed, defineOptions,defineExpose, nextTick, ref, useAttrs, watch, useTemplateRef} from 'vue'
4
4
  import {omit} from 'lodash-es'
5
5
  import type {FormDialogCallback} from '../../types/formDialog'
6
6
 
@@ -20,6 +20,8 @@ interface Props extends /* @vue-ignore */ InstanceType<typeof VDataTable['$props
20
20
  exportable?: boolean
21
21
  insertable?: boolean
22
22
  searchable?: boolean
23
+ inputPad?: boolean
24
+ inputPadOnly?: boolean
23
25
  }
24
26
 
25
27
  const props = withDefaults(defineProps<Props>(), {
@@ -31,6 +33,8 @@ const props = withDefaults(defineProps<Props>(), {
31
33
  exportable: true,
32
34
  insertable: true,
33
35
  searchable: true,
36
+ inputPad: false,
37
+ inputPadOnly: false,
34
38
  })
35
39
 
36
40
  const emit = defineEmits(['update:modelValue'])
@@ -153,11 +157,15 @@ function deleteItem(deleteItem: Record<string, any>, callback?: FormDialogCallba
153
157
  }
154
158
 
155
159
  function openDialog(item?: object) {
156
- currentItem.value = item
157
- nextTick(() => {
158
- isDialogOpen.value = true
159
- })
160
+ if (props.inputPadOnly) inputPadRef.value?.setOriginalData(item)
161
+ else {
162
+ currentItem.value = item
163
+ nextTick(() => {
164
+ isDialogOpen.value = true
165
+ })
166
+ }
160
167
  }
168
+ const inputPadRef = useTemplateRef("inputPadRef")
161
169
 
162
170
  const operation = ref({ openDialog, createItem, updateItem, deleteItem, moveUpItem, moveDownItem,moveToItem,setSearch })
163
171
 
@@ -219,7 +227,7 @@ defineExpose({operation})
219
227
  :color="toolbarColor"
220
228
  />
221
229
  <VBtn
222
- v-if="props.insertable"
230
+ v-if="props.insertable && !props.inputPadOnly"
223
231
  :color="toolbarColor"
224
232
  prepend-icon="mdi:mdi-plus"
225
233
  variant="flat"
@@ -282,6 +290,7 @@ defineExpose({operation})
282
290
  :form-data="currentItem"
283
291
  @create="createItem"
284
292
  @update="updateItem"
293
+ v-if="!props.inputPadOnly"
285
294
  >
286
295
  <template #default="slotData">
287
296
  <slot
@@ -291,4 +300,16 @@ defineExpose({operation})
291
300
  </template>
292
301
  </FormDialog>
293
302
  </v-card>
303
+ <slot name="inputPad" :operation="operation">
304
+ <v-sheet border rounded class="mt-1" v-if="inputPad">
305
+ <form-action-pad ref="inputPadRef" :title="props.title" @create="createItem" @update="updateItem" :initial-data="initialData">
306
+ <template #default="slotData">
307
+ <slot
308
+ name="form"
309
+ v-bind="slotData"
310
+ />
311
+ </template>
312
+ </form-action-pad>
313
+ </v-sheet>
314
+ </slot>
294
315
  </template>
@@ -223,7 +223,7 @@ onMounted(() => {
223
223
  </VToolbar>
224
224
  <v-img
225
225
  :src="image.data"
226
- @click="() => { (readonly) ? openImageFullScreen(image) : setDataUpdate(image)}"
226
+ @click="() => { (props.readonly) ? openImageFullScreen(image) : setDataUpdate(image)}"
227
227
  height="250"
228
228
  />
229
229
  </VCard>
@@ -53,6 +53,15 @@ function templateItemToString(item) {
53
53
  case "Header":
54
54
  templateString = `<div class="${optionString ? optionString.trim() : "text-h4 font-weight-medium"}">${item.inputLabel || item.variableName}</div>`;
55
55
  break;
56
+ case "FormTable":
57
+ templateString = `<form-table v-model="data.${item.variableName}" label="${item.inputLabel || item.variableName}"${validationRules ? " " + validationRules.trim() : ""} ${item.inputAttributes ? " " + item.inputAttributes : ""}>${optionString ? " " + optionString.trim() : ""}
58
+ <template #form>${item.inputFormTable}</template>
59
+ </form-table>`;
60
+ break;
61
+ case "FormHidden":
62
+ templateString = `${item.inputOptions} / ${item.inputFormHidden} <form-hidden v-model="data.${item.variableName}" :item-value="${item.inputOptions ? item.inputOptions : "data"}" :hook="() => {${item.inputFormHidden}}">
63
+ </form-hidden>`;
64
+ break;
56
65
  default:
57
66
  templateString = `<${item.inputType} v-model="data.${item.variableName}" label="${item.inputLabel || item.variableName}"${item.inputAttributes ? " " + item.inputAttributes : ""}${optionString ? " " + optionString.trim() : ""}${validationRules ? " " + validationRules.trim() : ""}></${item.inputType}>`;
58
67
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramathibodi/nuxt-commons",
3
- "version": "0.1.35",
3
+ "version": "0.1.36",
4
4
  "description": "Ramathibodi Nuxt modules for common components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -115,5 +115,5 @@
115
115
  "vitest": "^1.6.0",
116
116
  "vue-tsc": "2.0.29"
117
117
  },
118
- "packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab"
118
+ "packageManager": "pnpm@9.15.0+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c"
119
119
  }