@simitgroup/simpleapp-generator 1.0.64 → 1.1.0
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/buildinschemas/user.d.ts.map +1 -1
- package/dist/buildinschemas/user.js +0 -1
- package/dist/buildinschemas/user.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/user.ts +1 -2
- package/templates/basic/nuxt/pages.landing.vue.eta +1 -1
- package/templates/basic/nuxt/pages.new.vue.eta +52 -68
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +0 -1
- package/templates/nuxt/assets/css/style.css._eta +29 -1
- package/templates/nuxt/assets/primevue/passthrough.ts._eta +8 -2
- package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +8 -4
- package/templates/nuxt/components/event/EventNotification.vue.eta +13 -9
- package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +31 -44
- package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +12 -11
- package/templates/nuxt/components/simpleApp/SimpleAppForm.vue.eta +5 -4
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +288 -0
- package/templates/nuxt/components/simpleApp/SimpleAppInputTable.vue.eta +4 -52
- package/templates/nuxt/components/simpleApp/{SimpleAppAutocomplete.vue.eta → pending/SimpleAppAutocomplete.vue} +1 -2
- package/templates/nuxt/components/simpleApp/pending/SimpleAppDocumentNo.vue +90 -0
- package/templates/nuxt/components/simpleApp/pending/SimpleAppInputTable.vue +83 -0
- package/templates/nuxt/components/simpleApp/{SimpleAppText.vue.eta → pending/SimpleAppText.vue} +0 -2
- package/templates/nuxt/composables/getOpenApi.generate.ts.eta +32 -1
- package/templates/nuxt/layouts/default.vue.eta +1 -1
- package/templates/nuxt/layouts/documentlist.vue.eta +4 -4
- package/templates/nuxt/layouts/sidelist.vue.eta +1 -1
- package/templates/nuxt/layouts/sidelistcrud.vue.eta +1 -1
- package/templates/nuxt/nuxt.config.ts.eta +0 -1
- package/templates/nuxt/pages/[xorg]/docnoformat/[doctype]/new.vue.eta +96 -90
- package/templates/nuxt/pages/[xorg]/organization/[id]/branches/new.vue +3 -3
- package/templates/nuxt/pages/[xorg]/organization/new.vue.eta +24 -18
- package/templates/nuxt/pages/[xorg]/organization.vue.eta +32 -17
- package/templates/nuxt/pages/[xorg]/user/index.vue.eta +40 -35
- package/templates/nuxt/pages/[xorg]/user.vue.eta +10 -8
- package/templates/nuxt/pages/index.vue._eta +2 -2
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +4 -1
- package/templates/nuxt/types/index.ts.eta +2 -1
- package/templates/nuxt/types/simpleappinput.ts.eta +39 -0
- package/templates/project/jsonschemas/category.json._eta +3 -3
- package/templates/project/jsonschemas/customer.json._eta +3 -3
- package/templates/project/jsonschemas/invoice.json._eta +3 -3
- package/templates/project/jsonschemas/product.json._eta +3 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/templates/nuxt/composables/getAutocomplete.generate.ts.eta +0 -32
- /package/templates/nuxt/components/{ListView.vue.eta → list/ListView.vue.eta} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppAutocompletemulti.vue.eta → pending/SimpleAppAutocompletemulti.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppCalendar.vue.eta → pending/SimpleAppCalendar.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppCheckbox.vue.eta → pending/SimpleAppCheckbox.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppChip.vue.eta → pending/SimpleAppChip.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppColor.vue.eta → pending/SimpleAppColor.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppDynamicInput.vue.eta → pending/SimpleAppDynamicInput.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppEditor.vue.eta → pending/SimpleAppEditor.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppList.vue.eta → pending/SimpleAppList.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppListmulti.vue.eta → pending/SimpleAppListmulti.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppNumber.vue.eta → pending/SimpleAppNumber.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppPassword.vue.eta → pending/SimpleAppPassword.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppRadio.vue.eta → pending/SimpleAppRadio.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppRating.vue.eta → pending/SimpleAppRating.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppSelect.vue.eta → pending/SimpleAppSelect.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppSelectmulti.vue.eta → pending/SimpleAppSelectmulti.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppSlider.vue.eta → pending/SimpleAppSlider.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppSwitch.vue.eta → pending/SimpleAppSwitch.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppTextarea.vue.eta → pending/SimpleAppTextarea.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{SimpleAppValue.vue.eta → pending/SimpleAppValue.vue} +0 -0
- /package/templates/nuxt/components/simpleApp/{helper.ts.eta → pending/helper.ts-backup} +0 -0
- /package/templates/nuxt/components/simpleApp/{type.ts.eta → pending/type.ts-backup} +0 -0
- /package/templates/nuxt/components/{CrudNestedDoc.vue.eta → suspended/CrudNestedDoc.vue.eta} +0 -0
- /package/templates/nuxt/components/{CrudSimple.vue.eta → suspended/CrudSimple.vue.eta} +0 -0
- /package/templates/nuxt/components/{Menus.vue.eta → suspended/Menus.vue.eta} +0 -0
- /package/templates/nuxt/components/{Spinner.vue.eta → suspended/Spinner.vue.eta} +0 -0
- /package/templates/nuxt/components/{DocumentDatatable.vue.eta → table/TableDocuments.vue.eta} +0 -0
- /package/templates/nuxt/components/{ButtonCreateTenant.vue.eta → user/UserButtonCreateTenant.vue.eta} +0 -0
- /package/templates/nuxt/components/{ButtonPermissionInfo.vue.eta → user/UserButtonPermissionInfo.vue.eta} +0 -0
- /package/templates/nuxt/components/{Invitation.vue.eta → user/UserInvitation.vue.eta} +0 -0
- /package/templates/nuxt/components/{UserProfileListItem.vue.eta → user/UserProfileListItem.vue.eta} +0 -0
- /package/templates/nuxt/components/{TenantPicker.vue.eta → user/UserTenantPicker.vue.eta} +0 -0
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
</form>
|
|
6
6
|
</template>
|
|
7
7
|
<script setup lang="ts" >
|
|
8
|
-
import type {SimpleAppFieldSetting} from '
|
|
9
|
-
import { SimpleAppClient } from '
|
|
8
|
+
// import type {SimpleAppFieldSetting} from '/types'
|
|
9
|
+
import { SimpleAppClient } from '~/simpleapp/generate/clients/SimpleAppClient'
|
|
10
10
|
import type { JSONSchema7,JSONSchema7Definition } from 'json-schema';
|
|
11
|
-
|
|
11
|
+
import _ from 'lodash'
|
|
12
12
|
const props = defineProps<{
|
|
13
13
|
title?:string,
|
|
14
14
|
document: SimpleAppClient<any,any>
|
|
@@ -28,6 +28,7 @@ import type { JSONSchema7,JSONSchema7Definition } from 'json-schema';
|
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
30
|
path: path,
|
|
31
|
+
key: _.last(path.split('/')),
|
|
31
32
|
instancepath: getInstancePath(schema,path),
|
|
32
33
|
fieldsetting: fieldsetting,
|
|
33
34
|
modelObject: data,
|
|
@@ -37,7 +38,7 @@ import type { JSONSchema7,JSONSchema7Definition } from 'json-schema';
|
|
|
37
38
|
isrequired: getIsRequired(schema,path),
|
|
38
39
|
errors: props.document.getErrors(),
|
|
39
40
|
readonly: props.readonly
|
|
40
|
-
} as SimpleAppFieldSetting
|
|
41
|
+
} //as SimpleAppFieldSetting
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
// "schemaPath": "#/properties/email/format",
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SimpleAppFieldContainer :hidelabel="hidelabel" v-model="modelValue"
|
|
3
|
+
:label="label" :description="description"
|
|
4
|
+
:setting="setting" :instancepath="instancepath" :error="error" #default="slotprops">
|
|
5
|
+
<!-- binary input -->
|
|
6
|
+
<component :is="inputComponent" :readonly="isReadonly" :pt="pt"
|
|
7
|
+
v-if="[SimpleAppInputType.checkbox,SimpleAppInputType.switch ].includes(inputType)"
|
|
8
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
9
|
+
v-model="modelValue" :binary="true"/>
|
|
10
|
+
|
|
11
|
+
<!-- date component -->
|
|
12
|
+
<component :is="inputComponent" type="date" :pt="pt"
|
|
13
|
+
v-else-if="inputType == SimpleAppInputType.date"
|
|
14
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
15
|
+
v-model="datevalue" @update:modelValue="updateDate" :readonly="isReadonly"/>
|
|
16
|
+
<!-- calendar component -->
|
|
17
|
+
<component :is="inputComponent" type="date" :pt="pt" class="flex flex-col"
|
|
18
|
+
v-else-if="SimpleAppInputType.calendar==inputType"
|
|
19
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
20
|
+
v-model="datevalue" @update:modelValue="updateDate" :readonly="isReadonly"/>
|
|
21
|
+
|
|
22
|
+
<!-- select/list component -->
|
|
23
|
+
<component :is="inputComponent" v-model="modelValue" :pt="pt"
|
|
24
|
+
v-else-if="[SimpleAppInputType.select,SimpleAppInputType.list].includes(inputType)"
|
|
25
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
26
|
+
:readonly="isReadonly"
|
|
27
|
+
:options="getListOptions()" optionLabel="label" optionValue="value"/>
|
|
28
|
+
|
|
29
|
+
<!-- radio component -->
|
|
30
|
+
<div v-else-if="inputType == SimpleAppInputType.radio" >
|
|
31
|
+
<div v-for="(item,index) in getListOptions()">
|
|
32
|
+
<component :pt="pt" :is="inputComponent" v-model="modelValue"
|
|
33
|
+
:inputId="setting.key+'-'+index" name="smaple" :value="item.value"
|
|
34
|
+
:readonly="isReadonly"
|
|
35
|
+
/> {{ ' ' }}
|
|
36
|
+
<label :for="setting.key+'-'+index"> {{ item.label }} </label>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<!-- autocomplete -->
|
|
41
|
+
<AutoComplete :is="inputComponent" v-model="modelValue"
|
|
42
|
+
v-else-if="inputType==SimpleAppInputType.autocomplete"
|
|
43
|
+
forceSelection optionLabel="label" :dropdown="true"
|
|
44
|
+
@item-select="pickAutoComplete"
|
|
45
|
+
@complete="getListFromAutocompleteApi"
|
|
46
|
+
|
|
47
|
+
:pt="{
|
|
48
|
+
root:{class:'rounded-lg flex flex-row'},
|
|
49
|
+
input:{class:'w-full font-sans text-gray-600 dark:text-white/80 bg-white dark:bg-gray-900 border border-gray-300 dark:border-blue-900/40 rounded-lg rounded-tr-none rounded-br-none transition-colors duration-200 appearance-none hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)] text-base'},
|
|
50
|
+
loadingIcon:{class:'hidden'},
|
|
51
|
+
dropdownbutton: {
|
|
52
|
+
root:' bg-primary-600 hover:bg-primary-400 text-white rounded flex flex-row p-3 rounded-tl-none rounded-bl-none '
|
|
53
|
+
}
|
|
54
|
+
}"
|
|
55
|
+
:disabled="isReadonly"
|
|
56
|
+
:suggestions="list"
|
|
57
|
+
@blur="onBlurAutocomplete"
|
|
58
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
59
|
+
:readonly="isReadonly"
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<!-- document no input-->
|
|
63
|
+
<SimpleAppDocumentNo v-else-if="inputType == SimpleAppInputType.documentno"
|
|
64
|
+
:setting="setting" v-model="modelValue" :inputId="slotprops.uuid"
|
|
65
|
+
:readonly="isReadonly" @update:docNoFormat="triggerDocNoFormatChange"
|
|
66
|
+
:path="setting.instancepath"/>
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
<!-- password -->
|
|
70
|
+
<component :is="inputComponent"
|
|
71
|
+
v-else-if="inputType == SimpleAppInputType.password"
|
|
72
|
+
:type="type" v-model="modelValue" :pt="pt"
|
|
73
|
+
:readonly="isReadonly" class="flex flex-col"
|
|
74
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
75
|
+
|
|
76
|
+
<!-- rating -->
|
|
77
|
+
<Rating v-else-if="inputType == SimpleAppInputType.rating"
|
|
78
|
+
:is="inputComponent" :type="type" v-model="modelValue" :pt="pt"
|
|
79
|
+
:readonly="isReadonly"
|
|
80
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
81
|
+
|
|
82
|
+
<!-- chip -->
|
|
83
|
+
<component v-else-if="inputType == SimpleAppInputType.chip"
|
|
84
|
+
:is="inputComponent" :type="type" v-model="modelValue"
|
|
85
|
+
:pt="pt"
|
|
86
|
+
:disabled="isReadonly"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
90
|
+
<!-- simple component -->
|
|
91
|
+
<component v-else :is="inputComponent" :type="type" v-model="modelValue" :pt="pt"
|
|
92
|
+
:readonly="isReadonly"
|
|
93
|
+
class="w-full flex flex-col"
|
|
94
|
+
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
<!-- component require special treatment -->
|
|
98
|
+
|
|
99
|
+
</SimpleAppFieldContainer>
|
|
100
|
+
</template>
|
|
101
|
+
|
|
102
|
+
<script lang="ts" setup>
|
|
103
|
+
import { isNull, pick } from 'lodash';
|
|
104
|
+
import {autocompletetype} from '~/types'
|
|
105
|
+
import moment from 'moment'
|
|
106
|
+
import AutoComplete from 'primevue/autocomplete';
|
|
107
|
+
import Calendar from 'primevue/calendar';
|
|
108
|
+
import Checkbox from 'primevue/checkbox';
|
|
109
|
+
import Chips from 'primevue/chips';
|
|
110
|
+
import SimpleAppDocumentNo from './SimpleAppDocumentNo.vue';
|
|
111
|
+
import Dropdown from 'primevue/dropdown';
|
|
112
|
+
import InputNumber from 'primevue/inputnumber';
|
|
113
|
+
import InputSwitch from 'primevue/inputswitch';
|
|
114
|
+
import InputText from 'primevue/inputtext';
|
|
115
|
+
import Listbox from 'primevue/listbox';
|
|
116
|
+
import MultiSelect from 'primevue/multiselect';
|
|
117
|
+
import Password from 'primevue/password';
|
|
118
|
+
import RadioButton from 'primevue/radiobutton';
|
|
119
|
+
import Rating from 'primevue/rating';
|
|
120
|
+
import Slider from 'primevue/slider';
|
|
121
|
+
import Textarea from 'primevue/textarea';
|
|
122
|
+
import {SimpleAppInputType} from '~/types'
|
|
123
|
+
|
|
124
|
+
let inputComponent :Component
|
|
125
|
+
const emptyautocomplete =():autocompletetype=> ({_id:'',label:''})
|
|
126
|
+
const autocompleteitem = ref<autocompletetype>(emptyautocomplete())
|
|
127
|
+
const datevalue = ref('')
|
|
128
|
+
const modelValue = defineModel()
|
|
129
|
+
const list = ref([])
|
|
130
|
+
const props = withDefaults( defineProps<{
|
|
131
|
+
inputType:SimpleAppInputType,
|
|
132
|
+
label?:string,
|
|
133
|
+
description?:string,
|
|
134
|
+
error?:string,
|
|
135
|
+
setting:any,
|
|
136
|
+
type?:string,
|
|
137
|
+
instancepath?:string,
|
|
138
|
+
hidelabel?: boolean
|
|
139
|
+
readonly?: boolean
|
|
140
|
+
pt?:any
|
|
141
|
+
}>(),{type:'text'})
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
switch(props.inputType){
|
|
145
|
+
case SimpleAppInputType.text:
|
|
146
|
+
inputComponent = InputText
|
|
147
|
+
break;
|
|
148
|
+
case SimpleAppInputType.textarea:
|
|
149
|
+
inputComponent = Textarea
|
|
150
|
+
break;
|
|
151
|
+
case SimpleAppInputType.number:
|
|
152
|
+
inputComponent = InputNumber
|
|
153
|
+
break
|
|
154
|
+
case SimpleAppInputType.date:
|
|
155
|
+
inputComponent = InputText
|
|
156
|
+
break;
|
|
157
|
+
case SimpleAppInputType.calendar:
|
|
158
|
+
inputComponent = Calendar
|
|
159
|
+
break;
|
|
160
|
+
case SimpleAppInputType.autocomplete:
|
|
161
|
+
inputComponent = AutoComplete
|
|
162
|
+
break;
|
|
163
|
+
case SimpleAppInputType.autocompletemultiple: //*
|
|
164
|
+
inputComponent = AutoComplete
|
|
165
|
+
break;
|
|
166
|
+
case SimpleAppInputType.selectmultiple: //*
|
|
167
|
+
inputComponent = MultiSelect
|
|
168
|
+
break;
|
|
169
|
+
case SimpleAppInputType.listmultiple: //*
|
|
170
|
+
break;
|
|
171
|
+
case SimpleAppInputType.radio: //*
|
|
172
|
+
inputComponent = RadioButton
|
|
173
|
+
break;
|
|
174
|
+
case SimpleAppInputType.select: //*
|
|
175
|
+
inputComponent = Dropdown
|
|
176
|
+
break;
|
|
177
|
+
case SimpleAppInputType.list: //*
|
|
178
|
+
inputComponent = Listbox
|
|
179
|
+
break;
|
|
180
|
+
case SimpleAppInputType.chip: //*
|
|
181
|
+
inputComponent = Chips
|
|
182
|
+
break;
|
|
183
|
+
case SimpleAppInputType.checkbox:
|
|
184
|
+
inputComponent = Checkbox
|
|
185
|
+
break;
|
|
186
|
+
case SimpleAppInputType.switch:
|
|
187
|
+
inputComponent = InputSwitch
|
|
188
|
+
break;
|
|
189
|
+
case SimpleAppInputType.documentno: //*
|
|
190
|
+
break;
|
|
191
|
+
case SimpleAppInputType.password:
|
|
192
|
+
inputComponent = Password
|
|
193
|
+
break;
|
|
194
|
+
case SimpleAppInputType.rating:
|
|
195
|
+
inputComponent = Rating
|
|
196
|
+
break;
|
|
197
|
+
case SimpleAppInputType.slider:
|
|
198
|
+
inputComponent = Slider
|
|
199
|
+
break;
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
const isReadonly = computed(()=>{
|
|
203
|
+
if(props.readonly){
|
|
204
|
+
return props.readonly
|
|
205
|
+
}else if(props.setting.readonly){
|
|
206
|
+
return props.setting.readonly
|
|
207
|
+
}else{
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
const updateDate = (value:any)=>{
|
|
213
|
+
modelValue.value = moment(value).toISOString()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
const getListOptions = () =>{
|
|
218
|
+
|
|
219
|
+
const options = []
|
|
220
|
+
if(props.setting.fieldsetting.enum){
|
|
221
|
+
for(let i=0;i<props.setting.fieldsetting.enum.length;i++){
|
|
222
|
+
const v = props.setting.fieldsetting.enum[i]
|
|
223
|
+
options.push({value:v, label: camelCaseToWords(v)})
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
}
|
|
228
|
+
return options
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
const emits = defineEmits(['change','update:modelValue','update:docNoFormat'])
|
|
233
|
+
|
|
234
|
+
watch(modelValue ,(newvalue:any)=>{
|
|
235
|
+
|
|
236
|
+
if([SimpleAppInputType.date,SimpleAppInputType.calendar].includes(props.inputType)){
|
|
237
|
+
datevalue.value = moment(modelValue.value as string ).format('YYYY-MM-DD')
|
|
238
|
+
}else if(props.inputType==SimpleAppInputType.autocomplete){
|
|
239
|
+
modelValue.value=autocompleteitem.value
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
emits('change',modelValue.value)
|
|
243
|
+
emits('update:modelValue',modelValue.value)
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
/************ start autocomplete only ***************/
|
|
248
|
+
const onBlurAutocomplete = ()=>{
|
|
249
|
+
|
|
250
|
+
if( autocompleteitem.value === null){
|
|
251
|
+
autocompleteitem.value = emptyautocomplete()
|
|
252
|
+
}
|
|
253
|
+
if(isNull(modelValue.value )){
|
|
254
|
+
modelValue.value = autocompleteitem.value
|
|
255
|
+
}
|
|
256
|
+
else if(typeof modelValue.value =='object'){
|
|
257
|
+
|
|
258
|
+
}else{
|
|
259
|
+
modelValue.value = autocompleteitem.value
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
}
|
|
263
|
+
const getListFromAutocompleteApi = (event:any)=>{
|
|
264
|
+
const keyword = event.query??''
|
|
265
|
+
//props.setting.document.getDocType()
|
|
266
|
+
const targetDocument = props.setting.fieldsetting['x-foreignkey']
|
|
267
|
+
getDocumentApi(targetDocument).autoComplete(keyword).then((res:any)=>{
|
|
268
|
+
list.value = res.data
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
const pickAutoComplete = (event:any)=>{
|
|
272
|
+
if(typeof event.value.query == 'undefined'){
|
|
273
|
+
modelValue.value=event.value
|
|
274
|
+
autocompleteitem.value = event.value
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/************ end autocomplete only ***************/
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
const triggerDocNoFormatChange=(formatdata:any)=>{
|
|
284
|
+
emits('update:docNoFormat',formatdata)
|
|
285
|
+
}
|
|
286
|
+
</script>
|
|
287
|
+
<style scoped>
|
|
288
|
+
</style>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</template>
|
|
10
10
|
<slot>
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
|
|
13
13
|
<Column class="text-center" header="undefine columns">
|
|
14
14
|
<template #body>
|
|
@@ -18,30 +18,11 @@
|
|
|
18
18
|
</Column>
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
<!-- </template> -->
|
|
22
21
|
|
|
23
|
-
</slot>
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
</slot>
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
25
|
|
|
35
|
-
<!-- <Column v-for="(col,index) in columns" :field="col.field" :style="col.style" :header="camelCaseToWords(col.title??'')">
|
|
36
|
-
<template #body="{ data, field,index }">
|
|
37
|
-
<SimpleAppDynamicInput v-if="modelValue" :instancepath="getInstancePath(index,field)" :setting="getChildFieldSetting(field)" v-model="modelValue[index][field]" :getAutocomplete="getAutocomplete" :hidelabel="true" />
|
|
38
|
-
</template>
|
|
39
|
-
</Column>
|
|
40
|
-
<Column v-if="!readonly">
|
|
41
|
-
<template #body="{data,field,index}">
|
|
42
|
-
<Button class="simpleapp-inputtable-delrow button-danger" @click="deleteRow(index)" type="button">X</Button>
|
|
43
|
-
</template>
|
|
44
|
-
</Column> -->
|
|
45
26
|
</DataTable>
|
|
46
27
|
</template>
|
|
47
28
|
<script setup lang="ts">
|
|
@@ -49,13 +30,11 @@
|
|
|
49
30
|
import {ref} from 'vue'
|
|
50
31
|
import DataTable from 'primevue/datatable';
|
|
51
32
|
import Column from 'primevue/column';
|
|
52
|
-
|
|
53
|
-
import type {InputTableColumn} from './type'
|
|
33
|
+
|
|
54
34
|
const props = defineProps<{
|
|
55
35
|
// columns:InputTableColumn[],
|
|
56
36
|
setting:any,
|
|
57
|
-
getField:Function,
|
|
58
|
-
getAutocomplete:Function, readonly?:boolean
|
|
37
|
+
getField:Function,
|
|
59
38
|
}>()
|
|
60
39
|
|
|
61
40
|
|
|
@@ -63,33 +42,6 @@ const props = defineProps<{
|
|
|
63
42
|
const modelValue = defineModel<any[]>()
|
|
64
43
|
|
|
65
44
|
|
|
66
|
-
const fieldsetting = props.setting.fieldsetting
|
|
67
|
-
|
|
68
|
-
const readonly = ref(false)
|
|
69
|
-
if(props.setting.readonly!==undefined ){
|
|
70
|
-
readonly.value = props.setting.readonly
|
|
71
|
-
}
|
|
72
|
-
if(props.readonly!==undefined ){
|
|
73
|
-
readonly.value = props.readonly
|
|
74
|
-
}
|
|
75
|
-
// const columns = ref(props.columns)
|
|
76
|
-
// for(let i=0;i<props.columns.length;i++){
|
|
77
|
-
// if(columns.value[i].title ===undefined){
|
|
78
|
-
// columns.value[i].title=columns.value[i].field
|
|
79
|
-
// }
|
|
80
|
-
// }
|
|
81
|
-
const getChildFieldSetting=(field:string)=>{
|
|
82
|
-
return props.getField(`${props.setting.path}/items/properties/${field}`)
|
|
83
|
-
}
|
|
84
|
-
const getInstancePath=(index:number,field:string)=>{
|
|
85
|
-
return `${props.setting.instancepath}/${index}/${field}`
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const deleteRow=(index: number)=>{
|
|
89
|
-
if(modelValue.value){
|
|
90
|
-
modelValue.value.splice(index,1)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
45
|
const addNew = () => {
|
|
94
46
|
const field = props.setting.path.split('/').at(-1)
|
|
95
47
|
props.setting.document[`add${field}`]()
|
|
@@ -115,8 +115,7 @@ const onblur = ()=>{
|
|
|
115
115
|
selecteditem.value={...modelValue.value}
|
|
116
116
|
if(typeof selecteditem.value[labelfield]=='undefined'){
|
|
117
117
|
selecteditem.value[labelfield]=''
|
|
118
|
-
}
|
|
119
|
-
// console.log("selecteditem.value",selecteditem.value)
|
|
118
|
+
}
|
|
120
119
|
}
|
|
121
120
|
const capitalizeFirstLetter = (str: string) => {
|
|
122
121
|
const res = str == '' ? '' : str.slice(0, 1).toUpperCase() + str.slice(1);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
<template>
|
|
3
|
+
<FieldContainer :hidelabel="hidelabel" v-model="modelValue" :label="label" :description="description" :setting="setting" :instancepath="instancepath" :error="error" #default="slotprops">
|
|
4
|
+
<div class="p-inputgroup ">
|
|
5
|
+
<InputText class="simpleapp-inputfield"
|
|
6
|
+
:inputId="slotprops.uuid"
|
|
7
|
+
v-model="modelValue"
|
|
8
|
+
:placeholder="placeholder"
|
|
9
|
+
:path="setting.instancepath"
|
|
10
|
+
:pt="{input:{class:'text-right w-full'}}"
|
|
11
|
+
/>
|
|
12
|
+
<span class="p-inputgroup-addon p p-0">
|
|
13
|
+
<Button class="pi pi-angle-down" type="button" @click="toggle"></Button>
|
|
14
|
+
|
|
15
|
+
<OverlayPanel ref="op">
|
|
16
|
+
<ul>
|
|
17
|
+
<li v-for="docno in docFormatlist" class="hover-list-primary " >
|
|
18
|
+
<a class="flex-row p-2 mt-4" @click="chooseFormat(docno)">
|
|
19
|
+
<span class="pi pi-hashtag mr-2"></span>
|
|
20
|
+
<span class="">{{docno.docNoFormatName}}</span>
|
|
21
|
+
<span class="ml-2 text text-green-600">{{docno.sample}}</span>
|
|
22
|
+
</a>
|
|
23
|
+
</li>
|
|
24
|
+
</ul>
|
|
25
|
+
</OverlayPanel>
|
|
26
|
+
</span>
|
|
27
|
+
<!-- {{ Object.getOwnPropertyNames(setting) }} -->
|
|
28
|
+
</div>
|
|
29
|
+
</FieldContainer>
|
|
30
|
+
</template>
|
|
31
|
+
<script lang="ts" setup>
|
|
32
|
+
import {ForeignKey} from '~/types'
|
|
33
|
+
import OverlayPanel from 'primevue/overlaypanel';
|
|
34
|
+
import {computed,watch,ref} from 'vue'
|
|
35
|
+
import InputText from 'primevue/inputtext';
|
|
36
|
+
import FieldContainer from './SimpleAppFieldContainer.vue'
|
|
37
|
+
import {DocNoFormat} from "~/types"
|
|
38
|
+
const selectedformat = ref()
|
|
39
|
+
const op = ref();
|
|
40
|
+
const placeholder = ref('')
|
|
41
|
+
const docFormatlist = ref()
|
|
42
|
+
const modelValue = defineModel<string>()
|
|
43
|
+
const docNoFormat = defineModel<ForeignKey>('docNoFormat')
|
|
44
|
+
// const emit = defineEmits(['update:docNoFormat'])
|
|
45
|
+
|
|
46
|
+
const props = withDefaults(defineProps<{
|
|
47
|
+
// docNoFormat:object,
|
|
48
|
+
// docFormatlist?:DocNoFormat[]
|
|
49
|
+
label?:string,
|
|
50
|
+
description?:string,
|
|
51
|
+
setting:any
|
|
52
|
+
error?:string,
|
|
53
|
+
instancepath?:string,
|
|
54
|
+
hidelabel?:boolean,
|
|
55
|
+
|
|
56
|
+
}>(),{
|
|
57
|
+
hidelabel:false
|
|
58
|
+
})
|
|
59
|
+
const documenttype = props.setting.document.doctype
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
const toggle = async (event:any) => {
|
|
63
|
+
op.value.toggle(event);
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const chooseFormat = (item:any) =>{
|
|
69
|
+
placeholder.value = item.sample
|
|
70
|
+
const f = item
|
|
71
|
+
docNoFormat.value = { _id : f._id, label : f.docNoFormatName}
|
|
72
|
+
op.value.toggle();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const loadDocFormats = async () =>{
|
|
76
|
+
docFormatlist.value= await getDocFormats(documenttype)
|
|
77
|
+
if(docFormatlist.value.length>0){
|
|
78
|
+
const f = docFormatlist.value[0]
|
|
79
|
+
docNoFormat.value = { _id : f._id, label : f.docNoFormatName}
|
|
80
|
+
placeholder.value = docFormatlist.value[0].sample
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
onMounted(()=>{
|
|
87
|
+
loadDocFormats()
|
|
88
|
+
|
|
89
|
+
})
|
|
90
|
+
</script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DataTable v-bind="$attrs" stripedRows resizableColumns
|
|
3
|
+
class="simpleapp-datatable p-datatable-sm" :value="modelValue">
|
|
4
|
+
<template #empty> <div class="text-center">No record found.</div> </template>
|
|
5
|
+
<template #header >
|
|
6
|
+
<div>
|
|
7
|
+
<Button icon="pi pi-plus" @click="addNew()" class="simpleapp-datatable-add btn-primary" type="button">Add</Button>
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
<slot>
|
|
11
|
+
<!-- <template> -->
|
|
12
|
+
|
|
13
|
+
<Column class="text-center" header="undefine columns">
|
|
14
|
+
<template #body>
|
|
15
|
+
<div class="text-center">Missing {{ '<Column></Column>' }}</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
</Column>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
<!-- </template> -->
|
|
22
|
+
|
|
23
|
+
</slot>
|
|
24
|
+
</DataTable>
|
|
25
|
+
</template>
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
|
|
28
|
+
import {ref} from 'vue'
|
|
29
|
+
import DataTable from 'primevue/datatable';
|
|
30
|
+
import Column from 'primevue/column';
|
|
31
|
+
import {camelCaseToWords} from './helper'
|
|
32
|
+
import type {InputTableColumn} from './type'
|
|
33
|
+
const props = defineProps<{
|
|
34
|
+
// columns:InputTableColumn[],
|
|
35
|
+
setting:any,
|
|
36
|
+
getField:Function,
|
|
37
|
+
getAutocomplete:Function, readonly?:boolean
|
|
38
|
+
}>()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
//{path: '#/properties/details', instancepath: '/details', fieldsetting: {…}, modelObject: Proxy(Object), apiObj: INVApi, …}
|
|
42
|
+
const modelValue = defineModel<any[]>()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const fieldsetting = props.setting.fieldsetting
|
|
46
|
+
|
|
47
|
+
const readonly = ref(false)
|
|
48
|
+
if(props.setting.readonly!==undefined ){
|
|
49
|
+
readonly.value = props.setting.readonly
|
|
50
|
+
}
|
|
51
|
+
if(props.readonly!==undefined ){
|
|
52
|
+
readonly.value = props.readonly
|
|
53
|
+
}
|
|
54
|
+
// const columns = ref(props.columns)
|
|
55
|
+
// for(let i=0;i<props.columns.length;i++){
|
|
56
|
+
// if(columns.value[i].title ===undefined){
|
|
57
|
+
// columns.value[i].title=columns.value[i].field
|
|
58
|
+
// }
|
|
59
|
+
// }
|
|
60
|
+
const getChildFieldSetting=(field:string)=>{
|
|
61
|
+
return props.getField(`${props.setting.path}/items/properties/${field}`)
|
|
62
|
+
}
|
|
63
|
+
const getInstancePath=(index:number,field:string)=>{
|
|
64
|
+
return `${props.setting.instancepath}/${index}/${field}`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const deleteRow=(index: number)=>{
|
|
68
|
+
if(modelValue.value){
|
|
69
|
+
modelValue.value.splice(index,1)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const addNew = () => {
|
|
73
|
+
const field = props.setting.path.split('/').at(-1)
|
|
74
|
+
props.setting.document[`add${field}`]()
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 1. support array with field to label
|
|
78
|
+
* 2. auto add edit button
|
|
79
|
+
* 3. option readonly or not readonly
|
|
80
|
+
* 4.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
</script>
|
package/templates/nuxt/components/simpleApp/{SimpleAppText.vue.eta → pending/SimpleAppText.vue}
RENAMED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
<template>
|
|
3
3
|
<FieldContainer :hidelabel="hidelabel" v-model="modelValue" :label="label" :description="description" :setting="setting" :instancepath="instancepath" :error="error" #default="slotprops">
|
|
4
|
-
|
|
5
|
-
|
|
6
4
|
<InputText v-if="slotprops.error"
|
|
7
5
|
class="simpleapp-inputfield simpleapp-invalid-input"
|
|
8
6
|
:id="slotprops.uuid"
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator during initialization.
|
|
3
|
+
* DO NOT MODIFY IT BY HAND.
|
|
4
|
+
* last change 2023-09-09
|
|
5
|
+
* author: Ks Tan
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import * as o from "../simpleapp/generate/openapi";
|
|
2
9
|
import axios from 'axios'
|
|
10
|
+
export const getDocumentApi = (apiname: string): any => {
|
|
11
|
+
//const { csrf } = useCsrf()
|
|
12
|
+
//axios.defaults.headers.common = {"CSRF-TOKEN": csrf};
|
|
13
|
+
const route = useRoute();
|
|
3
14
|
|
|
4
|
-
|
|
15
|
+
const config: o.Configuration = {
|
|
16
|
+
basePath: `${useRuntimeConfig().public.APP_URL}/api/${route.params.xorg}`,
|
|
17
|
+
isJsonMime: () => true,
|
|
18
|
+
};
|
|
19
|
+
const docsOpenapi: any = {
|
|
20
|
+
<% for(let i=0;i<it.modules.length; i++){ %>
|
|
21
|
+
'<%=it.modules[i].docname.toLowerCase()%>': new o.<%=it.modules[i].doctype.toUpperCase()%>Api(config),
|
|
22
|
+
<%}%>
|
|
23
|
+
};
|
|
24
|
+
if (!docsOpenapi[apiname]) {
|
|
25
|
+
console.error(
|
|
26
|
+
`api for '${apiname}' does not exists, most probably define wrong x-foreignkey`,
|
|
27
|
+
);
|
|
28
|
+
return undefined;
|
|
29
|
+
} else {
|
|
30
|
+
return docsOpenapi[apiname];
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export const getAllApi=()=>{
|
|
5
36
|
return o
|
|
6
37
|
}
|
|
@@ -148,8 +148,8 @@ watch(()=> useRoute().meta ,(newvalue,oldvalue)=>{
|
|
|
148
148
|
<div>
|
|
149
149
|
|
|
150
150
|
<HeaderBar />
|
|
151
|
-
<
|
|
152
|
-
<
|
|
151
|
+
<UserInvitation/>
|
|
152
|
+
<TableDocuments :value="recordlist" :columns="tablecolumns" :title="String(useRoute().meta.name)">
|
|
153
153
|
<template #toolbar>
|
|
154
154
|
<div class="w-full text-left">
|
|
155
155
|
<slot>
|
|
@@ -162,10 +162,10 @@ watch(()=> useRoute().meta ,(newvalue,oldvalue)=>{
|
|
|
162
162
|
</template>
|
|
163
163
|
<Column header=" ">
|
|
164
164
|
<template #body="{index,data}">
|
|
165
|
-
<Button @click="goTo(String(useRoute().meta.documentName),data._id)" icon="pi pi-pencil" class="
|
|
165
|
+
<Button @click="goTo(String(useRoute().meta.documentName),data._id)" icon="pi pi-pencil" class="btn btn-primary" >Edit</Button>
|
|
166
166
|
</template>
|
|
167
167
|
</Column>
|
|
168
|
-
</
|
|
168
|
+
</TableDocuments>
|
|
169
169
|
<!--
|
|
170
170
|
<DebugDocumentData v-model="data"/>
|
|
171
171
|
-->
|