@simitgroup/simpleapp-generator 1.2.0 → 1.2.2

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 (26) hide show
  1. package/dist/framework.js +1 -1
  2. package/package.json +1 -1
  3. package/templates/basic/nest/service.ts.eta +4 -42
  4. package/templates/basic/nest/type.ts.eta +7 -0
  5. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +56 -33
  6. package/templates/nest/src/simpleapp/generate/types/index.ts.eta +5 -57
  7. package/templates/nest/src/simpleapp/generate/types/simpleapp.type.ts.eta +76 -0
  8. package/templates/nest/src/simpleapp/services/autoinc.service.ts.eta +3 -35
  9. package/templates/nest/src/simpleapp/services/branch.service.ts.eta +19 -43
  10. package/templates/nest/src/simpleapp/services/docno.service.ts.eta +3 -36
  11. package/templates/nest/src/simpleapp/services/org.service.ts.eta +8 -36
  12. package/templates/nest/src/simpleapp/services/perm.service.ts.eta +3 -46
  13. package/templates/nest/src/simpleapp/services/tenant.service.ts.eta +9 -39
  14. package/templates/nuxt/components/list/ListView.vue.eta +7 -7
  15. package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +11 -1
  16. package/templates/nuxt/composables/getOpenApi.generate.ts.eta +9 -48
  17. package/templates/nuxt/nuxt.config.ts._eta +1 -1
  18. package/templates/nuxt/pages/profile.vue.eta +8 -9
  19. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +27 -8
  20. package/templates/nuxt/server/api/[xorg]/[...].ts.eta +1 -1
  21. package/templates/nuxt/server/api/profile/[...].ts.eta +1 -1
  22. package/templates/nuxt/server/api/profile/index.ts.eta +1 -1
  23. package/templates/nuxt/types/user.ts.eta +34 -1
  24. package/templates/project/lang/default._json +12 -1
  25. package/tsconfig.tsbuildinfo +1 -1
  26. package/templates/nest/src/simpleapp/generate/types/apievent.type.ts.eta +0 -22
@@ -8,14 +8,17 @@ import { InjectModel } from '@nestjs/mongoose';
8
8
  import { Model } from 'mongoose';
9
9
  import { Injectable } from '@nestjs/common';
10
10
  import { OrganizationProcessor } from '../generate/processors/org.processor';
11
- import { Organization } from '../generate/types/org.type';
12
- export { Organization } from '../generate/types/org.type';
11
+ import { Organization,OrganizationHooks } from '../generate/types';
12
+ export { Organization } from '../generate/types';
13
13
  import { AutoincreamentService } from './autoinc.service';
14
14
  import { UserContext } from '../generate/commons/user.context';
15
15
 
16
16
  @Injectable()
