@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.
Files changed (76) hide show
  1. package/dist/framework.js +2 -2
  2. package/dist/framework.js.map +1 -1
  3. package/dist/generate.d.ts.map +1 -1
  4. package/dist/generate.js +22 -46
  5. package/dist/generate.js.map +1 -1
  6. package/dist/processors/jsonschemabuilder.js +9 -0
  7. package/dist/processors/jsonschemabuilder.js.map +1 -1
  8. package/dist/storage.d.ts +1 -0
  9. package/dist/storage.d.ts.map +1 -1
  10. package/dist/storage.js +2 -1
  11. package/dist/storage.js.map +1 -1
  12. package/package.json +1 -1
  13. package/src/framework.ts +2 -2
  14. package/src/generate.ts +29 -51
  15. package/src/processors/jsonschemabuilder.ts +12 -2
  16. package/src/storage.ts +2 -1
  17. package/templates/basic/nuxt/pages.[id].vue.eta +3 -2
  18. package/templates/basic/nuxt/pages.form.vue.eta +226 -0
  19. package/templates/basic/nuxt/pages.landing.vue.eta +19 -43
  20. package/templates/basic/nuxt/pages.new.vue.eta +7 -210
  21. package/templates/basic/nuxt/pages.viewer.vue.eta +21 -0
  22. package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +2 -1
  23. package/templates/nest/src/simpleapp/services/docno.service.ts.eta +1 -1
  24. package/templates/nuxt/app.vue.eta +5 -1
  25. package/templates/nuxt/assets/css/style.css._eta +33 -15
  26. package/templates/nuxt/assets/primevue/passthrough.ts._eta +14 -7
  27. package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +23 -22
  28. package/templates/nuxt/components/docPage/DocPageList.vue.eta +117 -0
  29. package/templates/nuxt/components/event/EventDocumentViewer.vue.eta +72 -0
  30. package/templates/nuxt/components/header/HeaderBar.vue.eta +12 -10
  31. package/templates/nuxt/components/header/HeaderBreadcrumb.vue.eta +76 -0
  32. package/templates/nuxt/components/header/button/HeaderButtonMenuPicker.vue.eta +5 -7
  33. package/templates/nuxt/components/header/button/HeaderButtonProfile.vue.eta +39 -8
  34. package/templates/nuxt/components/list/ListView.vue.eta +4 -2
  35. package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +22 -3
  36. package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +163 -0
  37. package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +8 -8
  38. package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +21 -7
  39. package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +24 -63
  40. package/templates/nuxt/components/table/TableDocuments.vue.eta +15 -9
  41. package/templates/nuxt/components/user/UserButtonCreateTenant.vue.eta +25 -3
  42. package/templates/nuxt/components/user/UserProfileListItem.vue.eta +41 -41
  43. package/templates/nuxt/components/user/UserTenantPicker.vue.eta +26 -14
  44. package/templates/nuxt/composables/getDocument.generate.ts.eta +1 -1
  45. package/templates/nuxt/composables/getUserStore.generate.ts.eta +4 -1
  46. package/templates/nuxt/composables/stringHelper.generate.ts.eta +5 -1
  47. package/templates/nuxt/composables/themes.generate.ts.eta +1 -0
  48. package/templates/nuxt/i18n.config.ts.eta +5 -0
  49. package/templates/nuxt/lang/cn.ts._eta +9 -0
  50. package/templates/nuxt/lang/df.ts.eta +22 -0
  51. package/templates/nuxt/lang/en.ts._eta +6 -0
  52. package/templates/nuxt/layouts/{documentlist.vue.eta → documentlist.vue.eta.disabled} +1 -1
  53. package/templates/nuxt/nuxt.config.ts.eta +49 -16
  54. package/templates/nuxt/pages/[xorg]/docnoformat.vue.eta +11 -81
  55. package/templates/nuxt/pages/[xorg]/organization/[id]/branches/new.vue +1 -1
  56. package/templates/nuxt/pages/[xorg]/organization.vue.eta +10 -0
  57. package/templates/nuxt/pages/[xorg]/profile.vue.eta +3 -0
  58. package/templates/nuxt/pages/[xorg]/user.vue.eta +5 -0
  59. package/templates/nuxt/pages/index.vue._eta +19 -56
  60. package/templates/nuxt/pages/profile.vue.eta +12 -12
  61. package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +3 -0
  62. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +1 -1
  63. package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +5 -4
  64. package/templates/nuxt/simpleapp/generate/commons/documents.ts.eta +4 -1
  65. package/templates/nuxt/tailwind.config.ts._eta +18 -17
  66. package/templates/nuxt/types/events.ts.eta +12 -0
  67. package/templates/nuxt/types/index.ts.eta +2 -1
  68. package/templates/nuxt/types/others.ts.eta +4 -1
  69. package/templates/nuxt/types/schema.ts.eta +183 -0
  70. package/templates/nuxt/types/simpleappinput.ts.eta +1 -0
  71. package/templates/project/jsonschemas/invoice.json._eta +3 -3
  72. package/templates/project/jsonschemas/product.json._eta +2 -2
  73. package/templates/project/sharelibs/money.ts.eta +2 -3
  74. package/tsconfig.tsbuildinfo +1 -1
  75. /package/templates/nuxt/layouts/{sidelist.vue.eta → sidelist.vue.eta.disabled} +0 -0
  76. /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="p-inputgroup w-full flex flex-row">
5
- <InputText class="flex-1 rounded-tr-none rounded-br-none"
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="p-inputgroup-addon p p-0">
11
- <button type="button" @click="toggle"
12
- :disabled="readonly"
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="flex-row p-2 mt-4" @click="chooseFormat(docno)">
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="ml-2 text text-green-600">{{docno.sample}}</span>
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" :class="fieldcontainerclass">
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
- if(props.label)fieldlabel.value = props.label
72
- else if (schema.title ) fieldlabel.value=schema.title
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
- :options="getListOptions()" optionLabel="label" optionValue="value"/>
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
- <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"
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" :pt="pt"
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
- const emptyautocomplete =():autocompletetype=> ({_id:'',label:''})
126
- const autocompleteitem = ref<autocompletetype>(emptyautocomplete())
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).toISOString()
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
- // header:{ class:'border bg-gray-100'},
9
- headerRow:{ class:'border bg-gray-200'},
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">no data found</div>
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="flex flex-row text-center">
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 bg-primary-800 dark:border-transparent text-white px-8 py-4 border rounded-md hover:bg-primary-800 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">
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
- <!-- <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">{{ data.fullName }}</p>
9
- <p class="mt-1 truncate text-xs leading-5 text-gray-500">{{ data.email }}</p>
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
- <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" />
17
- </div>
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 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>
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
- data:any
39
+ data:any
40
40
  }>()
41
41
 
42
42
 
43
43
 
44
44
  const datedifferent = computed(()=>{
45
- const data = moment.duration(differentTime.value)
46
- return data
45
+ const data = moment.duration(differentTime.value)
46
+ return data
47
47
  })
48
48
  const differentTime = computed(()=>{
49
- const lasttime = new Date(props.data.lastActivity).getTime()
50
- const current = new Date().getTime()
51
- const result = current - lasttime
52
- return result
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
- if(props.data.lastActivity) {
56
- const diffminutes = differentTime.value/ 1000/60
57
- return diffminutes < 1
58
- }else{
59
- return false
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