@simitgroup/simpleapp-generator 1.1.1 → 1.1.3
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/framework.js +2 -2
- package/dist/framework.js.map +1 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +22 -46
- package/dist/generate.js.map +1 -1
- package/dist/processors/jsonschemabuilder.js +9 -0
- package/dist/processors/jsonschemabuilder.js.map +1 -1
- package/dist/storage.d.ts +1 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +2 -1
- package/dist/storage.js.map +1 -1
- package/package.json +1 -1
- package/src/framework.ts +2 -2
- package/src/generate.ts +29 -51
- package/src/processors/jsonschemabuilder.ts +12 -2
- package/src/storage.ts +2 -1
- package/templates/basic/nuxt/pages.[id].vue.eta +3 -2
- package/templates/basic/nuxt/pages.form.vue.eta +226 -0
- package/templates/basic/nuxt/pages.landing.vue.eta +19 -43
- package/templates/basic/nuxt/pages.new.vue.eta +7 -210
- package/templates/basic/nuxt/pages.viewer.vue.eta +21 -0
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +2 -1
- package/templates/nest/src/simpleapp/services/docno.service.ts.eta +1 -1
- package/templates/nuxt/app.vue.eta +5 -1
- package/templates/nuxt/assets/css/style.css._eta +33 -15
- package/templates/nuxt/assets/primevue/passthrough.ts._eta +14 -7
- package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +23 -22
- package/templates/nuxt/components/docPage/DocPageList.vue.eta +117 -0
- package/templates/nuxt/components/event/EventDocumentViewer.vue.eta +72 -0
- package/templates/nuxt/components/header/HeaderBar.vue.eta +12 -10
- package/templates/nuxt/components/header/HeaderBreadcrumb.vue.eta +76 -0
- package/templates/nuxt/components/header/button/HeaderButtonMenuPicker.vue.eta +5 -7
- package/templates/nuxt/components/header/button/HeaderButtonProfile.vue.eta +39 -8
- package/templates/nuxt/components/list/ListView.vue.eta +4 -2
- package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +22 -3
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +163 -0
- package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +8 -8
- package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +21 -7
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +24 -63
- package/templates/nuxt/components/table/TableDocuments.vue.eta +15 -9
- package/templates/nuxt/components/user/UserButtonCreateTenant.vue.eta +25 -3
- package/templates/nuxt/components/user/UserProfileListItem.vue.eta +41 -41
- package/templates/nuxt/components/user/UserTenantPicker.vue.eta +26 -14
- package/templates/nuxt/composables/getDocument.generate.ts.eta +1 -1
- package/templates/nuxt/composables/getUserStore.generate.ts.eta +4 -1
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +5 -1
- package/templates/nuxt/composables/themes.generate.ts.eta +1 -0
- package/templates/nuxt/i18n.config.ts.eta +5 -0
- package/templates/nuxt/lang/cn.ts._eta +9 -0
- package/templates/nuxt/lang/df.ts.eta +22 -0
- package/templates/nuxt/lang/en.ts._eta +6 -0
- package/templates/nuxt/layouts/{documentlist.vue.eta → documentlist.vue.eta.disabled} +1 -1
- package/templates/nuxt/nuxt.config.ts.eta +49 -16
- package/templates/nuxt/pages/[xorg]/docnoformat.vue.eta +11 -81
- package/templates/nuxt/pages/[xorg]/organization/[id]/branches/new.vue +1 -1
- package/templates/nuxt/pages/[xorg]/organization.vue.eta +10 -0
- package/templates/nuxt/pages/[xorg]/profile.vue.eta +3 -0
- package/templates/nuxt/pages/[xorg]/user.vue.eta +5 -0
- package/templates/nuxt/pages/index.vue._eta +19 -56
- package/templates/nuxt/pages/profile.vue.eta +12 -12
- package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +3 -0
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +1 -1
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +5 -4
- package/templates/nuxt/simpleapp/generate/commons/documents.ts.eta +4 -1
- package/templates/nuxt/tailwind.config.ts._eta +18 -17
- package/templates/nuxt/types/events.ts.eta +12 -0
- package/templates/nuxt/types/index.ts.eta +2 -1
- package/templates/nuxt/types/others.ts.eta +4 -1
- package/templates/nuxt/types/schema.ts.eta +183 -0
- package/templates/nuxt/types/simpleappinput.ts.eta +1 -0
- package/templates/project/jsonschemas/invoice.json._eta +3 -3
- package/templates/project/jsonschemas/product.json._eta +2 -2
- package/templates/project/sharelibs/money.ts.eta +2 -3
- package/tsconfig.tsbuildinfo +1 -1
- /package/templates/nuxt/layouts/{sidelist.vue.eta → sidelist.vue.eta.disabled} +0 -0
- /package/templates/nuxt/layouts/{sidelistcrud.vue.eta → sidelistcrud.vue.eta.disabled} +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<AutoComplete v-model="modelValue" v-if="!readonly" ref="autocompleteinput"
|
|
3
|
+
forceSelection optionLabel="label"
|
|
4
|
+
@item-select="pickAutoComplete"
|
|
5
|
+
@complete="getListFromAutocompleteApi"
|
|
6
|
+
:placeholder="t('keyword')"
|
|
7
|
+
:dropdown="true"
|
|
8
|
+
:dropdown-icon="buttonClass"
|
|
9
|
+
@before-show="beforeShow"
|
|
10
|
+
@clear = "clear"
|
|
11
|
+
:dropdown-mode="'current'"
|
|
12
|
+
:pt="pt"
|
|
13
|
+
:delay="500"
|
|
14
|
+
:disabled="readonly"
|
|
15
|
+
:suggestions="list"
|
|
16
|
+
@blur="onBlurAutocomplete"
|
|
17
|
+
:inputId="inputId" :path="setting.instancepath"
|
|
18
|
+
:readonly="readonly"
|
|
19
|
+
/>
|
|
20
|
+
<div v-else class="p-3 border rounded-lg border-gray-300 dark:border-blue-900/40 ">
|
|
21
|
+
<span :readonly="readonly" class="cursor-pointer text-primary-600 dark:text-primary-400 "
|
|
22
|
+
tabindex="0" @click="openViewer(true)">{{ modelValue && modelValue.label ? modelValue.label:'-' }}</span>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { isNull } from 'lodash';
|
|
27
|
+
import {autocompletetype,SchemaConfig,SchemaType} from '~/types'
|
|
28
|
+
const autocompleteinput = ref()
|
|
29
|
+
const {$event} = useNuxtApp()
|
|
30
|
+
const list = ref<any[]>([])
|
|
31
|
+
const emptyautocomplete =():autocompletetype=> ({_id:'',code:'',label:''})
|
|
32
|
+
|
|
33
|
+
const props = withDefaults(defineProps<{
|
|
34
|
+
setting:any
|
|
35
|
+
allowAddNew?:boolean
|
|
36
|
+
showNull?:boolean
|
|
37
|
+
readonly?:boolean
|
|
38
|
+
inputId:string
|
|
39
|
+
pt?:any
|
|
40
|
+
}>(),{
|
|
41
|
+
allowAddNew:true,showNull:true
|
|
42
|
+
})
|
|
43
|
+
const autocompleteitem = ref<autocompletetype>(emptyautocomplete())
|
|
44
|
+
const modelValue = defineModel<autocompletetype>()
|
|
45
|
+
if(modelValue.value && modelValue.value._id){
|
|
46
|
+
autocompleteitem.value={...modelValue.value}
|
|
47
|
+
}
|
|
48
|
+
//clear auto complete auto set value = empty
|
|
49
|
+
const clear = ()=>{
|
|
50
|
+
autocompleteitem.value = emptyautocomplete()
|
|
51
|
+
modelValue.value = emptyautocomplete()
|
|
52
|
+
}
|
|
53
|
+
const buttonClass=computed(()=>modelValue.value?._id ? 'pi pi-link' : 'pi pi-angle-down')
|
|
54
|
+
|
|
55
|
+
//if record picked, click button show record info instead
|
|
56
|
+
const beforeShow = ()=>{
|
|
57
|
+
if(modelValue.value?._id ){
|
|
58
|
+
openViewer(true)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//recorrect data if lose focus
|
|
63
|
+
const onBlurAutocomplete = ()=>{
|
|
64
|
+
if( autocompleteitem.value === null){
|
|
65
|
+
autocompleteitem.value = emptyautocomplete()
|
|
66
|
+
}
|
|
67
|
+
if(isNull(modelValue.value )){
|
|
68
|
+
modelValue.value = autocompleteitem.value
|
|
69
|
+
}
|
|
70
|
+
else if(typeof modelValue.value =='object'){
|
|
71
|
+
|
|
72
|
+
}else{
|
|
73
|
+
modelValue.value = autocompleteitem.value
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//obtain remote data
|
|
78
|
+
const getListFromAutocompleteApi = (event:any)=>{
|
|
79
|
+
const keyword = event.query??''
|
|
80
|
+
const targetDocument = props.setting.fieldsetting['x-foreignkey']
|
|
81
|
+
getDocumentApi(targetDocument).autoComplete(keyword).then((res:any)=>{
|
|
82
|
+
|
|
83
|
+
list.value = res.data
|
|
84
|
+
|
|
85
|
+
if(props.allowAddNew){
|
|
86
|
+
list.value = list.value.concat({_id:'new',label:'<'+t('new')+'>'})
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//on select
|
|
92
|
+
const pickAutoComplete = (event:any)=>{
|
|
93
|
+
console.log("event",event,'event.value._id',"'"+event.value._id+"'")
|
|
94
|
+
if(event.value._id===''){
|
|
95
|
+
|
|
96
|
+
modelValue.value = emptyautocomplete()
|
|
97
|
+
autocompleteitem.value = emptyautocomplete()
|
|
98
|
+
console.log(modelValue.value )
|
|
99
|
+
} else if(event.value._id==='new'){
|
|
100
|
+
|
|
101
|
+
modelValue.value = emptyautocomplete()
|
|
102
|
+
autocompleteitem.value = emptyautocomplete()
|
|
103
|
+
openViewer(false)
|
|
104
|
+
}
|
|
105
|
+
else if(typeof event.value.query == 'undefined'){
|
|
106
|
+
modelValue.value=event.value
|
|
107
|
+
autocompleteitem.value = event.value
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const emits = defineEmits(['change','update:modelValue','update:docNoFormat'])
|
|
112
|
+
watch(modelValue ,(newvalue:any)=>{
|
|
113
|
+
|
|
114
|
+
emitChanges()
|
|
115
|
+
|
|
116
|
+
})
|
|
117
|
+
const emitChanges = () =>{
|
|
118
|
+
|
|
119
|
+
emits('change',modelValue.value)
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//pop up records
|
|
124
|
+
const openViewer = (readonly:boolean) =>{
|
|
125
|
+
const remotedoc = getDocument(props.setting.fieldsetting['x-foreignkey'])
|
|
126
|
+
|
|
127
|
+
if(remotedoc){
|
|
128
|
+
const schema:SchemaType = remotedoc.docClass.getSchema()
|
|
129
|
+
const labelfield = schema['x-simpleapp-config'].documentTitle as string
|
|
130
|
+
const codefield = schema['x-simpleapp-config'].uniqueKey as string
|
|
131
|
+
$event('ViewRecord',{
|
|
132
|
+
_id: modelValue.value?._id as string,
|
|
133
|
+
eventId: crypto.randomUUID(),
|
|
134
|
+
label: modelValue.value?.label as string,
|
|
135
|
+
readonly:readonly,
|
|
136
|
+
viewer : getDocument(props.setting.fieldsetting['x-foreignkey'])?.viewer,
|
|
137
|
+
documentName: props.setting.fieldsetting['x-foreignkey'],
|
|
138
|
+
|
|
139
|
+
//after create, auto copy value into auto complete
|
|
140
|
+
afterCreate:(data:any)=>{
|
|
141
|
+
autocompleteitem.value = {
|
|
142
|
+
_id: data._id,
|
|
143
|
+
code: data[codefield],
|
|
144
|
+
label: data[labelfield],
|
|
145
|
+
}
|
|
146
|
+
if(schema['x-simpleapp-config'].additionalAutoCompleteFields){
|
|
147
|
+
const addfields = schema['x-simpleapp-config'].additionalAutoCompleteFields
|
|
148
|
+
for(let i=0;i<addfields.length;i++){
|
|
149
|
+
const fieldname = addfields[i] as string
|
|
150
|
+
autocompleteitem.value[fieldname] = data[fieldname]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
modelValue.value = {...autocompleteitem.value}
|
|
154
|
+
emitChanges()
|
|
155
|
+
console.log("autocompleteitem.value",autocompleteitem.value ,modelValue.value)
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
</script>
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
|
|
2
2
|
<template>
|
|
3
3
|
|
|
4
|
-
<div class="
|
|
5
|
-
<InputText
|
|
4
|
+
<div class="flex flex-row w-full">
|
|
5
|
+
<InputText
|
|
6
6
|
:readonly="readonly"
|
|
7
7
|
v-model="modelValue"
|
|
8
8
|
:placeholder="placeholder"
|
|
9
|
+
:class="'flex-1 w-full rounded-lg '+ ( props.readonly?'':'dark:!bg-gray-700 rounded-tr-none rounded-br-none')"
|
|
9
10
|
/>
|
|
10
|
-
<span class="
|
|
11
|
-
<button type="button" @click="toggle"
|
|
12
|
-
|
|
13
|
-
class="border rounded-tl-none rounded-bl-none btn btn-primary -ml-1 h-full p-3 rounded-r-md">
|
|
11
|
+
<span class="" v-if="!readonly">
|
|
12
|
+
<button type="button" @click="toggle" tabindex="-1"
|
|
13
|
+
class="'btn btn-primary p-3 dark:border-blue-900/40 rounded-lg rounded-tl-none rounded-bl-none">
|
|
14
14
|
<i class="pi pi-angle-down"></i>
|
|
15
15
|
</button>
|
|
16
16
|
<OverlayPanel ref="op" class="p-4">
|
|
17
17
|
<div class="m-4">
|
|
18
18
|
<ul>
|
|
19
19
|
<li v-for="docno in docFormatlist" class="hover-list-primary p-2" >
|
|
20
|
-
<a class="
|
|
20
|
+
<a class="" @click="chooseFormat(docno)">
|
|
21
21
|
<span class="pi pi-hashtag mr-2"></span>
|
|
22
22
|
<span class="">{{docno.docNoFormatName}}</span>
|
|
23
|
-
<span class="
|
|
23
|
+
<span class=" text text-green-600">{{docno.sample}}</span>
|
|
24
24
|
</a>
|
|
25
25
|
</li>
|
|
26
26
|
</ul>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="schema"
|
|
2
|
+
<div v-if="schema" class="flex flex-col">
|
|
3
3
|
<div v-if="hidelabel"></div>
|
|
4
|
-
<label v-else-if="error" class="text-danger-600" :for="uuid">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
|
|
5
|
-
<label v-else :for="uuid">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
|
|
4
|
+
<label v-else-if="error" class="text-danger-600 overflow-hidden" :for="uuid">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
|
|
5
|
+
<label v-else :for="uuid" class="whitespace-nowrap text-gray-500 truncate">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
|
|
6
6
|
|
|
7
7
|
<!-- <div :uuid="uuid" >{{ modelValue }}</div> -->
|
|
8
8
|
<!-- <div v-if="typeof modelValue =='object' && typeof modelValue['_id']!='undefined' && typeof modelValue['label']!='undefined' && readonly ==true " :uuid="uuid" class="simpleapp-value-readonly">{{ modelValue['label'] }}</div> -->
|
|
@@ -24,8 +24,10 @@ import SimpleAppValue from './SimpleAppValue.vue'
|
|
|
24
24
|
// import {computed,setBlockTracking,watch} from 'vue'
|
|
25
25
|
|
|
26
26
|
import {ref} from 'vue'
|
|
27
|
+
|
|
28
|
+
|
|
27
29
|
const uuid = crypto.randomUUID();
|
|
28
|
-
const fieldlabel = ref('')
|
|
30
|
+
// const fieldlabel = ref('')
|
|
29
31
|
// const fielddesc = ref('')
|
|
30
32
|
const defaultcssclass='simpleapp-input-container'
|
|
31
33
|
const fieldcontainerclass = ref(defaultcssclass)
|
|
@@ -57,6 +59,7 @@ let schema:any
|
|
|
57
59
|
const fielddesc = computed(()=>{
|
|
58
60
|
return props.description ?? schema.description ?? ''
|
|
59
61
|
})
|
|
62
|
+
|
|
60
63
|
if(props.setting.fieldsetting && props.setting.fieldsetting.type){
|
|
61
64
|
|
|
62
65
|
schema = props.setting.fieldsetting
|
|
@@ -68,9 +71,8 @@ if(props.setting.fieldsetting && props.setting.fieldsetting.type){
|
|
|
68
71
|
const fieldnamearr = instancepath.value.split('/')
|
|
69
72
|
const fieldname = camelCaseToWords(fieldnamearr[fieldnamearr.length-1])
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
else fieldlabel.value=fieldname
|
|
74
|
+
|
|
75
|
+
|
|
74
76
|
|
|
75
77
|
// if(props.description)fielddesc.value = props.description
|
|
76
78
|
// else if (schema?.description != 'undefined') fielddesc.value=schema.description
|
|
@@ -79,6 +81,18 @@ if(props.setting.fieldsetting && props.setting.fieldsetting.type){
|
|
|
79
81
|
|
|
80
82
|
|
|
81
83
|
}
|
|
84
|
+
const fieldlabel = computed(()=>{
|
|
85
|
+
|
|
86
|
+
if(props.label){
|
|
87
|
+
return t(props.label)
|
|
88
|
+
}
|
|
89
|
+
else if (schema.title ) {
|
|
90
|
+
return t(schema.title)
|
|
91
|
+
}
|
|
92
|
+
else{
|
|
93
|
+
return t(props.setting.key)
|
|
94
|
+
}
|
|
95
|
+
})
|
|
82
96
|
const errormsg = computed(()=>{
|
|
83
97
|
|
|
84
98
|
props.setting.errors[instancepath.value]
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<!-- date component -->
|
|
12
12
|
<component :is="inputComponent" type="date" :pt="pt"
|
|
13
|
-
v-else-if="inputType == SimpleAppInputType.date"
|
|
13
|
+
v-else-if="inputType == SimpleAppInputType.date"
|
|
14
14
|
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
15
15
|
v-model="datevalue" @update:modelValue="updateDate" :readonly="isReadonly"/>
|
|
16
16
|
<!-- calendar component -->
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
v-else-if="[SimpleAppInputType.select,SimpleAppInputType.list].includes(inputType)"
|
|
25
25
|
:inputId="slotprops.uuid" :path="setting.instancepath"
|
|
26
26
|
:readonly="isReadonly"
|
|
27
|
-
|
|
27
|
+
:disabled="isReadonly"
|
|
28
|
+
:options="getListOptions()" optionLabel="label" optionValue="value"/>
|
|
28
29
|
|
|
29
30
|
<!-- radio component -->
|
|
30
31
|
<div v-else-if="inputType == SimpleAppInputType.radio" >
|
|
@@ -37,32 +38,22 @@
|
|
|
37
38
|
</div>
|
|
38
39
|
</div>
|
|
39
40
|
|
|
40
|
-
<!-- autocomplete -->
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
:
|
|
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"
|
|
41
|
+
<!-- autocomplete, need do more enterprise grade component-->
|
|
42
|
+
<SimpleAppAutocomplete v-else-if="inputType==SimpleAppInputType.autocomplete"
|
|
43
|
+
v-model="modelValue"
|
|
44
|
+
:pt="pt"
|
|
45
|
+
:setting="setting"
|
|
46
|
+
:disabled="isReadonly"
|
|
47
|
+
:inputId="slotprops.uuid"
|
|
48
|
+
:path="setting.instancepath"
|
|
59
49
|
:readonly="isReadonly"
|
|
60
50
|
/>
|
|
61
51
|
|
|
62
52
|
<!-- document no input-->
|
|
63
53
|
<SimpleAppDocumentNo v-else-if="inputType == SimpleAppInputType.documentno"
|
|
64
54
|
:setting="setting" v-model="modelValue" :inputId="slotprops.uuid"
|
|
65
|
-
:readonly="isReadonly" @update:docNoFormat="triggerDocNoFormatChange"
|
|
55
|
+
:readonly="isReadonly" @update:docNoFormat="triggerDocNoFormatChange"
|
|
56
|
+
:pt="pt"
|
|
66
57
|
:path="setting.instancepath"/>
|
|
67
58
|
|
|
68
59
|
|
|
@@ -83,13 +74,11 @@
|
|
|
83
74
|
<component v-else-if="inputType == SimpleAppInputType.chip"
|
|
84
75
|
:is="inputComponent" :type="type" v-model="modelValue"
|
|
85
76
|
:pt="pt"
|
|
86
|
-
:disabled="isReadonly"
|
|
87
|
-
|
|
88
|
-
|
|
77
|
+
:disabled="isReadonly"
|
|
89
78
|
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
90
79
|
<!-- simple component -->
|
|
91
|
-
<component v-else :is="inputComponent" :type="type" v-model="modelValue"
|
|
92
|
-
:readonly="isReadonly"
|
|
80
|
+
<component v-else :is="inputComponent" :type="type" v-model="modelValue"
|
|
81
|
+
:readonly="isReadonly"
|
|
93
82
|
class="w-full flex flex-col"
|
|
94
83
|
:inputId="slotprops.uuid" :path="setting.instancepath"/>
|
|
95
84
|
|
|
@@ -100,14 +89,13 @@
|
|
|
100
89
|
</template>
|
|
101
90
|
|
|
102
91
|
<script lang="ts" setup>
|
|
103
|
-
import { isNull, pick } from 'lodash';
|
|
104
|
-
import {autocompletetype} from '~/types'
|
|
105
92
|
import moment from 'moment'
|
|
106
93
|
import AutoComplete from 'primevue/autocomplete';
|
|
107
94
|
import Calendar from 'primevue/calendar';
|
|
108
95
|
import Checkbox from 'primevue/checkbox';
|
|
109
96
|
import Chips from 'primevue/chips';
|
|
110
97
|
import SimpleAppDocumentNo from './SimpleAppDocumentNo.vue';
|
|
98
|
+
import SimpleAppAutocomplete from './SimpleAppAutocomplete.vue'
|
|
111
99
|
import Dropdown from 'primevue/dropdown';
|
|
112
100
|
import InputNumber from 'primevue/inputnumber';
|
|
113
101
|
import InputSwitch from 'primevue/inputswitch';
|
|
@@ -121,12 +109,12 @@ import Slider from 'primevue/slider';
|
|
|
121
109
|
import Textarea from 'primevue/textarea';
|
|
122
110
|
import {SimpleAppInputType} from '~/types'
|
|
123
111
|
|
|
112
|
+
|
|
124
113
|
let inputComponent :Component
|
|
125
|
-
|
|
126
|
-
|
|
114
|
+
|
|
115
|
+
|
|
127
116
|
const datevalue = ref('')
|
|
128
117
|
const modelValue = defineModel()
|
|
129
|
-
const list = ref([])
|
|
130
118
|
const props = withDefaults( defineProps<{
|
|
131
119
|
inputType:SimpleAppInputType,
|
|
132
120
|
label?:string,
|
|
@@ -210,7 +198,7 @@ const isReadonly = computed(()=>{
|
|
|
210
198
|
})
|
|
211
199
|
|
|
212
200
|
const updateDate = (value:any)=>{
|
|
213
|
-
modelValue.value = moment(value).
|
|
201
|
+
modelValue.value = moment(value).format('YYYY-MM-DD')
|
|
214
202
|
}
|
|
215
203
|
|
|
216
204
|
|
|
@@ -235,9 +223,10 @@ watch(modelValue ,(newvalue:any)=>{
|
|
|
235
223
|
|
|
236
224
|
if([SimpleAppInputType.date,SimpleAppInputType.calendar].includes(props.inputType)){
|
|
237
225
|
datevalue.value = moment(modelValue.value as string ).format('YYYY-MM-DD')
|
|
238
|
-
}else if(props.inputType==SimpleAppInputType.autocomplete){
|
|
239
|
-
modelValue.value=autocompleteitem.value
|
|
240
226
|
}
|
|
227
|
+
// else if(props.inputType==SimpleAppInputType.autocomplete){
|
|
228
|
+
// modelValue.value=autocompleteitem.value
|
|
229
|
+
// }
|
|
241
230
|
|
|
242
231
|
emits('change',modelValue.value)
|
|
243
232
|
emits('update:modelValue',modelValue.value)
|
|
@@ -245,35 +234,7 @@ watch(modelValue ,(newvalue:any)=>{
|
|
|
245
234
|
|
|
246
235
|
|
|
247
236
|
/************ 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
237
|
|
|
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
238
|
/************ end autocomplete only ***************/
|
|
278
239
|
|
|
279
240
|
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
:showGridlines="true"
|
|
6
6
|
size="small"
|
|
7
7
|
:pt="{
|
|
8
|
-
|
|
9
|
-
headerRow:{ class:'
|
|
8
|
+
header:{ class:''},
|
|
9
|
+
headerRow:{ class:' bg-gray-200'},
|
|
10
10
|
}"
|
|
11
|
+
v-on:row-click="clickRow"
|
|
11
12
|
:value="value"
|
|
12
13
|
:filters="filters"
|
|
13
14
|
:paginator="true" :rows="20"
|
|
@@ -15,13 +16,13 @@
|
|
|
15
16
|
>
|
|
16
17
|
<!-- header -->
|
|
17
18
|
<template #header>
|
|
18
|
-
<div class=" flex flex-row w-full text-right justify-content-end">
|
|
19
|
+
<div class=" flex flex-row w-full text-right justify-content-end" >
|
|
19
20
|
<div class="flex-1">
|
|
20
21
|
<slot name="toolbar"></slot>
|
|
21
22
|
</div>
|
|
22
23
|
<div class="flex-1">
|
|
23
24
|
<slot name="title">
|
|
24
|
-
<h1 class="text text-2xl pt-2 text-center">{{ title }}</h1>
|
|
25
|
+
<h1 class="text text-2xl pt-2 text-center">{{ t(title) }}</h1>
|
|
25
26
|
</slot>
|
|
26
27
|
|
|
27
28
|
</div>
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
<template #empty>
|
|
36
37
|
<div class="text-center ">
|
|
37
38
|
<div class="text-3xl text-gray-400 pi pi-exclamation-circle"></div>
|
|
38
|
-
<div class="text-3xl text-gray-400">
|
|
39
|
+
<div class="text-3xl text-gray-400">{{t('noDataFound')}}</div>
|
|
39
40
|
|
|
40
41
|
</div>
|
|
41
42
|
</template>
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
<p >{{ t(col) }}</p>
|
|
48
49
|
</template>
|
|
49
50
|
<template v-else-if="typeof col =='object'" #header>
|
|
50
|
-
<span>{{ col.title }} </span>
|
|
51
|
+
<span>{{ t(col.title) }} </span>
|
|
51
52
|
</template>
|
|
52
53
|
<template v-else #header>
|
|
53
54
|
<span class="text-danger-600">unknown</span>
|
|
@@ -100,13 +101,18 @@ import { FilterMatchMode } from 'primevue/api';
|
|
|
100
101
|
import DataTable from 'primevue/datatable';
|
|
101
102
|
import Column from 'primevue/column';
|
|
102
103
|
import renderComponent from '~/components/renderer'
|
|
104
|
+
import { emit } from 'process';
|
|
103
105
|
const props = defineProps<{
|
|
104
106
|
value:any[]
|
|
105
|
-
columns: CellSetting[]
|
|
106
|
-
title:string
|
|
107
|
-
|
|
107
|
+
columns: CellSetting[]
|
|
108
|
+
title:string
|
|
108
109
|
|
|
109
110
|
}>()
|
|
111
|
+
const emits = defineEmits(['selectRow'])
|
|
112
|
+
|
|
113
|
+
const clickRow = (eventdata:any) =>{
|
|
114
|
+
emits('selectRow',eventdata.data)
|
|
115
|
+
}
|
|
110
116
|
|
|
111
117
|
const filters = ref({
|
|
112
118
|
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
|
|
@@ -8,7 +8,29 @@
|
|
|
8
8
|
/> -->
|
|
9
9
|
|
|
10
10
|
<!-- <button class="">Create</button> -->
|
|
11
|
-
<form @submit.prevent="true" class="
|
|
11
|
+
<form @submit.prevent="true" class="w-full">
|
|
12
|
+
<div class="p-inputgroup flex flex-row">
|
|
13
|
+
<InputText
|
|
14
|
+
class="flex-1"
|
|
15
|
+
type="email"
|
|
16
|
+
placeholder="your company name"
|
|
17
|
+
v-model:model-value="data.tenantName"
|
|
18
|
+
/>
|
|
19
|
+
<div class="p-inputgroup-addon p p-0">
|
|
20
|
+
<button
|
|
21
|
+
:label="t('create')"
|
|
22
|
+
class="border rounded-tl-none rounded-bl-none btn btn-primary -ml-1 h-full p-3 rounded-r-md"
|
|
23
|
+
@click="createTenant" :loading="onhold"
|
|
24
|
+
>
|
|
25
|
+
{{t('create')}}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</form>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<!-- <form @submit.prevent="true" class="flex flex-row text-center">
|
|
33
|
+
|
|
12
34
|
<div class="flex flex-col">
|
|
13
35
|
<InputText
|
|
14
36
|
type="text"
|
|
@@ -18,10 +40,10 @@
|
|
|
18
40
|
/>
|
|
19
41
|
<div v-if="errCreateTenant" class="text-error">{{ errCreateTenant }}</div>
|
|
20
42
|
</div>
|
|
21
|
-
<Button class="w-full md:w-auto
|
|
43
|
+
<Button class="w-full md:w-auto dark:border-transparent px-8 py-4 border rounded-md btn btn-primary grid place-items-center font-semibold mt-4 md:mt-0 focus:outline-none focus:ring-2 focus:ring-primary-700 focus:ring-primary-50" type="submit" @click="createTenant" :loading="onhold">
|
|
22
44
|
Create
|
|
23
45
|
</Button>
|
|
24
|
-
</form>
|
|
46
|
+
</form> -->
|
|
25
47
|
</div>
|
|
26
48
|
|
|
27
49
|
|
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
</div>
|
|
2
|
+
<!-- <ul role="list" class="divide-y divide-gray-100">
|
|
3
|
+
<li v-for="person in people" :key="person.email" class="flex justify-between gap-x-6 py-5"> -->
|
|
4
|
+
<div class="flex justify-between gap-x-6 py-5 cursor-pointer">
|
|
5
|
+
<div class="flex min-w-0 gap-x-4">
|
|
6
|
+
<img class="h-12 w-12 flex-none rounded-full bg-gray-50" :src="`${getAvatarLink(data.email,32)}`" alt="" />
|
|
7
|
+
<div class="min-w-0 flex-auto">
|
|
8
|
+
<p class="text-sm font-semibold leading-6 text-gray-900 dark:text-gray-200">{{ data.fullName }}</p>
|
|
9
|
+
<p class="mt-1 truncate text-xs leading-5 text-gray-500 dark:text-gray-400">{{ data.email }}</p>
|
|
11
10
|
</div>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<p class="text-xs leading-5 text-gray-500">Online</p>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="hidden shrink-0 sm:flex sm:flex-col sm:items-end">
|
|
13
|
+
|
|
14
|
+
<div v-if="isOnline" class="mt-1 flex items-center gap-x-1.5">
|
|
15
|
+
<div class="flex-none rounded-full bg-emerald-500/20 p-1">
|
|
16
|
+
<div class="h-1.5 w-1.5 rounded-full bg-emerald-500" />
|
|
19
17
|
</div>
|
|
20
|
-
<p
|
|
21
|
-
<span v-if="datedifferent.get('years')>0">{{ datedifferent.get('years') }} year(s)</span>
|
|
22
|
-
<span v-if="datedifferent.get('months')>0">{{ datedifferent.get('months') }} month(s)</span>
|
|
23
|
-
<span v-if="datedifferent.get('days')>0">{{ datedifferent.get('days') }} day(s)</span>
|
|
24
|
-
<span v-if="datedifferent.get('hours')>0">{{ datedifferent.get('hours') }} Hour(s)</span>
|
|
25
|
-
<span v-if="datedifferent.get('minutes')>0">{{ datedifferent.get('minutes') }} min(s)</span>
|
|
26
|
-
</p>
|
|
27
|
-
<p class="text-sm text-right leading-6 text-gray-400 w-[120px] truncate ...">
|
|
28
|
-
{{ data.description }}
|
|
29
|
-
</p>
|
|
18
|
+
<p class="text-xs leading-5 text-gray-500 dark:text-gray-400">Online</p>
|
|
30
19
|
</div>
|
|
20
|
+
<p v-else class="mt-1 text-xs leading-5 text-gray-500">
|
|
21
|
+
<span v-if="datedifferent.get('years')>0">{{ datedifferent.get('years') }} year(s)</span>
|
|
22
|
+
<span v-if="datedifferent.get('months')>0">{{ datedifferent.get('months') }} month(s)</span>
|
|
23
|
+
<span v-if="datedifferent.get('days')>0">{{ datedifferent.get('days') }} day(s)</span>
|
|
24
|
+
<span v-if="datedifferent.get('hours')>0">{{ datedifferent.get('hours') }} Hour(s)</span>
|
|
25
|
+
<span v-if="datedifferent.get('minutes')>0">{{ datedifferent.get('minutes') }} min(s)</span>
|
|
26
|
+
</p>
|
|
27
|
+
<p class="text-sm text-right leading-6 text-gray-400 w-[120px] truncate ...">
|
|
28
|
+
{{ data.description }}
|
|
29
|
+
</p>
|
|
31
30
|
</div>
|
|
32
|
-
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
33
|
</template>
|
|
34
34
|
|
|
35
35
|
<script setup lang="ts">
|
|
36
36
|
import {computed} from 'vue'
|
|
37
37
|
import moment from 'moment'
|
|
38
38
|
const props = defineProps<{
|
|
39
|
-
|
|
39
|
+
data:any
|
|
40
40
|
}>()
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
const datedifferent = computed(()=>{
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
const data = moment.duration(differentTime.value)
|
|
46
|
+
return data
|
|
47
47
|
})
|
|
48
48
|
const differentTime = computed(()=>{
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
const lasttime = new Date(props.data.lastActivity).getTime()
|
|
50
|
+
const current = new Date().getTime()
|
|
51
|
+
const result = current - lasttime
|
|
52
|
+
return result
|
|
53
53
|
})
|
|
54
54
|
const isOnline = computed(()=>{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
if(props.data.lastActivity) {
|
|
56
|
+
const diffminutes = differentTime.value/ 1000/60
|
|
57
|
+
return diffminutes < 1
|
|
58
|
+
}else{
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
|