@ramathibodi/nuxt-commons 0.1.61 → 0.1.63
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
|
@@ -12,11 +12,10 @@ import {
|
|
|
12
12
|
watch,
|
|
13
13
|
withDefaults
|
|
14
14
|
} from 'vue'
|
|
15
|
-
import {isObject} from 'lodash-es'
|
|
16
15
|
import {watchDebounced} from '@vueuse/core'
|
|
17
16
|
import {useRules} from '../../composables/utils/validation'
|
|
18
17
|
import {useDocumentTemplate} from '../../composables/document/template'
|
|
19
|
-
import { isArray, isString, isPlainObject, isEqual } from 'lodash-es'
|
|
18
|
+
import { isObject, isArray, isString, isPlainObject, isEqual } from 'lodash-es'
|
|
20
19
|
import FormPad from './Pad.vue'
|
|
21
20
|
|
|
22
21
|
defineOptions({
|
|
@@ -85,7 +84,7 @@ const formInjected = ref()
|
|
|
85
84
|
const formData = ref<any>({})
|
|
86
85
|
|
|
87
86
|
function isBlankString(v: unknown): v is string {
|
|
88
|
-
return isString(v) && v.length === 0
|
|
87
|
+
return isString(v) && v.trim().length === 0
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
function sanitizeBlankStrings(val: any, original?: any): void {
|
|
@@ -101,6 +100,8 @@ function sanitizeBlankStrings(val: any, original?: any): void {
|
|
|
101
100
|
val.splice(i, 1)
|
|
102
101
|
} else if (isPlainObject(item) || isArray(item)) {
|
|
103
102
|
sanitizeBlankStrings(item,{})
|
|
103
|
+
} else {
|
|
104
|
+
if (item && typeof item.trimEnd == "function") val[i] = item.trimEnd()
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
return
|
|
@@ -111,9 +112,12 @@ function sanitizeBlankStrings(val: any, original?: any): void {
|
|
|
111
112
|
const v = val[key]
|
|
112
113
|
if (isBlankString(v)) {
|
|
113
114
|
if (original && !Object.keys(original).includes(key)) delete val[key]
|
|
115
|
+
else val[key] = null
|
|
114
116
|
} else if (isPlainObject(v) || isArray(v)) {
|
|
115
117
|
let originalChild = (original && (isPlainObject(original[key]) || isArray(original[key]))) ? original[key] : {}
|
|
116
118
|
sanitizeBlankStrings(v, originalChild)
|
|
119
|
+
} else {
|
|
120
|
+
if (v && typeof v.trimEnd == "function") val[key] = v.trimEnd()
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
}
|
|
@@ -128,6 +132,37 @@ watch(() => props.modelValue, (newValue) => {
|
|
|
128
132
|
formData.value = isObject(newValue) ? newValue : {}
|
|
129
133
|
}, { deep: true, immediate: true })
|
|
130
134
|
|
|
135
|
+
function diffPaths(
|
|
136
|
+
a: any,
|
|
137
|
+
b: any,
|
|
138
|
+
base: string[] = [],
|
|
139
|
+
out: string[] = []
|
|
140
|
+
): string[] {
|
|
141
|
+
const keys = new Set<string>([
|
|
142
|
+
...Object.keys(a ?? {}),
|
|
143
|
+
...Object.keys(b ?? {}),
|
|
144
|
+
])
|
|
145
|
+
|
|
146
|
+
for (const k of keys) {
|
|
147
|
+
const av = a?.[k]
|
|
148
|
+
const bv = b?.[k]
|
|
149
|
+
if (!av && !bv) continue // ignore when both are falsy
|
|
150
|
+
|
|
151
|
+
const path = [...base, k]
|
|
152
|
+
|
|
153
|
+
if (isPlainObject(av) && isPlainObject(bv)) {
|
|
154
|
+
diffPaths(av, bv, path, out)
|
|
155
|
+
continue
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!isEqual(av, bv)) {
|
|
159
|
+
out.push(path.join('.'))
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return out
|
|
164
|
+
}
|
|
165
|
+
|
|
131
166
|
const injectedClass = computed<Record<string, string>>(() => {
|
|
132
167
|
const data = (formData.value ?? {}) as Record<string, any>
|
|
133
168
|
const result: Record<string, string> = {}
|
|
@@ -135,13 +170,11 @@ const injectedClass = computed<Record<string, string>>(() => {
|
|
|
135
170
|
if (!props.dirtyOnCreate && !props.originalData) return result
|
|
136
171
|
|
|
137
172
|
const original = (props.originalData ?? {}) as Record<string, any>
|
|
173
|
+
const cls = props.dirtyClass || 'form-data-dirty'
|
|
174
|
+
|
|
175
|
+
const paths = diffPaths(data, original)
|
|
176
|
+
for (const p of paths) result[p] = cls
|
|
138
177
|
|
|
139
|
-
for (const key of Object.keys(data)) {
|
|
140
|
-
if (!isEqual(data[key], original[key])) {
|
|
141
|
-
if (!data[key] && !original[key]) continue
|
|
142
|
-
result[key] = props.dirtyClass || 'form-data-dirty'
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
178
|
return result
|
|
146
179
|
})
|
|
147
180
|
|
|
@@ -282,5 +315,5 @@ defineExpose({
|
|
|
282
315
|
/>
|
|
283
316
|
</template>
|
|
284
317
|
<style>
|
|
285
|
-
.form-data-dirty,.form-data-dirty *{color:color-mix(in srgb,currentColor 70%,rgb(var(--v-theme-primary)))!important;text-shadow:0 0 .02em currentColor}
|
|
318
|
+
.form-data-dirty,.form-data-dirty:not(.v-input--error) *{color:color-mix(in srgb,currentColor 70%,rgb(var(--v-theme-primary)))!important;text-shadow:0 0 .02em currentColor}
|
|
286
319
|
</style>
|
|
@@ -10,10 +10,16 @@ defineOptions({
|
|
|
10
10
|
})
|
|
11
11
|
|
|
12
12
|
interface Props extends /* @vue-ignore */ InstanceType<typeof EditPad['$props']> {
|
|
13
|
+
title?: string
|
|
14
|
+
saveCaption?: string
|
|
15
|
+
cancelCaption?: string
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
const props = withDefaults(defineProps<Props & GraphqlModelItemProps>(), {
|
|
16
19
|
fields: () => ['*'],
|
|
20
|
+
|
|
21
|
+
saveCaption: 'บันทึก',
|
|
22
|
+
cancelCaption: 'ยกเลิก',
|
|
17
23
|
})
|
|
18
24
|
|
|
19
25
|
const emit = defineEmits(['create', 'update'])
|
|
@@ -75,7 +81,7 @@ defineExpose({ operation, formPad: editPad.value?.formPad })
|
|
|
75
81
|
:disabled="!slotData.operation?.isDataChange || !canSave"
|
|
76
82
|
@click="slotData.operation?.save"
|
|
77
83
|
>
|
|
78
|
-
{{ saveCaption }}
|
|
84
|
+
{{ props.saveCaption }}
|
|
79
85
|
</VBtn>
|
|
80
86
|
<VBtn
|
|
81
87
|
color="error"
|
|
@@ -83,15 +89,13 @@ defineExpose({ operation, formPad: editPad.value?.formPad })
|
|
|
83
89
|
:disabled="isLoading"
|
|
84
90
|
@click="slotData.operation?.cancel"
|
|
85
91
|
>
|
|
86
|
-
{{ cancelCaption }}
|
|
92
|
+
{{ props.cancelCaption }}
|
|
87
93
|
</VBtn>
|
|
88
94
|
</slot>
|
|
89
95
|
</template>
|
|
90
96
|
<template #default="slotData">
|
|
91
97
|
<slot
|
|
92
98
|
v-bind="slotData"
|
|
93
|
-
:is-creating="isCreating"
|
|
94
|
-
:is-data-change="isDataChange"
|
|
95
99
|
/>
|
|
96
100
|
</template>
|
|
97
101
|
</FormEditPad>
|