17
17
  export class OrganizationService extends OrganizationProcessor {
18
18
  protected strictIsolation = false;
19
+ protected hooks : OrganizationHooks = {
20
+ beforeCreate: async (appuser: UserContext, data: Organization) => await this.orgBeforeCreate(appuser,data),
21
+ };
19
22
  constructor(
20
23
  @InjectModel('Organization') mydoc: Model<Organization>,
21
24
  private increament: AutoincreamentService,
@@ -23,43 +26,12 @@ export class OrganizationService extends OrganizationProcessor {
23
26
  super(mydoc);
24
27
  }
25
28
 
26
- hook = async (appuser: UserContext, type: string, data?: any) => {
27
- switch (type) {
28
- // case 'init':
29
- // break;
30
- // case 'beforeSearch':
31
- // break;
32
- // case 'afterSearch':
33
- // break;
34
- // case 'beforeValidation':
35
- // break;
36
- // case 'afterValidation':
37
- // break;
38
- case 'beforeCreate':
39
- const searchresult = await this.increament.runGenerateNextNo(
29
+ async orgBeforeCreate(appuser:UserContext,data:Organization){
30
+ const searchresult = await this.increament.runGenerateNextNo(
40
31
  appuser,
41
32
  'organization',
42
33
  'orgId',
43
34
  );
44
35
  data.orgId = searchresult.nextno;
45
- break;
46
- // case 'afterCreate':
47
- // break;
48
- // case 'beforeUpdate':
49
- // break;
50
- // case 'afterUpdate':
51
- // break;
52
- // case 'beforeDelete':
53
- // break;
54
- // case 'afterDelete':
55
- // break;
56
- // case 'beforeFetchRecord':
57
- // break;
58
- // case 'afterFetchRecord':
59
- // break;
60
- // default:
61
- // break;
62
- }
63
- return true;
64
- };
36
+ }
65
37
  }
@@ -8,63 +8,20 @@ import { InjectModel } from '@nestjs/mongoose';
8
8
  import { Model, PipelineStage } from 'mongoose';
9
9
  import { Injectable } from '@nestjs/common';
10
10
  import { PermissionProcessor } from '../generate/processors/perm.processor';
11
- import { Permission } from '../generate/types/perm.type';
11
+ import { Permission,PermissionHooks } from '../generate/types';
12
12
  import { UserContext } from '../generate/commons/user.context';
13
-
14
- export { Permission } from '../generate/types/perm.type';
13
+ export { Permission } from '../generate/types';
15
14
 
16
15
  @Injectable()
17
16
  export class PermissionService extends PermissionProcessor {
18
17
  protected strictIsolation = false;
18
+ protected hooks : PermissionHooks = {};
19
19
  constructor(
20
20
  @InjectModel('Permission') mydoc: Model<Permission>,
21
21
  ) {
22
22
  super(mydoc);
23
23
  }
24
24
 
25
- hook = async (appuser: UserContext, type: string, data?: any) => {
26
- switch (
27
- type
28
- // case 'init':
29
- // break;
30
- // case 'beforeSearch':
31
- // break;
32
- // case 'afterSearch':
33
- // break;
34
- // case 'beforeValidation':
35
- // break;
36
- // case 'afterValidation':
37
- // break;
38
- // case 'beforeCreate':
39
- // break;
40
- // case 'afterCreate':
41
- // break;
42
- // case 'beforeUpdate':
43
- // break;
44
- // case 'afterUpdate':
45
- // break;
46
- // case 'beforeDelete':
47
- // break;
48
- // case 'afterDelete':
49
- // case 'beforeDeleteMany':
50
- // this.logger.log(data, 'beforeDeleteMany');
51
- // this.deleteMany(appuser,data)
52
- // break;
53
- // case 'afterDeleteMany':
54
- // this.logger.log(data, 'afterDeleteMany', data);
55
- // break;
56
-
57
- // break;
58
- // case 'beforeFetchRecord':
59
- // break;
60
- // case 'afterFetchRecord':
61
- // break;
62
- // default:
63
- // break;
64
- ) {
65
- }
66
- return true;
67
- };
68
25
 
69
26
  async runListUser(appuser: UserContext) {
70
27
  const getallrecords: PipelineStage = { $match: {} };
@@ -9,13 +9,16 @@ import { InjectModel } from '@nestjs/mongoose';
9
9
  import { Model } from 'mongoose';
10
10
  import { Injectable } from '@nestjs/common';
11
11
  import { TenantProcessor } from '../generate/processors/tenant.processor';
12
- import { Tenant } from '../generate/types/tenant.type';
12
+ import { Tenant,TenantHooks } from '../generate/types';
13
13
  import { AutoincreamentService } from './autoinc.service';
14
14
  import { UserContext } from '../generate/commons/user.context';
15
- export { Tenant } from '../generate/types/tenant.type';
15
+ export { Tenant } from '../generate/types';
16
16
 
17
17
  @Injectable()
18
18
  export class TenantService extends TenantProcessor {
19
+ protected hooks : TenantHooks = {
20
+ beforeCreate: async (appuser: UserContext, data: Tenant) => await this.tenantBeforeCreate(appuser,data),
21
+ };
19
22
  constructor(
20
23
  @InjectModel('Tenant') mydoc: Model<Tenant>,
21
24
  private increament: AutoincreamentService,
@@ -24,45 +27,12 @@ export class TenantService extends TenantProcessor {
24
27
  super(mydoc);
25
28
  }
26
29
 
27
- hook = async (appuser: UserContext, type: string, data?: any) => {
28
- switch (type) {
29
- // case 'init':
30
- // break;
31
- // case 'beforeSearch':
32
- // break;
33
- // case 'afterSearch':
34
- // break;
35
- // case 'beforeValidation':
36
- // break;
37
- // case 'afterValidation':
38
- // break;
39
- case 'beforeCreate':
40
- const searchresult = await this.increament.runGenerateNextNo(
30
+ async tenantBeforeCreate(appuser:UserContext,data:Tenant){
31
+ const searchresult = await this.increament.runGenerateNextNo(
41
32
  appuser,
42
33
  'tenant',
43
34
  'tenantId',
44
35
  );
45
- data.tenantId = searchresult.nextno;
46
- data.uuid = crypto.randomUUID()
47
- break;
48
- // case 'afterCreate':
49
- // console.log('this.data',data)
50
- // break;
51
- // case 'beforeUpdate':
52
- // break;
53
- // case 'afterUpdate':
54
- // break;
55
- // case 'beforeDelete':
56
- // break;
57
- // case 'afterDelete':
58
- // break;
59
- // case 'beforeFetchRecord':
60
- // break;
61
- // case 'afterFetchRecord':
62
- // break;
63
- // default:
64
- // break;
65
- }
66
- return true;
67
- };
36
+ data.tenantId = searchresult.nextno;
37
+ }
68
38
  }
@@ -14,8 +14,8 @@
14
14
  <div :class="getSelectedCSS(item)">
15
15
  <NuxtLink :to="url ? `${url}/${item[idField]}`:undefined">
16
16
  <slot :item="item" :index="index">
17
- <div class="mr-2">{{item[titleField] }}</div>
18
- <div class="font font-bold text-right">{{item[subTitleField]}}</div>
17
+ <div class="mr-2">{{item[titleField??''] }}</div>
18
+ <div class="font font-bold text-right">{{item[subTitleField??'']}}</div>
19
19
  </slot>
20
20
  </NuxtLink>
21
21
  </div>
@@ -25,11 +25,11 @@
25
25
  </div>
26
26
  </div>
27
27
  </template>
28
- <script setup lang="ts">
28
+ <script setup lang="ts" generic="T extends {[key:string]:any}">
29
29
  import {ref} from 'vue'
30
30
  import {ListItem} from '~/types/listview'
31
31
  const props = withDefaults(defineProps<{
32
- list:any[],
32
+ list:T[],
33
33
  url?:string,
34
34
  titleField?:string
35
35
  idField?:string
@@ -48,13 +48,13 @@ const clickRow=(item:ListItem)=>{
48
48
  const filterlist = computed(()=>{
49
49
  const newlist =props.list.filter((item:any)=>
50
50
  {
51
- return String(item[props.titleField]).toLowerCase().includes(searchvalue.value.toLowerCase()) ||
52
- String(item[props.subTitleField]).toLowerCase().includes(searchvalue.value.toLowerCase())
51
+ return String(item[props.titleField??'']).toLowerCase().includes(searchvalue.value.toLowerCase()) ||
52
+ String(item[props.subTitleField??'']).toLowerCase().includes(searchvalue.value.toLowerCase())
53
53
  })
54
54
 
55
55
  return newlist
56
56
  })
57
- const getSelectedCSS= (item:ListItem)=>{
57
+ const getSelectedCSS= (item:T)=>{
58
58
  if(selecteditem.value == item.code){
59
59
  return "p-2 border bg-sky-200"
60
60
  }else{
@@ -120,7 +120,17 @@
120
120
  v-bind="(componentProps as InputNumber)"
121
121
  :placeholder="placeholder"
122
122
  />
123
-
123
+ <Textarea v-else-if="inputType == SimpleAppInputType.textarea"
124
+ v-model="(modelValue as string)"
125
+ :readonly="isReadonly"
126
+ :pt="pt"
127
+ :type="type"
128
+ class="w-full flex flex-col"
129
+ :inputId="slotprops.uuid"
130
+ :path="setting.instancepath"
131
+ :placeholder="placeholder"
132
+ v-bind="(componentProps as TextareaProps)"
133
+ />
124
134
  <InputText v-else
125
135
  v-model="(modelValue as string)"
126
136
  :readonly="isReadonly"
@@ -10,12 +10,15 @@ import axios from 'axios'
10
10
 
11
11
 
12
12
  const getAxiosConfig = () => {
13
+ const suffix = getCurrentXorg() ? '/'+getCurrentXorg() : ''
13
14
  const config: o.Configuration = {
14
- basePath: `${useRuntimeConfig().public.APP_URL}/api/${getCurrentXorg()}`,
15
+ basePath: `${useRuntimeConfig().public.APP_URL}/api${suffix}`,
15
16
  isJsonMime: () => true,
16
17
  };
17
18
  return config
18
19
  }
20
+
21
+
19
22
  export const getApiSession = async ()=> {
20
23
  const res = await (new o.PROFILEApi(getAxiosConfig(),undefined,useNuxtApp().$axios)).getSession()
21
24
  return res
@@ -28,54 +31,12 @@ export const getDocumentApi = (documentName: string): any => {
28
31
 
29
32
  const config = getAxiosConfig()
30
33
  const docsOpenapi: any = {
31
- 'tenant': new o.TENANTApi(config),
32
-
33
- 'organization': new o.ORGApi(config),
34
-
35
- 'branch': new o.BRANCHApi(config),
36
-
37
- 'permission': new o.PERMApi(config),
38
-
39
- 'autoincreament': new o.AUTOINCApi(config),
40
-
41
- 'docnoformat': new o.DOCNOApi(config),
42
-
43
- 'category': new o.CATApi(config),
44
-
45
- 'customer': new o.CUSTApi(config),
46
-
47
- 'enrollment': new o.ENROLLApi(config),
48
-
49
- 'invoice': new o.INVApi(config),
50
-
51
- 'level': new o.LVLApi(config),
52
-
53
- 'payment': new o.PAYApi(config),
54
-
55
- 'paymentmethod': new o.PAYMETHODApi(config),
56
-
57
- 'period': new o.PERIODApi(config),
58
-
59
- 'product': new o.PRDApi(config),
60
-
61
- 'room': new o.ROOMApi(config),
62
-
63
- 'schedule': new o.SCHEDULEApi(config),
64
-
65
- 'school': new o.SCHOOLApi(config),
66
-
67
- 'student': new o.STUApi(config),
68
-
69
- 'studentgroup': new o.STUGROUPApi(config),
70
-
71
- 'teacher': new o.TEACHERApi(config),
72
-
73
- 'tuitionclass': new o.TUITIONApi(config),
74
-
75
- 'user': new o.USERApi(config),
76
-
77
-
34
+ <%for(let i=0; i<it.modules.length;i++){ %>
35
+ <% const d = it.modules[i] %>
36
+ '<%= d['docname'].toLowerCase() %>': new o.<%= d['doctype'].toUpperCase() %>Api(config),
37
+ <%}%>
78
38
  };
39
+
79
40
  if (!docsOpenapi[documentName]) {
80
41
  console.error(
81
42
  `api for '${documentName}' does not exists, most probably define wrong x-foreignkey`,
@@ -115,7 +115,7 @@ tailwindcss: {
115
115
  // },
116
116
  //csrf: true, // been force to off csrf cash it crash with nuxt-auth
117
117
  // },
118
- // ssr: false,
118
+ ssr: false,
119
119
  // content: [
120
120
  // "./index.html",
121
121
  // "./src/**/*.{vue,js,ts,jsx,tsx}",
@@ -6,7 +6,7 @@
6
6
  <h3
7
7
  class="text-base font-semibold leading-7 text-gray-900 dark:text-gray-400"
8
8
  >
9
- {{t('userinfo')}}
9
+ {{ t("userinfo") }}
10
10
  </h3>
11
11
  </div>
12
12
  <div class="mt-6 border-t border-gray-100">
@@ -15,7 +15,7 @@
15
15
  <dt
16
16
  class="text-sm font-medium leading-6 text-gray-900 dark:text-gray-400"
17
17
  >
18
- Full name
18
+ {{ t("fullName") }}
19
19
  </dt>
20
20
  <dd
21
21
  class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300"
@@ -27,7 +27,7 @@
27
27
  <dt
28
28
  class="text-sm font-medium leading-6 text-gray-900 dark:text-gray-400"
29
29
  >
30
- Group
30
+ {{ t("group") }}
31
31
  </dt>
32
32
  <dd
33
33
  class="mt-1 text-sm leading-6 text-gray-700 dark:text-gray-300 sm:col-span-2 sm:mt-0"
@@ -39,7 +39,7 @@
39
39
  <dt
40
40
  class="text-sm font-medium leading-6 text-gray-900 dark:text-gray-400"
41
41
  >
42
- Email address
42
+ {{ t("email") }}
43
43
  </dt>
44
44
  <dd
45
45
  class="mt-1 text-sm leading-6 text-gray-700 dark:text-gray-300 sm:col-span-2 sm:mt-0"
@@ -52,7 +52,7 @@
52
52
  <dt
53
53
  class="text-sm font-medium leading-6 text-gray-900 dark:text-gray-400"
54
54
  >
55
- Branch Access
55
+ {{t('branches')}}
56
56
  </dt>
57
57
  <dd class="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
58
58
  <ul
@@ -96,8 +96,8 @@
96
96
  <dt
97
97
  class="text-sm font-medium leading-6 text-gray-900 dark:text-gray-400"
98
98
  >
99
- Current Branch Access Rights
100
- <p class="text-danger-600">only appear in debug mode</p>
99
+ {{t('accessRights')}}
100
+ <p class="text-danger-600">{{ t("onlyAppearInDebugMode") }}</p>
101
101
  <p class="text-danger-600">{{ getUserProfile().sessionId }}</p>
102
102
  </dt>
103
103
  <dd
@@ -110,5 +110,4 @@
110
110
  </div>
111
111
  </div>
112
112
  </template>
113
- <script setup lang="ts">
114
- </script>
113
+ <script setup lang="ts"></script>
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { defineNuxtPlugin } from "#app";
8
8
  import {PROFILEApi} from '../simpleapp/generate/openapi'
9
+ import {UserProfile} from '~/types'
9
10
  import axios, { Axios, AxiosResponse } from 'axios'
10
11
  import _ from 'lodash'
11
12
 
@@ -92,15 +93,15 @@ export default defineNuxtPlugin( async(nuxtApp) => {
92
93
  })
93
94
  },
94
95
  getCurrentXorg(){
95
- return (useRoute().params.xorg) ? String(useRoute().params.xorg) : undefined
96
+ return (useRoute().params.xorg) ? String(useRoute().params.xorg) : undefined
96
97
  },
97
98
  async pingSession(){
98
- let xorg = this.getCurrentXorg()
99
+ let xorg = this.getCurrentXorg()
99
100
  let apiurl=''
100
- if(xorg===undefined){
101
+ if(!xorg){
101
102
  apiurl = `${useRuntimeConfig().public.APP_URL}/api`
102
103
  }else{
103
- apiurl = `${useRuntimeConfig().public.APP_URL}/api/${xorg}`
104
+ apiurl = `${useRuntimeConfig().public.APP_URL}/api/${xorg}`
104
105
  }
105
106
  const {$axios} = useNuxtApp()
106
107
  return await new PROFILEApi(undefined,apiurl,$axios).getSession()
@@ -151,8 +152,18 @@ export default defineNuxtPlugin( async(nuxtApp) => {
151
152
  }
152
153
  return false
153
154
  },
155
+ async logout (redirecturl:string){
156
+ const redirectdata = encodeURIComponent(redirecturl)
157
+ const { signOut } = useAuth();
158
+ const { data } = await <any>useFetch('/api/auth/logout');
159
+ // remove session
160
+ await signOut({redirect:false});
161
+ let addPath = encodeURIComponent(`/login?callbackUrl=${redirectdata}`);
162
+ const tourl= `${data.value.path}${addPath}`
163
+ navigateTo(tourl,{external:true})
164
+ },
154
165
  getUserInfo(){
155
- return {
166
+ const userinfo:UserProfile = {
156
167
  _id : this._id,
157
168
  sessionId : this.sessionId,
158
169
  tenantId : this.tenantId,
@@ -174,22 +185,30 @@ export default defineNuxtPlugin( async(nuxtApp) => {
174
185
  time:this.time,
175
186
  moreProps: this.moreProps
176
187
 
177
-
178
-
179
188
  }
189
+ return userinfo
180
190
  }
181
191
  }
182
192
  })
183
193
  console.log("after define user store")
184
194
 
185
195
  if( useRoute().meta.auth !==false){
196
+
186
197
  if(await useUserStore().pingSession()){
187
198
  console.log("ping session ok")
188
199
  await useUserStore().loadRemoteUserInfo()
200
+ console.log("load remote user info ok")
201
+
189
202
  }else{
190
203
  console.log("No login session", useRoute().path)
191
- await logout(useRoute().path)
204
+ await useUserStore().logout(useRoute().path)
192
205
  }
206
+ }else{
207
+ // if(await useUserStore().pingSession()){
208
+
209
+ // }else{
210
+
211
+ // }
193
212
  }
194
213
 
195
214
  return {
@@ -10,7 +10,7 @@ import axios from 'axios';
10
10
  import { getServerSession } from '#auth'
11
11
  import type { Session } from 'next-auth';
12
12
 
13
- export default defineEventHandler(async (event) => {
13
+ export default defineEventHandler(async (event:any) => {
14
14
  type additionalprops = {accessToken?:string}
15
15
  let session:any=null
16
16
 
@@ -10,7 +10,7 @@ import axios from 'axios';
10
10
  import { getServerSession } from '#auth'
11
11
  import type { Session } from 'next-auth';
12
12
 
13
- export default defineEventHandler(async (event) => {
13
+ export default defineEventHandler(async (event:any) => {
14
14
  type additionalprops = {accessToken?:string}
15
15
  let session:any=null
16
16
  // console.log("profile api-------------------------")
@@ -9,7 +9,7 @@ import axios from 'axios';
9
9
  import { getServerSession } from '#auth'
10
10
  import type { Session } from 'next-auth';
11
11
 
12
- export default defineEventHandler(async (event) => {
12
+ export default defineEventHandler(async (event:any) => {
13
13
  type additionalprops = {accessToken?:string}
14
14
  let session:any=null
15
15
  // console.log("profile api-------------------------")
@@ -41,4 +41,37 @@ export type UserListItem = {
41
41
  }
42
42
 
43
43
 
44
-
44
+ export type UserProfile = {
45
+ _id : string
46
+ sessionId : string
47
+ tenantId : number
48
+ orgId : number
49
+ branchId : number
50
+ orgRecordId: string
51
+ branchRecordId: string
52
+ uid : string
53
+ email : string
54
+ branchCode: string
55
+ branchName: string
56
+ orgCode: string
57
+ orgName: string
58
+ fullName : string
59
+ branches: {
60
+ _id: string
61
+ branch: any
62
+ group: string
63
+ xOrg: string
64
+ }[]
65
+ invites: {
66
+ _id: string;
67
+ email: string;
68
+ fullName: string;
69
+ tenantId: string;
70
+ tenantName: string;
71
+ created: string;
72
+ }[]
73
+ roles: string[]
74
+ group: string
75
+ time: string
76
+ moreProps: any
77
+ }
@@ -34,5 +34,16 @@
34
34
  "simpleApproveMessage": "Approve or reject",
35
35
  "suspendcustomer": "Suspend Customer",
36
36
  "formKeyNotFound": "Formkey not found \"{formKey}\"",
37
- "selectAll": "Select All"
37
+ "selectAll": "Select All",
38
+
39
+
40
+ "branches":"Branches",
41
+ "accessRights": "Access Rights",
42
+ "fullName":"Full Name",
43
+ "type": "Type",
44
+ "save": "Save",
45
+ "general": "General",
46
+ "login":"Login",
47
+ "sessionExpire": "Session Expire",
48
+ "reloginMessage": "Session Expire, relogin"
38
49
  }