@simitgroup/simpleapp-generator 1.6.4-c-alpha → 1.6.4-d-alpha

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 (65) hide show
  1. package/dist/buildinschemas/documentevent.d.ts +3 -0
  2. package/dist/buildinschemas/documentevent.d.ts.map +1 -0
  3. package/dist/buildinschemas/documentevent.js +38 -0
  4. package/dist/buildinschemas/documentevent.js.map +1 -0
  5. package/dist/buildinschemas/index.d.ts +2 -0
  6. package/dist/buildinschemas/index.d.ts.map +1 -1
  7. package/dist/buildinschemas/index.js +5 -1
  8. package/dist/buildinschemas/index.js.map +1 -1
  9. package/dist/buildinschemas/tenant.d.ts.map +1 -1
  10. package/dist/buildinschemas/tenant.js +8 -0
  11. package/dist/buildinschemas/tenant.js.map +1 -1
  12. package/dist/buildinschemas/webhook.d.ts.map +1 -1
  13. package/dist/buildinschemas/webhook.js +21 -3
  14. package/dist/buildinschemas/webhook.js.map +1 -1
  15. package/dist/buildinschemas/webhookhistory.d.ts +3 -0
  16. package/dist/buildinschemas/webhookhistory.d.ts.map +1 -0
  17. package/dist/buildinschemas/webhookhistory.js +44 -0
  18. package/dist/buildinschemas/webhookhistory.js.map +1 -0
  19. package/dist/framework.js +1 -1
  20. package/dist/framework.js.map +1 -1
  21. package/dist/generate.js +1 -1
  22. package/dist/generate.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/buildinschemas/documentevent.ts +36 -0
  25. package/src/buildinschemas/index.ts +3 -1
  26. package/src/buildinschemas/tenant.ts +8 -0
  27. package/src/buildinschemas/webhook.ts +22 -3
  28. package/src/buildinschemas/webhookhistory.ts +42 -0
  29. package/src/framework.ts +1 -1
  30. package/src/generate.ts +1 -1
  31. package/templates/basic/nest/apischema.ts.eta +6 -2
  32. package/templates/basic/nest/controller.ts.eta +4 -3
  33. package/templates/basic/nest/default.ts.eta +6 -5
  34. package/templates/basic/nuxt/default.ts.eta +2 -0
  35. package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +1 -6
  36. package/templates/nest/src/simpleapp/apischemas/index.ts._eta +17 -0
  37. package/templates/nest/src/simpleapp/generate/commons/audittrail.service.ts.eta +37 -7
  38. package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +39 -20
  39. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +53 -39
  40. package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +3 -3
  41. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +100 -34
  42. package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +5 -0
  43. package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +3 -3
  44. package/templates/nest/src/simpleapp/types/index.ts._eta +14 -0
  45. package/templates/nuxt/app.vue.eta +9 -7
  46. package/templates/nuxt/components/image/ImageAvatar.vue.eta._vue +7 -14
  47. package/templates/nuxt/components/list/ListView.vue.eta +97 -111
  48. package/templates/nuxt/components/renderer/RendererDocHistories.vue.eta +102 -42
  49. package/templates/nuxt/components/search/SearchBox.vue._eta +371 -0
  50. package/templates/nuxt/components/search/SearchBoxBefore.vue._eta +11 -0
  51. package/templates/nuxt/components/search/SearchBoxProduct.vue._eta +26 -0
  52. package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +24 -3
  53. package/templates/nuxt/components/simpleApp/SimpleAppCalendarInput.vue.eta +1 -0
  54. package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +10 -5
  55. package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +4 -3
  56. package/templates/nuxt/components/user/UserTenantPicker.vue.eta +18 -16
  57. package/templates/nuxt/composables/getOpenApi.generate.ts.eta +6 -49
  58. package/templates/nuxt/composables/stringHelper.generate.ts.eta +2 -2
  59. package/templates/nuxt/middleware/30.acl.global.ts.eta +6 -5
  60. package/templates/nuxt/pages/[xorg]/pickgroup.vue._eta +28 -27
  61. package/templates/nuxt/pages/picktenant.vue._eta +3 -3
  62. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +49 -29
  63. package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +7 -1
  64. package/templates/nuxt/types/others.ts.eta +7 -1
  65. package/tsconfig.tsbuildinfo +1 -1
