@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.
- package/dist/buildinschemas/documentevent.d.ts +3 -0
- package/dist/buildinschemas/documentevent.d.ts.map +1 -0
- package/dist/buildinschemas/documentevent.js +38 -0
- package/dist/buildinschemas/documentevent.js.map +1 -0
- package/dist/buildinschemas/index.d.ts +2 -0
- package/dist/buildinschemas/index.d.ts.map +1 -1
- package/dist/buildinschemas/index.js +5 -1
- package/dist/buildinschemas/index.js.map +1 -1
- package/dist/buildinschemas/tenant.d.ts.map +1 -1
- package/dist/buildinschemas/tenant.js +8 -0
- package/dist/buildinschemas/tenant.js.map +1 -1
- package/dist/buildinschemas/webhook.d.ts.map +1 -1
- package/dist/buildinschemas/webhook.js +21 -3
- package/dist/buildinschemas/webhook.js.map +1 -1
- package/dist/buildinschemas/webhookhistory.d.ts +3 -0
- package/dist/buildinschemas/webhookhistory.d.ts.map +1 -0
- package/dist/buildinschemas/webhookhistory.js +44 -0
- package/dist/buildinschemas/webhookhistory.js.map +1 -0
- package/dist/framework.js +1 -1
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +1 -1
- package/dist/generate.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/documentevent.ts +36 -0
- package/src/buildinschemas/index.ts +3 -1
- package/src/buildinschemas/tenant.ts +8 -0
- package/src/buildinschemas/webhook.ts +22 -3
- package/src/buildinschemas/webhookhistory.ts +42 -0
- package/src/framework.ts +1 -1
- package/src/generate.ts +1 -1
- package/templates/basic/nest/apischema.ts.eta +6 -2
- package/templates/basic/nest/controller.ts.eta +4 -3
- package/templates/basic/nest/default.ts.eta +6 -5
- package/templates/basic/nuxt/default.ts.eta +2 -0
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +1 -6
- package/templates/nest/src/simpleapp/apischemas/index.ts._eta +17 -0
- package/templates/nest/src/simpleapp/generate/commons/audittrail.service.ts.eta +37 -7
- package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +39 -20
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +53 -39
- package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +3 -3
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +100 -34
- package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +5 -0
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +3 -3
- package/templates/nest/src/simpleapp/types/index.ts._eta +14 -0
- package/templates/nuxt/app.vue.eta +9 -7
- package/templates/nuxt/components/image/ImageAvatar.vue.eta._vue +7 -14
- package/templates/nuxt/components/list/ListView.vue.eta +97 -111
- package/templates/nuxt/components/renderer/RendererDocHistories.vue.eta +102 -42
- package/templates/nuxt/components/search/SearchBox.vue._eta +371 -0
- package/templates/nuxt/components/search/SearchBoxBefore.vue._eta +11 -0
- package/templates/nuxt/components/search/SearchBoxProduct.vue._eta +26 -0
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +24 -3
- package/templates/nuxt/components/simpleApp/SimpleAppCalendarInput.vue.eta +1 -0
- package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +10 -5
- package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +4 -3
- package/templates/nuxt/components/user/UserTenantPicker.vue.eta +18 -16
- package/templates/nuxt/composables/getOpenApi.generate.ts.eta +6 -49
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +2 -2
- package/templates/nuxt/middleware/30.acl.global.ts.eta +6 -5
- package/templates/nuxt/pages/[xorg]/pickgroup.vue._eta +28 -27
- package/templates/nuxt/pages/picktenant.vue._eta +3 -3
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +49 -29
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +7 -1
- package/templates/nuxt/types/others.ts.eta +7 -1
- 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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
609
|
+
//version exists, need ensure different only 1
|
|
582
610
|
const existingdata = await this.findById(appuser, id);
|
|
583
|
-
if(!existingdata)
|
|
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(
|
|
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(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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
|
-
|
|
601
|
-
|
|
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
|
-
|
|
609
|
-
|
|
646
|
+
// existingdata['_id']=''
|
|
647
|
+
await this.validateData(appuser, data, id);
|
|
610
648
|
|
|
611
|
-
|
|
612
|
-
|
|
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 '
|
|
12
|
-
import { PrintapiModule } from '
|
|
13
|
-
import { RunWebhookService } from '
|
|
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
|
|
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
|
-
|
|
36
|
-
|
|
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
|
|
3
|
-
<Avatar
|
|
4
|
-
:image="getAvatarLink(<string>
|
|
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
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<
|
|
29
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
80
|
-
:class="`
|
|
81
|
-
index > 0 ? 'border-t-2' : ''
|
|
82
|
-
}`"
|
|
75
|
+
|
|
76
|
+
:class="`p-2 ${showClickEffect ? 'listlink' : ''}`"
|
|
83
77
|
>
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
</
|
|
102
|
-
</
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
255
|
-
|
|
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>
|