@simitgroup/simpleapp-generator 1.2.6 → 1.2.8

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 (91) hide show
  1. package/README.md +6 -0
  2. package/dist/buildinschemas/organization.js +2 -2
  3. package/dist/buildinschemas/organization.js.map +1 -1
  4. package/dist/framework.js +3 -3
  5. package/dist/framework.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/buildinschemas/organization.ts +2 -2
  8. package/src/framework.ts +3 -3
  9. package/templates/basic/nest/controller.ts.eta +25 -21
  10. package/templates/basic/nest/service.ts.eta +5 -5
  11. package/templates/basic/nuxt/default.ts.eta +1 -1
  12. package/templates/basic/nuxt/pages.form.vue.eta +4 -4
  13. package/templates/basic/nuxt/pages.landing.vue.eta +9 -0
  14. package/templates/basic/nuxt/pages.viewer.vue.eta +4 -3
  15. package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +6 -17
  16. package/templates/nest/src/simpleapp/apischemas/index.ts._eta +10 -0
  17. package/templates/nest/src/simpleapp/generate/apischemas/index.ts.eta +7 -19
  18. package/templates/nest/src/simpleapp/generate/apischemas/simpleapp.apischema.ts.eta +20 -0
  19. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +9 -3
  20. package/templates/nest/src/simpleapp/generate/types/index.ts.eta +3 -3
  21. package/templates/nest/src/simpleapp/generate/types/simpleapp.type.ts.eta +1 -4
  22. package/templates/nest/src/simpleapp/types/index.ts._eta +7 -0
  23. package/templates/nuxt/app.vue.eta +7 -3
  24. package/templates/nuxt/assets/css/calendar.css._eta +50 -0
  25. package/templates/nuxt/assets/css/style.css._eta +1 -5
  26. package/templates/nuxt/assets/primevue/passthrough.ts._eta +38 -16
  27. package/templates/nuxt/components/button/ButtonDanger.vue._eta +6 -0
  28. package/templates/nuxt/components/button/ButtonDefault.vue._eta +6 -0
  29. package/templates/nuxt/components/button/ButtonPrimary.vue._eta +6 -0
  30. package/templates/nuxt/components/button/ButtonWarning.vue._eta +6 -0
  31. package/templates/nuxt/components/calendar/CalendarByResource.vue.eta +188 -0
  32. package/templates/nuxt/components/calendar/CalendarSmall.vue.eta +74 -0
  33. package/templates/nuxt/components/docPage/DocPageList.vue.eta +48 -40
  34. package/templates/nuxt/components/event/EventDocumentViewer.vue._eta +12 -12
  35. package/templates/nuxt/components/event/EventNotification.vue._eta +23 -2
  36. package/templates/nuxt/components/header/HeaderBar.vue._eta +32 -19
  37. package/templates/nuxt/components/header/HeaderBreadcrumb.vue.eta +2 -2
  38. package/templates/nuxt/components/header/button/HeaderButtonMenuPicker.vue._eta +7 -15
  39. package/templates/nuxt/components/header/button/HeaderButtonProfile.vue.eta +23 -34
  40. package/templates/nuxt/components/list/ListView.vue.eta +10 -8
  41. package/templates/nuxt/components/renderer/RendererBoolean.vue.eta +6 -1
  42. package/templates/nuxt/components/renderer/RendererDate.vue.eta +6 -0
  43. package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +7 -1
  44. package/templates/nuxt/components/renderer/RendererLink.vue.eta +33 -0
  45. package/templates/nuxt/components/renderer/RendererMoney.vue.eta +20 -2
  46. package/templates/nuxt/components/renderer/RendererMultiText.vue.eta +6 -0
  47. package/templates/nuxt/components/renderer/RendererViewer.vue.eta +32 -0
  48. package/templates/nuxt/components/renderer/{index.ts.eta → index.ts._eta} +10 -2
  49. package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +37 -12
  50. package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +8 -2
  51. package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +24 -17
  52. package/templates/nuxt/components/simpleApp/SimpleAppForm.vue.eta +1 -1
  53. package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue.eta +3 -2
  54. package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +25 -8
  55. package/templates/nuxt/components/simpleApp/SimpleAppInputTable.vue.eta +4 -3
  56. package/templates/nuxt/components/simpleApp/pending/SimpleAppValue.vue +1 -1
  57. package/templates/nuxt/components/user/UserProfileListItem.vue.eta +2 -2
  58. package/templates/nuxt/composables/date.generate.ts.eta +16 -0
  59. package/templates/nuxt/composables/goTo.generate.ts.eta +1 -0
  60. package/templates/nuxt/composables/screensize.generate.ts.eta +1 -0
  61. package/templates/nuxt/composables/stringHelper.generate.ts.eta +3 -6
  62. package/templates/nuxt/error.vue._eta +4 -4
  63. package/templates/nuxt/layouts/default.vue._eta +32 -8
  64. package/templates/nuxt/layouts/loginlayout.vue._eta +3 -0
  65. package/templates/nuxt/layouts/mobile.vue._eta +29 -0
  66. package/templates/nuxt/nuxt.config.ts._eta +27 -13
  67. package/templates/nuxt/pages/[xorg]/index.vue._eta +11 -9
  68. package/templates/nuxt/pages/[xorg]/organization.vue.eta +5 -0
  69. package/templates/nuxt/pages/[xorg]/user/{index.vue._eta → index.vue.eta} +10 -12
  70. package/templates/nuxt/pages/login.vue._eta +34 -0
  71. package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +35 -22
  72. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +6 -0
  73. package/templates/nuxt/server/api/[xorg]/[...].ts.eta +7 -40
  74. package/templates/nuxt/server/api/profile/[...].ts.eta +3 -32
  75. package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +1 -1
  76. package/templates/nuxt/types/calendar.ts.eta +61 -0
  77. package/templates/nuxt/types/documentlist.ts.eta +6 -0
  78. package/templates/nuxt/types/events.ts.eta +5 -5
  79. package/templates/nuxt/types/index.ts._eta +4 -3
  80. package/templates/nuxt/types/listview.ts.eta +6 -0
  81. package/templates/nuxt/types/notifications.ts.eta +6 -1
  82. package/templates/nuxt/types/others.ts.eta +10 -2
  83. package/templates/nuxt/types/schema.ts.eta +8 -0
  84. package/templates/nuxt/types/simpleappinput.ts.eta +6 -0
  85. package/templates/nuxt/types/user.ts.eta +8 -0
  86. package/templates/nuxt/types/workflow.ts.eta +6 -1
  87. package/templates/project/lang/default._json +4 -1
  88. package/tsconfig.tsbuildinfo +1 -1
  89. package/templates/nuxt/pages/login.vue.eta +0 -30
  90. /package/templates/nuxt/pages/[xorg]/user/{[id].vue._eta → [id].vue.eta} +0 -0
  91. /package/templates/nuxt/pages/[xorg]/{user.vue._eta → user.vue.eta} +0 -0