@@ -41,6 +41,7 @@ import {
41
41
  MoreProjectionType,
42
42
  DeleteResultType,
43
43
  WorkflowName,
44
+ TextSearchBody,
44
45
  } from '../types';
45
46
  @Injectable()
46
47
  export class SimpleAppService<T extends { _id?: string; __v?: number }> {
@@ -269,6 +270,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
269
270
  .sort(sort);
270
271
  } else {
271
272
  const pipelines = this.searchToAggregate(
273
+ appuser,
272
274
  filters,
273
275
  projection,
274
276
  sort,
@@ -293,14 +295,17 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
293
295
  // return this;
294
296
  }
295
297
 
296
- async fullTextSearch(appuser: UserContext, keyword: string) {
298
+ async fullTextSearch(appuser: UserContext, body: TextSearchBody) {
297
299
  const isolationFilter = { ...this.getIsolationFilter(appuser) };
298
300
  this.polishIsolationFilter(isolationFilter);
299
301
 
300
- const filters = { $text: { $search: keyword } };
302
+ const filters = { $text: { $search: body.keyword } };
301
303
  const newfilters: FilterQuery<T> = { ...filters, ...isolationFilter };
302
-
303
- return await this.doc.find(newfilters);
304
+ const fields = body.fields;
305
+ const sorts = body.sorts;
306
+ //not yet support lookup mapper
307
+ const lookup = body.lookup;
308
+ return await this.doc.find(newfilters, fields, sorts);
304
309
  }
305
310
  async findById(appuser: UserContext, id: string) {
306
311
  if (this.hooks.beforeFetchRecord)
@@ -335,7 +340,14 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
335
340
  await this.validateData(appuser, data);
336
341
  this.applyNestedDateTime(appuser, data, 'create');
337
342
  }
343
+
338
344
  const result = await this.doc.insertMany(datas);
345
+ await this.audittrail.addManyEvents(
346
+ appuser,
347
+ this.documentName,
348
+ 'createMany',
349
+ datas,
350
+ );
339
351
  return result;
340
352
  } else {
341
353
  throw new BadRequestException(
@@ -346,6 +358,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
346
358
 
347
359
  async create(appuser: UserContext, data: T) {
348
360
  let result;
361
+
349
362
  if (!data._id) {
350
363
  data._id = crypto.randomUUID();
351
364
  }
@@ -354,6 +367,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
354
367
  dbsession.startTransaction();
355
368
  }
356
369
 
370
+
357
371
  this.logger.debug(
358
372
  'this.withDocNumberFormat :' +
359
373
  this.withDocNumberFormat +
@@ -365,7 +379,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
365
379
  await this.genNewDocNo(appuser, data);
366
380
  }
367
381
 
368
- if (this.hooks.beforeCreate) await this.hooks.beforeCreate(appuser, data);
382
+
369
383
  let isolationFilter: any = { ...appuser.getCreateFilter() };
370
384
  isolationFilter = this.polishIsolationFilter(isolationFilter, data);
371
385
 
@@ -379,11 +393,19 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
379
393
  this.logger.debug(data, `after create validation`);
380
394
  this.applyNestedDateTime(appuser, data, 'create');
381
395
 
396
+ if (this.hooks.beforeCreate) await this.hooks.beforeCreate(appuser, data);
382
397
  this.logger.debug(data, `Create Record ${this.documentName}`);
383
398
  const newdoc = new this.doc(data);
384
399
  await this.identifyForeignKeys(appuser, data);
385
400
  try {
386
401
  result = await newdoc.save({ session: dbsession });
402
+ await this.audittrail.addEvent(
403
+ appuser,
404
+ this.documentName,
405
+ result._id,
406
+ 'create',
407
+ data,
408
+ );
387
409
  appuser.addInsertedRecordId(this.documentName, result._id);
388
410
  } catch (err) {
389
411
  this.logger.error(err);
@@ -543,6 +565,13 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
543
565
  const result = await this.doc
544
566
  .deleteOne(filterIsolation)
545
567
  .session(dbsession);
568
+ await this.audittrail.addEvent(
569
+ appuser,
570
+ this.documentName,
571
+ id,
572
+ 'delete',
573
+ deletedata,
574
+ );
546
575
 
547
576
  appuser.addDeletedRecordId(this.documentName, id);
548
577
  const deleteresult: DeleteResultType<T> = {
@@ -576,50 +605,64 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
576
605
  // };
577
606
 
578
607
  findIdThenUpdate = async (appuser: UserContext, id: string, data: T) => {
579
-
580
608
  try {
581
- //version exists, need ensure different only 1
609
+ //version exists, need ensure different only 1
582
610
  const existingdata = await this.findById(appuser, id);
583
- if(!existingdata) throw new NotFoundException(`${this.documentName} findIdThenUpdate: _id:${id} not found`, 'not found');
611
+ if (!existingdata)
612
+ throw new NotFoundException(
613
+ `${this.documentName} findIdThenUpdate: _id:${id} not found`,
614
+ 'not found',
615
+ );
584
616
 
585
- this.logger.debug("update id:"+id,this.documentName+' findIdThenUpdate')
617
+ this.logger.debug(
618
+ 'update id:' + id,
619
+ this.documentName + ' findIdThenUpdate',
620
+ );
586
621
  if (typeof data.__v == 'number' && data.__v != existingdata.__v) {
587
622
  throw new BadRequestException(
588
623
  `You submit older version data "v${data.__v}"" but latest version = "v${existingdata.__v}"`,
589
624
  );
590
625
  }
591
- this.logger.debug("warn1",existingdata)
592
- data.__v = existingdata.__v + 1;
593
- // if (!existingdata) {
594
- // throw new NotFoundException(`${id} not found`, 'not found');
595
- // }
596
- this.logger.debug("warn2")
597
- if (this.hooks.beforeUpdate)
598
- await this.hooks.beforeUpdate(appuser, id, data, existingdata);
626
+ this.logger.debug('warn1', existingdata);
627
+ data.__v = existingdata.__v + 1;
628
+ // if (!existingdata) {
629
+ // throw new NotFoundException(`${id} not found`, 'not found');
630
+ // }
631
+ this.logger.debug('warn2');
632
+ if (this.hooks.beforeUpdate)
633
+ await this.hooks.beforeUpdate(appuser, id, data, existingdata);
634
+
635
+ const dbsession = appuser.getDBSession();
636
+ if (dbsession && !dbsession.inTransaction()) {
637
+ dbsession.startTransaction();
638
+ }
639
+ // try {
640
+ Object.assign(data, appuser.getUpdateFilter());
641
+ // Object.assign(existingdata, data);
599
642
 
600
- const dbsession = appuser.getDBSession();
601
- if (dbsession && !dbsession.inTransaction()) {
602
- dbsession.startTransaction();
603
- }
604
- // try {
605
- Object.assign(data, appuser.getUpdateFilter());
606
- // Object.assign(existingdata, data);
643
+ delete data['_id'];
644
+ this.reCalculateValue(data);
607
645
 
608
- delete data['_id'];
609
- this.reCalculateValue(data);
646
+ // existingdata['_id']=''
647
+ await this.validateData(appuser, data, id);
610
648
 
611
- // existingdata['_id']=''
612
- await this.validateData(appuser, data, id);
649
+ const isolationFilter = { ...this.getIsolationFilter(appuser) };
650
+ this.polishIsolationFilter(isolationFilter);
651
+ isolationFilter['_id'] = id;
652
+ this.applyNestedDateTime(appuser, data, 'update');
613
653
 
614
- const isolationFilter = { ...this.getIsolationFilter(appuser) };
615
- this.polishIsolationFilter(isolationFilter);
616
- isolationFilter['_id'] = id;
617
- this.applyNestedDateTime(appuser, data, 'update');
618
-
619
654
  const result = await this.doc.findOneAndReplace(isolationFilter, data, {
620
655
  session: dbsession,
621
656
  new: true,
622
657
  });
658
+ await this.audittrail.addEvent(
659
+ appuser,
660
+ this.documentName,
661
+ id,
662
+ 'update',
663
+ data,
664
+ );
665
+
623
666
  appuser.addUpdatedRecordId(this.documentName, data._id);
624
667
  if (this.hooks.afterUpdate)
625
668
  await this.hooks.afterUpdate(appuser, id, existingdata, result);
@@ -679,7 +722,13 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
679
722
  session: dbsession,
680
723
  new: true,
681
724
  });
682
-
725
+ await this.audittrail.addEvent(
726
+ appuser,
727
+ this.documentName,
728
+ id,
729
+ 'patch',
730
+ data,
731
+ );
683
732
  appuser.addUpdatedRecordId(this.documentName, data._id);
684
733
 
685
734
  if (this.hooks.afterUpdate)
@@ -781,12 +830,27 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
781
830
  const createresult = await this.create(appuser, data);
782
831
  if (this.hooks.afterSetStatus)
783
832
  await this.hooks.afterSetStatus(appuser, docstatus, createresult);
833
+ await this.audittrail.addEvent(
834
+ appuser,
835
+ this.documentName,
836
+ id,
837
+ docstatus,
838
+ data,
839
+ );
840
+
784
841
  return createresult;
785
842
  } else {
786
843
  const updateresult = await this.findIdThenPatch(appuser, id, data);
787
844
  const finaldata = await this.findById(appuser, id);
788
845
  if (this.hooks.afterSetStatus)
789
846
  await this.hooks.afterSetStatus(appuser, docstatus, finaldata);
847
+ await this.audittrail.addEvent(
848
+ appuser,
849
+ this.documentName,
850
+ id,
851
+ docstatus,
852
+ data,
853
+ );
790
854
 
791
855
  this.callWebhook(appuser, docstatus, finaldata);
792
856
  return updateresult;
@@ -975,6 +1039,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
975
1039
  }
976
1040
 
977
1041
  searchToAggregate(
1042
+ appuser: UserContext,
978
1043
  filter: FilterQuery<T>,
979
1044
  columns: string[],
980
1045
  sort: string[][],
@@ -1002,6 +1067,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1002
1067
  as: '_' + to,
1003
1068
  localField: lookup[tokey],
1004
1069
  foreignField: foreignField,
1070
+ pipeline: [{ $match: { tenantId: appuser.getTenantId() } }],
1005
1071
  },
1006
1072
  });
1007
1073
  pipelines.push({ $unwind: '$_' + to });
@@ -103,6 +103,11 @@ export class ProfileService {
103
103
  const tenantdata: Tenant = {
104
104
  tenantId: 1,
105
105
  tenantName: tenantName,
106
+ clientSetting: {
107
+ auditTrail:false,
108
+ webhook:false,
109
+ support:false,
110
+ },
106
111
  active: true,
107
112
  owner: {
108
113
  _id: appuser.getId(),
@@ -8,9 +8,9 @@ import { Module } from '@nestjs/common';
8
8
  import { MongooseModule } from '@nestjs/mongoose';
9
9
  import {DocNumberFormatGenerator} from './generate/commons/docnogenerator.service'
10
10
  import { AuditTrail } from './generate/commons/audittrail.service';
11
- import { CloudapiModule } from 'src/cloudapi/cloudapi.module';
12
- import { PrintapiModule } from 'src/printapi/printapi.module';
13
- import { RunWebhookService } from 'src/simpleapp/generate/commons/runwebhook.service'
11
+ import { CloudapiModule } from '../cloudapi/cloudapi.module';
12
+ import { PrintapiModule } from '../printapi/printapi.module';
13
+ import { RunWebhookService } from '../simpleapp/generate/commons/runwebhook.service'
14
14
  import { UserResolverService } from './services/userresolver.service';
15
15
  // auto import modules
16
16
  <% for(let i=0;i<it.modules.length; i++){ %>
@@ -29,3 +29,17 @@ export type UserPermission = {
29
29
  groups: string[]
30
30
  userId : string
31
31
  }
32
+ export type OutstandingByStudent = {
33
+ _id: string;
34
+ student: ForeignKey;
35
+ level: ForeignKey;
36
+ totalAmt: number;
37
+ invoices: ForeignKey[];
38
+ };
39
+
40
+ export type TextSearchBody = {
41
+ keyword:string;
42
+ fields?:string[];
43
+ sorts?:string[][];
44
+ lookup?: Record<string,string>;
45
+ }
@@ -1,5 +1,7 @@
1
1
  <template>
2
- <NuxtLayout :name="getLayout()">
2
+ <NuxtLayout>
3
+
4
+ <!-- <NuxtLayout :name="getLayout()"> -->
3
5
  <ConfirmDialog></ConfirmDialog>
4
6
  <DynamicDialog />
5
7
  <SessionBlock/>
@@ -28,13 +30,13 @@ watch(()=>useRoute().params['xorg'],async (newval,oldvalue)=>{
28
30
  })
29
31
 
30
32
  const getLayout = ()=>{
31
- const { status } = useAuth();
33
+ // const { status } = useAuth();
32
34
 
33
- if(status.value=='unauthenticated') return 'loginlayout'
34
- else {
35
- if (isMobile()) return 'mobile'
36
- else 'default'
37
- }
35
+ // if(status.value=='unauthenticated') return 'loginlayout'
36
+ // else {
37
+ // if (isMobile()) return 'mobile'
38
+ // else 'default'
39
+ // }
38
40
  }
39
41
 
40
42
  onMounted(()=>{
@@ -1,30 +1,23 @@
1
1
  <template>
2
- <div class="inline-block border rounded-lg w-20 h-20 bg-white">
3
- <Avatar v-if="email"
4
- :image="getAvatarLink(<string>email, size)"
2
+ <div :class="`inline-block border rounded-lg w-${size} h-${size} bg-white`">
3
+ <Avatar
4
+ :image="getAvatarLink(<string>id, size*3)"
5
5
  shape="circle"
6
- size="xlarge"
7
- />
8
- <Avatar v-else-if="id"
9
- :image="getAvatarByUid(<string>id, size)"
10
- shape="circle"
11
- size="xlarge"
6
+ class="w-full h-full"
12
7
  />
8
+
9
+
13
10
  </div>
14
-
15
-
16
11
  </template>
17
12
  <script lang="ts" setup>
18
13
  /**
19
- * This file was automatically generated by simpleapp generator during initialization.
14
+ * This file was automatically generated by simpleapp generator during initialization.
20
15
  * --remove-this-line-to-prevent-override--
21
16
  * last change 2024-04-06
22
17
  * author: Ks Tan
23
18
  */
24
19
  const props = defineProps<{
25
- email?: string;
26
20
  id?: string;
27
21
  size: number;
28
22
  }>();
29
-
30
23
  </script>
@@ -1,15 +1,23 @@
1
- <template>
2
- <div class="relative">
3
- <div v-if="header">
4
- <slot name="header">
5
- <TextMain class="text-gray-800 pl-2 pt-2">{{ header }}</TextMain>
6
- </slot>
7
- <hr class="mt-2" />
8
- </div>
9
- <div v-if="withFilter" class="flex flex-row p-2">
10
- <InputGroup :pt="{ root: { class: 'p-0' } }">
11
- <InputGroupAddon
12
- v-if="filter !== undefined && Object.keys(filter).length > 0"
1
+ <template>
2
+ <Listbox
3
+ ref="listview"
4
+ :options="filterlist"
5
+ v-model="selectedItem"
6
+ :optionLabel="titleField"
7
+ :filter="withFilter"
8
+ :optionValue="idField"
9
+
10
+ :filterFields="filterFields"
11
+ :pt="{filterContainer:{class:'p-inputgroup'}}"
12
+ >
13
+ <template #empty>
14
+ <slot name="nodata">
15
+ <NodataLarge/>
16
+ </slot>
17
+ </template>
18
+ <template #filtericon="sss">
19
+ <!-- <i class="pi pi-refresh"/> -->
20
+ <InputGroupAddon v-if="filter !== undefined && Object.keys(filter).length > 0"
13
21
  :pt="{
14
22
  root: {
15
23
  class:
@@ -18,20 +26,15 @@
18
26
  }"
19
27
  @click="showMoreFilter"
20
28
  >
21
- </InputGroupAddon>
22
- <InputGroupAddon
23
- v-else
24
- :pt="{ root: { class: 'p-0 pi pi-filter cursor-pointer p-3' } }"
25
- @click="showMoreFilter"
26
- >
27
- </InputGroupAddon>
28
- <InputText
29
- :placeholder="t('searchKeyword')"
30
- v-model="searchvalue"
31
- type="search"
32
- :pt="{ root: { class: 'p-1' } }"
33
- ref="listviewfilter"
34
- />
29
+ </InputGroupAddon>
30
+ <InputGroupAddon
31
+ v-else-if="filter !== undefined"
32
+ :pt="{ root: { class: 'p-0 pi pi-filter cursor-pointer p-3' } }"
33
+ @click="showMoreFilter"
34
+ >
35
+ </InputGroupAddon>
36
+ <slot name="filterInputGroupAddon"></slot>
37
+
35
38
  <InputGroupAddon
36
39
  :pt="{
37
40
  root: {
@@ -42,73 +45,53 @@
42
45
  v-if="withAddNew"
43
46
  @click="emits('add')"
44
47
  >
45
-
46
48
  </InputGroupAddon>
47
- <slot name="inputAddOn"></slot>
48
- </InputGroup>
49
- </div>
50
-
51
- <div
52
- v-if="showIndex"
53
- class="flex flex-col fixed left-1 top-1/5 gap-2 z-10 rounded border bg-white dark:bg-black opacity-90"
54
- >
55
- <NuxtLink
56
- class="text-primary-600 dark:text-primary-400 text-lg p-2"
57
- :url="'#' + l"
58
- v-for="l in allLetters"
59
- >{{ l }}</NuxtLink
60
- >
61
- </div>
49
+ </template>
50
+
51
+ <template #header="{options,value}">
52
+ <div>
53
+ <slot name="header">
54
+ <TextMain class="text-gray-800 pl-2 pt-2">{{ header }}</TextMain>
55
+ </slot>
56
+ <hr class="mt-2" />
57
+ </div>
58
+ </template>
62
59
 
63
- <div v-if="filterlist && filterlist.length > 0">
64
- <div>
65
- <div v-for="(item, index) in filterlist">
66
- <!-- :class="isMobile() ? '' : 'overflow overflow-y-scroll overflow-auto '" -->
67
- <div
68
- :id="titleField && item[titleField] && item[titleField][0]"
69
- ></div>
70
- <div
71
- class="w-full bg-gray-400 dark:bg-gray-500 p-1 pl-2 top-0 sticky opacity-90"
72
- v-if="
73
- showIndex && titleField && showCategoryBar(item[titleField][0])
74
- "
75
- >
76
- <span>{{ item[titleField][0] }}</span>
77
- </div>
60
+ <template #option="{option,index}">
61
+ <div
62
+ :id="titleField && option[titleField] && option[titleField][0]"
63
+ ></div>
64
+ <div
65
+ class="w-full bg-gray-400 dark:bg-gray-500 p-1 pl-2 top-0 sticky opacity-90"
66
+ v-if="
67
+ showIndex && titleField && showCategoryBar(option[titleField][0])
68
+ "
69
+ >
70
+ <span>{{ option[titleField][0] }}</span>
71
+ </div>
72
+ <div class="border-l-none border-r-none listview-item">
73
+ <!-- :to="getUrl(option)" -->
78
74
  <div
79
- @click="onClick(index, item, $event)"
80
- :class="`border-l-none border-r-none listview-item dark:border-t-gray-700 ${
81
- index > 0 ? 'border-t-2' : ''
82
- }`"
75
+
76
+ :class="`p-2 ${showClickEffect ? 'listlink' : ''}`"
83
77
  >
84
- <NuxtLink
85
- :to="getUrl(item)"
86
- :class="`p-2 ${showClickEffect ? 'listlink' : ''}`"
87
- >
88
- <slot name="default" :item="item" :index="index">
89
- <div class="flex flex-row">
90
- <div class="flex-1 mr-2 dark:text-white">
91
- {{ item[titleField ?? ""] }}
92
- </div>
93
- <div class="text-right dark:text-gray-400 text-gray-600">
94
- {{ item[subTitleField ?? ""] }}
95
- </div>
78
+ <slot name="default" :item="option" :index="index">
79
+ <div class="flex flex-row">
80
+ <div class="flex-1 mr-2 dark:text-white">
81
+ {{ option[titleField ?? ""] }}
96
82
  </div>
97
- </slot>
98
- </NuxtLink>
83
+ <div class="text-right dark:text-gray-400 text-gray-600">
84
+ {{ option[subTitleField ?? ""] }}
85
+ </div>
86
+ </div>
87
+ </slot>
99
88
  </div>
100
89
  </div>
101
- </div>
102
- </div>
103
- <div v-else>
104
- <div class="w-full h-20 p-2 border-l-none border-r-none">
105
- <slot name="nodata">
106
- <div class="border-round border-1 surface-border p-4 surface-card">
107
- {{ t("noDataFound") }}
108
- </div>
109
- </slot>
110
- </div>
111
- </div>
90
+ </template>
91
+ </Listbox>
92
+
93
+
94
+
112
95
 
113
96
  <Dialog
114
97
  v-model:visible="visibleMoreFilter"
@@ -129,7 +112,7 @@
129
112
  </div>
130
113
  </template>
131
114
  </Dialog>
132
- </div>
115
+
133
116
  </template>
134
117
  <script setup lang="ts" generic="T extends { [key: string]: any }">
135
118
  /**
@@ -141,8 +124,10 @@
141
124
  import { ref } from "vue";
142
125
  import { ListItem } from "~/types/listview";
143
126
  import _ from "lodash";
127
+ const listview = ref(null)
144
128
  const visibleMoreFilter = ref(false);
145
129
  const listviewfilter = ref();
130
+ const selectedItem = ref('')
146
131
  const props = withDefaults(
147
132
  defineProps<{
148
133
  list: T[];
@@ -150,40 +135,31 @@ const props = withDefaults(
150
135
  urlsuffix?: string;
151
136
  header?: string;
152
137
  titleField?: string;
153
- idField?: string;
138
+ idField: string;
154
139
  subTitleField?: string;
155
140
  withFilter?: boolean;
156
141
  filter?: { [key: string]: any };
157
142
  withAddNew?: boolean;
158
143
  showIndex?: boolean;
159
144
  showClickEffect?: boolean;
145
+
160
146
  }>(),
161
147
  {
162
148
  idField: "_id",
163
149
  },
164
150
  );
151
+ const filterFields=computed(()=>{
152
+ const fields:string[] = []
153
+ if(props.titleField) fields.push(props.titleField)
154
+ if(props.subTitleField) fields.push(props.subTitleField)
155
+ return fields
156
+ })
165
157
  const letters = ref<string[]>([]);
166
158
  let lastchar = "";
167
159
 
168
160
  const emits = defineEmits(["add", "runFilter", "clearFilter", "click"]);
169
161
  const searchvalue = ref("");
170
- const selecteditem = ref("");
171
- const clickRow = (item: ListItem) => {
172
- // emit('clickitem',item)
173
- // selecteditem.value = item.code
174
- };
175
- const getUrl = (item: any) => {
176
- const urlsuffix =
177
- props.urlsuffix === undefined || props.urlsuffix == ""
178
- ? ""
179
- : "/" + props.urlsuffix;
180
- if (props.url && props.idField) {
181
- if (_.last(props.url) == "/")
182
- return `${props.url}${item[props.idField]}${urlsuffix}`;
183
- else return `${props.url}/${item[props.idField]}${urlsuffix}`;
184
- } else return undefined;
185
- // :to="url ? `${url}/${item[idField]}` : undefined"
186
- };
162
+
187
163
  const filterlist = computed(() => {
188
164
  let newlist: T[] = [];
189
165
  if (!Array.isArray(props.list)) {
@@ -236,9 +212,6 @@ const showCategoryBar = (letter: string) => {
236
212
  }
237
213
  };
238
214
 
239
- const onClick = (index: number, data: T, event: Event | MouseEvent) => {
240
- emits("click", index, data, event);
241
- };
242
215
 
243
216
  const showMoreFilter = () => {
244
217
  visibleMoreFilter.value = true;
@@ -251,7 +224,20 @@ const runFilter = () => {
251
224
  visibleMoreFilter.value = false;
252
225
  emits("runFilter");
253
226
  };
254
- onMounted(() => {
255
- // if(props.withFilter) listviewfilter.value.$el.focus()
256
- });
227
+
228
+ watch(selectedItem,(newvalue)=>{
229
+ if(newvalue){
230
+ emits("click",newvalue);
231
+ if(props.url){
232
+ navigateTo(props.url+'/'+newvalue)
233
+ }
234
+
235
+ }
236
+ })
237
+
238
+ function setFocus(){
239
+ const listbodyid = listview.value?.$el?.id
240
+ document.querySelector(`#${listbodyid} .p-listbox-list`)?.focus()
241
+ }
242
+ defineExpose({setFocus})
257
243
  </script>