@@ -1,8 +1,9 @@
1
1
  <template>
2
- <div v-if="schema" class="flex flex-col">
3
- <div v-if="hidelabel"></div>
4
- <label v-else-if="error" class="simpleapp-input-label 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="simpleapp-input-label whitespace-nowrap text-gray-500 truncate">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
2
+ <div v-if="schema" :class="getLayoutClass()">
3
+ <label v-if="hidelabel"></label>
4
+ <label v-else :for="uuid" :class="getLabelClass()" @click="console.log(inputType)">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
5
+ <!-- <label v-else-if="error" class="simpleapp-input-label text-danger-600 overflow-hidden" :for="uuid">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label>
6
+ <label v-else :for="uuid" class="simpleapp-input-label whitespace-nowrap text-gray-500 truncate">{{ fieldlabel }} <span v-if="props.setting.isrequired && fieldlabel" class="text-danger-600">*</span></label> -->
6
7
 
7
8
  <!-- <div :uuid="uuid" >{{ modelValue }}</div> -->
8
9
  <!-- <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> -->
@@ -26,7 +27,7 @@ import SimpleAppValue from './SimpleAppValue.vue'
26
27
  import {ref} from 'vue'
27
28
 
28
29
 
29
- const uuid = crypto.randomUUID();
30
+ const uuid = randomUUID();
30
31
  // const fieldlabel = ref('')
31
32
  // const fielddesc = ref('')
32
33
  const defaultcssclass='simpleapp-input-container'
@@ -34,6 +35,7 @@ const fieldcontainerclass = ref(defaultcssclass)
34
35
  let instancepath = ref('')
35
36
  const props = defineProps<{
36
37
  label?: string,
38
+ inputType: string,
37
39
  description?: string,
38
40
  instancepath?:string,
39
41
  hidelabel?:boolean,
@@ -45,17 +47,27 @@ const props = defineProps<{
45
47
  const readonly = computed(()=>{
46
48
  return props.readonly ?? props.setting.readonly ?? false
47
49
  })
48
- // if(props.readonly !== undefined){
49
- // readonly.value=props.readonly
50
- // }else if(props.setting.readonly !==undefined){
51
- // readonly.value=props.readonly
52
- // }
53
- // console.log("props.setting.format",props.setting.format)
54
- const modelValue = defineModel()
50
+
51
+ const modelValue = defineModel<any>() //this model value support all kind of data, string, number, autocomplete and etc
55
52
  const readonlyclass="simpleapp-value-readonly"
56
53
  // console.log('props.setting',modelValue.value,props.setting)
57
54
  let schema:any
58
55
 
56
+ const getLayoutClass = () => `simpleapp-input-container flex ${ props.inputType == 'checkbox' ? " flex-row gap-4 mt-1 ml-1 " : "flex flex-col "}`
57
+
58
+ const getLabelClass = () => {
59
+ let class1= "simpleapp-input-label text-left text-gray-500 "
60
+ if(!isMobile()) class1 += "whitespace-nowrap truncate"
61
+ else if (props.inputType == 'checkbox' ) class1 += " ml-1 dark:text-grey-200"
62
+ else if (props.inputType != 'autocomplete' && modelValue.value) class1 += "-mb-4 ml-1 z-50 text-xs dark:text-grey-100"
63
+ else if (props.inputType == 'autocomplete' && modelValue.value?.label) class1 += "-mb-4 ml-1 z-50 text-xs dark:text-grey-100"
64
+ else if (props.inputType == 'number' && modelValue.value !== undefined) class1 += "-mb-4 ml-1 z-50 text-xs dark:text-grey-100"
65
+ else class1 += "-mb-4 ml-1 z-50 text-xs dark:text-grey-100 hidden"
66
+ return class1
67
+ }
68
+
69
+
70
+
59
71
  const fielddesc = computed(()=>{
60
72
  return props.description ?? ''
61
73
  })
@@ -116,8 +128,3 @@ watch(props.setting.errors,(newvalue,oldvalue)=>{
116
128
  })
117
129
 
118
130
  </script>
119
- <style scoped>
120
- .simpleapp-input-container{
121
- @apply flex flex-col
122
- }
123
- </style>
@@ -34,7 +34,7 @@ import _, { upperFirst } from 'lodash'
34
34
  type keytype = keyof defaulttype
35
35
 
36
36
  const x : keytype = 'Default'+ props.document.getDocName(true) as keytype
37
- const defaultvalue = alldefaults[x](crypto.randomUUID())
37
+ const defaultvalue = alldefaults[x](randomUUID())
38
38
  return {
39
39
  path: path,
40
40
  key: _.last(path.split('/')),
@@ -1,14 +1,15 @@
1
1
  <template>
2
+ <!-- dont modify this component -->
2
3
  <div class="simpleapp-tool-bar flex flex-row text-left gap-4">
3
4
  <div v-for="(menu,index) in menus" :key="index">
4
5
  <div>
5
- <Button v-if="showMenuButton(menu)" @click="emitEvent(menu,$event)">{{ menu.label }}</Button>
6
+ <ButtonDefault v-if="showMenuButton(menu)" @click="emitEvent(menu,$event)">{{ menu.label }}</ButtonDefault>
6
7
  </div>
7
8
 
8
9
  </div>
9
10
  <div v-for="(menu,index) in getDocActions()" :key="index">
10
11
  <div>
11
- <Button @click="emitEvent(menu,$event)">{{ menu.label }}</Button>
12
+ <ButtonDefault @click="emitEvent(menu,$event)">{{ menu.label }}</ButtonDefault>
12
13
  </div>
13
14
 
14
15
  </div>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <SimpleAppFieldContainer :hidelabel="hidelabel" v-model="modelValue"
3
- :label="label" :description="description" :pt="pt"
3
+ :label="label" :description="description" :pt="pt" :inputType="inputType"
4
4
  :setting="setting" :instancepath="instancepath" :error="error" #default="slotprops">
5
5
  <Checkbox v-if="inputType ==SimpleAppInputType.checkbox" :readonly="isReadonly" :pt="pt"
6
6
  :inputId="slotprops.uuid" :path="setting.instancepath"
@@ -93,6 +93,7 @@
93
93
  <Password
94
94
  v-else-if="inputType == SimpleAppInputType.password"
95
95
  :type="type" v-model="(modelValue as string)" :pt="pt"
96
+ @focus="setFocus"
96
97
  :readonly="isReadonly" class="flex flex-col"
97
98
  :inputId="slotprops.uuid" :path="setting.instancepath"
98
99
  :placeholder="placeholder"
@@ -117,6 +118,7 @@
117
118
  <!-- simple component -->
118
119
  <InputNumber v-else-if="inputType == SimpleAppInputType.number"
119
120
  :type="type" v-model="(modelValue as number)"
121
+ @focus="setFocus"
120
122
  :readonly="isReadonly"
121
123
  :pt="pt"
122
124
  :class="!pt ? 'w-full flex flex-col' :''"
@@ -125,7 +127,8 @@
125
127
  :placeholder="placeholder"
126
128
  />
127
129
  <Textarea v-else-if="inputType == SimpleAppInputType.textarea"
128
- v-model="(modelValue as string)"
130
+ v-model="(modelValue as string)"
131
+ :autofocus="autofocus"
129
132
  :readonly="isReadonly"
130
133
  :pt="pt"
131
134
  :type="type"
@@ -136,7 +139,9 @@
136
139
  v-bind="(componentProps as TextareaProps)"
137
140
  />
138
141
  <InputText v-else
139
- v-model="(modelValue as string)"
142
+ v-model="(modelValue as string)"
143
+ @focus="setFocus"
144
+ :autofocus="autofocus"
140
145
  :readonly="isReadonly"
141
146
  :pt="pt"
142
147
  :type="type"
@@ -172,7 +177,7 @@ import Slider,{ SliderProps } from 'primevue/slider';
172
177
  import Textarea, { TextareaProps } from 'primevue/textarea';
173
178
  import {SimpleAppInputType} from '~/types'
174
179
 
175
- const modelValue = defineModel()
180
+ const modelValue = defineModel({required:true})
176
181
  const datevalue = ref('')
177
182
  const timevalue = ref<Date>()
178
183
 
@@ -186,6 +191,7 @@ const props = withDefaults( defineProps<{
186
191
  instancepath?:string,
187
192
  hidelabel?: boolean
188
193
  readonly?: boolean
194
+ autofocus?:boolean
189
195
  pt?:any,
190
196
  placeholder?:string
191
197
  componentProps?: InputNumberProps | InputSwitchProps | InputTextProps | TextareaProps | DropdownProps | CalendarProps | RatingProps
@@ -221,6 +227,9 @@ const updateDate = (value:any)=>{
221
227
 
222
228
  }
223
229
 
230
+ const setFocus = (ev:any) => {
231
+ if(!isMobile()) ev.target.select()
232
+ }
224
233
 
225
234
  const getListOptions = () =>{
226
235
 
@@ -244,6 +253,7 @@ const getListOptions = () =>{
244
253
 
245
254
  const emits = defineEmits(['change','update:modelValue','update:docNoFormat'])
246
255
 
256
+
247
257
  watch(modelValue ,(newvalue:any)=>{
248
258
 
249
259
  if([SimpleAppInputType.date,SimpleAppInputType.calendar].includes(props.inputType)){
@@ -259,7 +269,16 @@ watch(modelValue ,(newvalue:any)=>{
259
269
  emits('change',modelValue.value)
260
270
  emits('update:modelValue',modelValue.value)
261
271
  })
262
-
272
+ onMounted(()=>{
273
+ if([SimpleAppInputType.date,SimpleAppInputType.calendar].includes(props.inputType)){
274
+ if(modelValue.value){
275
+ datevalue.value = moment(modelValue.value as string ).format('YYYY-MM-DD')
276
+ }else{
277
+ datevalue.value = ''
278
+ }
279
+
280
+ }
281
+ })
263
282
 
264
283
  /************ start autocomplete only ***************/
265
284
 
@@ -272,6 +291,4 @@ watch(modelValue ,(newvalue:any)=>{
272
291
  const triggerDocNoFormatChange=(formatdata:any)=>{
273
292
  emits('update:docNoFormat',formatdata)
274
293
  }
275
- </script>
276
- <style scoped>
277
- </style>
294
+ </script>
@@ -2,9 +2,9 @@
2
2
  <DataTable v-bind="$attrs" stripedRows resizableColumns
3
3
  class="simpleapp-datatable p-datatable-sm" :value="modelValue">
4
4
  <template #empty> <div class="text-center">No record found.</div> </template>
5
- <template #header >
6
- <div>
7
- <Button v-if="!setting.readonly" icon="pi pi-plus" @click="addNew()" class="simpleapp-datatable-add btn-primary" type="button">Add</Button>
5
+ <template #header v-if="!setting.readonly && !readonly">
6
+ <div >
7
+ <Button icon="pi pi-plus" @click="addNew()" class="simpleapp-datatable-add btn-primary" type="button">Add</Button>
8
8
  </div>
9
9
  </template>
10
10
  <slot>
@@ -35,6 +35,7 @@ const props = defineProps<{
35
35
  // columns:InputTableColumn[],
36
36
  setting:any,
37
37
  getField:Function,
38
+ readonly?:boolean
38
39
  }>()
39
40
 
40
41
 
@@ -22,7 +22,7 @@ import {camelCaseToWords} from './helper'
22
22
  import {computed,watch} from 'vue'
23
23
  import {ref} from 'vue'
24
24
  const modelValue = defineModel()
25
- const uuid = crypto.randomUUID()
25
+ const uuid = randomUUID()
26
26
  const fieldlabel = ref('')
27
27
  const fielddesc = ref('')
28
28
  const defaultcssclass='simpleapp-input-container'
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <!-- <ul role="list" class="divide-y divide-gray-100">
3
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">
4
+ <div class="flex justify-between gap-x-6 py-5 cursor-pointer" @click="emits('click',data)">
5
5
  <div class="flex min-w-0 gap-x-4">
6
6
  <img class="h-12 w-12 flex-none rounded-full bg-gray-50" :src="`${getAvatarLink(data.email,32)}`" alt="" />
7
7
  <div class="min-w-0 flex-auto">
@@ -38,7 +38,7 @@ import moment from 'moment'
38
38
  const props = defineProps<{
39
39
  data:any
40
40
  }>()
41
-
41
+ const emits = defineEmits(['click'])
42
42
 
43
43
 
44
44
  const datedifferent = computed(()=>{
@@ -0,0 +1,16 @@
1
+ import moment from "moment";
2
+
3
+ export const dateExists = (date:Date,listDate:Date[]) => {
4
+ const existsrecord = listDate.find(item=>{
5
+ return date.getTime()===item.getTime()
6
+ })
7
+ return existsrecord===undefined ? false :true
8
+ }
9
+ export const getMoment = (startTime:string)=> moment(startTime)
10
+ export const lastDateOfMonth = (datestr:string) => moment(datestr).endOf('month').format('YYYY-MM-DD');
11
+ export const today = () => moment().format('YYYY-MM-DD')
12
+ export const dateToString = (date:Date) => moment(date).format('YYYY-MM-DD')
13
+ export const dateToDateTimeString = (date:Date)=> moment(date).format('YYYY-MM-DD HH:mm:ss')
14
+ export const toLocalDate = (dateiso8601:string)=> new Date(String(dateiso8601)).toLocaleDateString()
15
+
16
+
@@ -30,3 +30,4 @@ export const getPathPara = (paraname:string,emptyvalue:string=''):string=>{
30
30
  }
31
31
  }
32
32
 
33
+ export const setCurrentUrl = (path:string)=>useRouter().push({path:path})
@@ -0,0 +1 @@
1
+ export const isMobile = () => window.innerWidth <= 640
@@ -1,12 +1,14 @@
1
1
  import _ from 'lodash'
2
2
  import {Md5} from 'ts-md5'
3
3
  import moment from "moment";
4
+ import { v4 as uuidv4 } from 'uuid';
5
+
4
6
  export const camelCaseToWords = (s: string) =>{
5
7
  const result = s.replace(/([A-Z])/g, ' $1');
6
8
  return result.charAt(0).toUpperCase() + result.slice(1);
7
9
  }
8
10
 
9
-
11
+ export const randomUUID = ()=> uuidv4()
10
12
  export const md5=(s:string)=> new Md5().appendStr(s).end()
11
13
 
12
14
  export const getAvatarLink = (email:string, size:number):string=>{
@@ -14,10 +16,5 @@ export const getAvatarLink = (email:string, size:number):string=>{
14
16
 
15
17
  }
16
18
 
17
- export const toLocalDate = (dateiso8601:string)=> new Date(String(dateiso8601)).toLocaleDateString()
18
19
  export const t = (txt:string,options?:any):string => !txt || txt.trim()=='' ? '' : useNuxtApp().$i18n.t(txt,options)
19
- export const today = () => moment().format('YYYY-MM-DD')
20
- export const dateToString = (date:Date) => moment(date).format('YYYY-MM-DD')
21
- export const getMoment = (startTime:string)=> moment(startTime)
22
- export const lastDateOfMonth = (datestr:string) => moment(datestr).endOf('month').format('YYYY-MM-DD');
23
20
  export const upperFirst = (str:string) => _.upperFirst(str)
@@ -1,15 +1,15 @@
1
1
  <template>
2
- <div class="flex items-center justify-center py-12 bg bg-gray-500">
3
- <div class="bg-white border rounded-md flex items-center justify-center mx-4 md:w-2/3">
2
+ <div class="w w-full items-center justify-center py-12 bg bg-gray-500">
3
+ <div class="bg-white dark:bg-gray-600 p-1 border rounded-md flex items-center justify-center mx-4 w-7/8 md:w-2/3">
4
4
  <div class="flex flex-col items-center py-16">
5
5
 
6
6
  <div class="flex flex-row">
7
- <div class="w w-40">
7
+ <div class="w w-full ">
8
8
  <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-13.59 -13.59 480.17 480.17" xml:space="preserve" fill="#000000" stroke="#000000" stroke-width="0.00452986"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <g> <path style="fill:#010002;" d="M0,0v452.986h452.986V0H0z M403.223,24.655c8.132,0,14.668,6.558,14.668,14.625 c0,8.111-6.536,14.711-14.668,14.711c-8.089,0-14.668-6.601-14.668-14.711C388.576,31.234,395.134,24.655,403.223,24.655z M352.035,24.655c8.046,0,14.647,6.558,14.647,14.625c0,8.111-6.601,14.711-14.647,14.711c-8.132,0-14.668-6.601-14.668-14.711 C337.389,31.234,343.903,24.655,352.035,24.655z M417.955,418.624H35.053V85.701h382.903V418.624z"></path> <path style="fill:#010002;" d="M226.493,398.952c80.394,0,145.495-65.101,145.495-145.43s-65.101-145.495-145.495-145.495 c-80.373,0-145.516,65.165-145.516,145.495C80.977,333.873,146.12,398.952,226.493,398.952z M142.044,198.516l29.444-29.444 l55.005,55.027l54.984-55.027l29.379,29.444L255.894,253.5l54.984,54.941l-29.423,29.444l-54.962-54.962l-55.005,54.984 l-29.444-29.444l54.984-54.941L142.044,198.516z"></path> </g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> </g> </g></svg>
9
9
  </div>
10
10
  <div>
11
11
  <h1 class="px-4 pt-2 pb-4 text-left text-5xl font-bold leading-10 text-gray-800">OOPS!</h1>
12
- <p class="px-4 mt mb-4 text-4xl text-left font font-bold">{{error?.statusCode}} Error</p>
12
+ <p class="px-4 mt mb-4 text-4xl text-left font font-bold">{{isNaN(error?.statusCode) ? t('server'): error?.statusCode}} Error</p>
13
13
  <p class="px-4 pb-10 text-base leading-none text-left text-red-400">{{t(error?.statusMessage)}}</p>
14
14
  <p> <Button @click="handleError" class="btn-primary">{{ t('backToHome') }}</Button></p>
15
15
  </div>
@@ -1,10 +1,34 @@
1
- <script lang="ts" setup>
2
- // import Menus from '~/components/Menus.vue'
3
- </script>
4
1
  <template>
5
- <div>
6
- <HeaderBar />
7
- <UserInvitation/>
8
- <slot></slot>
2
+ <div class="h-full flex flex-row">
3
+ <div class="flex flex-col justify justify-between">
4
+ <div >
5
+ <HeaderButtonMenuPicker class="cursor-pointer p-2 text-6xl "></HeaderButtonMenuPicker>
6
+ <div class="" v-for="item in menus">
7
+ <div class="">
8
+ <NuxtLink
9
+ :class="`pi ${item.iconClass} p-2 text-6xl cursor-pointer`"
10
+ :to="getDocumentUrl(item.path)"
11
+ ></NuxtLink>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ <HeaderButtonProfile class="p-6"/>
16
+ </div>
17
+ <div class="flex-1">
18
+ <HeaderBar />
19
+ <UserInvitation/>
20
+ <slot></slot>
21
+ </div>
9
22
  </div>
10
- </template>
23
+
24
+ </template>
25
+ <script setup lang="ts">
26
+ const menus=[
27
+ // {iconClass:'pi-bars',path:'managestudents/profile'},
28
+ {iconClass:'pi-home text-white',path:''},
29
+ {iconClass:'pi-users text-white',path:'managestudents/profile'},
30
+ {iconClass:'pi-calendar text-white',path:`manageclasses`},
31
+ // {iconClass:'pi-database',path:'managedata'},
32
+ {iconClass:'pi-chart-pie text-white',path:'reports'},
33
+ ]
34
+ </script>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <slot v-if="useRoute().path=='/login'"></slot>
3
+ </template>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <div class="h-screen flex flex-col">
3
+ <div class="flex flex-col grow">
4
+ <slot></slot>
5
+ </div>
6
+ <!-- fixed -->
7
+ <div v-if="getCurrentXorg()" class="flex h-20 border-t-2 dark:border-t-gray-700 text-4xl flex-row left-0 w-full justify justify-between bottom-0 z-50 bg-white dark:bg-gray-600 pl-2 pr-2" >
8
+ <NuxtLink v-for="item in menus"
9
+ :class="`pi ${item.iconClass} pb-6 pt-6 cursor-pointer inline-block align-middle`"
10
+ :to="getDocumentUrl(item.path)"
11
+ ></NuxtLink>
12
+ <HeaderButtonMenuPicker class=" cursor-pointer"></HeaderButtonMenuPicker>
13
+ <HeaderButtonProfile class=""/>
14
+ <UserInvitation/>
15
+ </div>
16
+ <!-- <HeaderBar class="border flex flex-row h-10 fixed left-0 w-full justify justify-between top-0 z-50 bg-white dark:bg-gray-800"/> -->
17
+
18
+ </div>
19
+ </template>
20
+ <script setup lang="ts">
21
+ const menus=[
22
+ // {iconClass:'pi-bars',path:'managestudents/profile'},
23
+ {iconClass:'pi-home text-white',path:''},
24
+ // {iconClass:'pi-users text-white',path:'managestudents/profile'},
25
+ // {iconClass:'pi-calendar text-white',path:`manageclasses`},
26
+ // {iconClass:'pi-database',path:'managedata'},
27
+ // {iconClass:'pi-chart-pie text-white',path:'reports'},
28
+ ]
29
+ </script>
@@ -6,7 +6,11 @@
6
6
  */
7
7
  import path from 'path'
8
8
  export default defineNuxtConfig({
9
- // colorMode: {} ,
9
+ colorMode: {
10
+ classSuffix: ''
11
+
12
+ },
13
+
10
14
  runtimeConfig:{
11
15
  public:{
12
16
  APP_URL: process.env.APP_URL,
@@ -26,13 +30,19 @@ export default defineNuxtConfig({
26
30
  tailwindcss: {
27
31
  // Options
28
32
  },
33
+ devServer: {
34
+ host: "0.0.0.0",
35
+ },
29
36
  modules: [
30
37
  // "@hebilicious/authjs-nuxt",
38
+ '@nuxtjs/color-mode',
39
+ '@nuxtjs/device',
31
40
  '@nuxtjs/i18n',
32
41
  '@sidebase/nuxt-auth',
33
42
  'nuxt-primevue',
43
+ // '@nuxtjs/pwa', //cannot turn on, will cause nuxt cant start
34
44
  // "nuxt-security", //temporary avoid nuxt-security cause cors
35
- '@vueuse/nuxt',
45
+ '@vueuse/nuxt',
36
46
  '@nuxtjs/tailwindcss',
37
47
  ['@pinia/nuxt',{
38
48
  autoImports: [
@@ -41,10 +51,13 @@ tailwindcss: {
41
51
  ['defineStore', 'definePiniaStore'], // import { defineStore as definePiniaStore } from 'pinia'
42
52
  ],
43
53
  }],
44
- '@nuxtjs/color-mode',
54
+
45
55
 
46
56
 
47
- ],
57
+ ],
58
+ device: {
59
+ refreshOnResize: true
60
+ },
48
61
  i18n: {
49
62
  lazy: true,
50
63
  langDir: "lang/",
@@ -67,13 +80,14 @@ tailwindcss: {
67
80
  iso: "cn",
68
81
  name: "Chinese",
69
82
  file: "cn.ts",
83
+
70
84
  },
71
85
  ],
72
86
  defaultLocale: "df",
73
87
  },
74
88
  primevue: {
75
89
  options: {
76
- unstyled: true,
90
+ //unstyled: true,
77
91
  ripple: true,
78
92
  inputStyle: 'filled'
79
93
  },
@@ -82,7 +96,7 @@ tailwindcss: {
82
96
  exclude: ['chart']
83
97
  },
84
98
  directives: {
85
- include: ['Ripple', 'Tooltip','BadgeDirective']
99
+ include: ['Ripple', 'Tooltip','BadgeDirective','FocusTrap']
86
100
  },
87
101
  cssLayerOrder: 'tailwind-base, primevue, tailwind-utilities',
88
102
  importPT: { as: 'SimpleAppPT', from: path.resolve(__dirname,'./assets/primevue/passthrough.ts') },
@@ -93,7 +107,7 @@ tailwindcss: {
93
107
 
94
108
  // },
95
109
  auth: {
96
- globalAppMiddleware: true
110
+ globalAppMiddleware: false
97
111
  },
98
112
  // security: {
99
113
  // corsHandler:{
@@ -122,14 +136,14 @@ tailwindcss: {
122
136
  // ],
123
137
  css: [
124
138
  'primeicons/primeicons.css',
125
- path.resolve(__dirname,'./assets/css/style.css')
126
- ],
139
+ path.resolve(__dirname,'./assets/css/style.css'),
140
+ path.resolve(__dirname,'./assets/css/calendar.css'),
141
+ ],
142
+ },
127
143
 
128
144
  // devtools: { enabled: true },
129
145
  // build: {
130
146
  // // transpile: ["primevue"]
131
- // },
132
-
133
-
147
+ // },
134
148
 
135
- })
149
+ )
@@ -1,18 +1,20 @@
1
- <script lang="ts" setup>
2
- /**
3
- * This file was automatically generated by simpleapp generator.
4
- * YOU ALLOWED TO CHANGE THIS FILE, IT WONT OVERRIDE BY GENERATOR
5
- * last change 2023-10-28
6
- * Author: Ks Tan
7
- */
8
- </script>
9
1
  <template>
10
2
  <div class="frontpage-container">
11
3
  <client-only>
12
- <title>{{ getUserProfile().branchName }}</title>
4
+ <title>{{ getUserProfile()?.branchName }}</title>
13
5
  </client-only>
14
6
  <h1 class="border text-3xl text-center m-20 p-20">
15
7
  {{ t("createYourContentHere") }}
16
8
  </h1>
17
9
  </div>
18
10
  </template>
11
+ <script lang="ts" setup>
12
+ /**
13
+ * This file was automatically generated by simpleapp generator.
14
+ * YOU ALLOWED TO CHANGE THIS FILE, IT WONT OVERRIDE BY GENERATOR
15
+ * last change 2023-10-28
16
+ * Author: Ks Tan
17
+ */
18
+
19
+ useNuxtApp().$event('SetTitle',t('home'))
20
+ </script>
@@ -114,6 +114,11 @@ getCurrentOrg();
114
114
  v-model="data.timeZone"
115
115
  :setting="o.getField('#/properties/timeZone')"
116
116
  />
117
+ <SimpleAppInput
118
+ :input-type="SimpleAppInputType.text"
119
+ v-model="data.currency"
120
+ :setting="o.getField('#/properties/currency')"
121
+ />
117
122
  </div>
118
123
  <div>
119
124
  <SimpleAppInput
@@ -22,21 +22,17 @@
22
22
  />
23
23
 
24
24
  <SimpleAppInput
25
- :input-type="SimpleAppInputType.checkbox"
25
+ :input-type="SimpleAppInputType.checkbox"
26
26
  :setting="o.getField('#/properties/active')"
27
27
  v-model="userdata.active"
28
28
  />
29
29
  <SimpleAppInput
30
- :input-type="SimpleAppInputType.textarea"
30
+ :input-type="SimpleAppInputType.textarea"
31
31
  :setting="o.getField('#/properties/description')"
32
32
  v-model="userdata.description"
33
33
  />
34
34
  <div>
35
- <Button
36
- @click="saveUser"
37
- class="btn btn-primary"
38
- >Save</Button
39
- >
35
+ <Button @click="saveUser" class="btn btn-primary">Save</Button>
40
36
  <Button
41
37
  v-if="canPerform('user', 'delete')"
42
38
  @click="deleteUser"
@@ -103,7 +99,7 @@
103
99
  </template>
104
100
  <script setup lang="ts">
105
101
  // import Card from "primevue/card";
106
- import {SimpleAppInputType} from "~/types"
102
+ import { SimpleAppInputType } from "~/types";
107
103
  import { Permission, User } from "../../../simpleapp/generate/openapi/api";
108
104
  import _ from "lodash";
109
105
  import SelectButton from "primevue/selectbutton";
@@ -294,9 +290,11 @@ const getPermssionData = (userId: string, branchId: number) => {
294
290
  return pm;
295
291
  };
296
292
 
297
- onMounted(() => {
298
- const id = String(useRoute().params.id);
299
- console.log("id", id);
300
- onSelectUser(id);
293
+ onMounted(async () => {
294
+ const id = getPathPara('id')
295
+ if(id){
296
+ await onSelectUser(id);
297
+ }
298
+
301
299
  });
302
300
  </script>
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <div class="p-10 m-10 text-3xl border text-center dark:text-white">
3
+ {{ t('redirectToLoginPage') }}
4
+ <!-- <NuxtPage /> -->
5
+ </div>
6
+ </template>
7
+ <script setup lang="ts">
8
+ /**
9
+ * This file was automatically generated by simpleapp generator. Every
10
+ * MODIFICATION OVERRIDE BY GENERATEOR
11
+ * last change 2024-02-13
12
+ * Author: Ks Tan
13
+ */
14
+
15
+ definePageMeta({
16
+ name: "Login",
17
+ auth: false,
18
+ layout: false
19
+ });
20
+
21
+ const route = useRoute();
22
+ const { signIn } = useAuth();
23
+ const callbackUrl = ref("");
24
+ onMounted(async () => {
25
+ if (route.query.callbackUrl) {
26
+ callbackUrl.value = <string>route.query.callbackUrl;
27
+ } else {
28
+ callbackUrl.value = "/";
29
+ }
30
+ callbackUrl.value = decodeURIComponent(callbackUrl.value);
31
+ // console.log("callbackUrlcallbackUrlcallbackUrl", callbackUrl.value);
32
+ await signIn("keycloak", { callbackUrl: callbackUrl.value });
33
+ });
34
+ </script>