@simitgroup/simpleapp-generator 1.6.4-d-alpha → 1.6.4-f-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/index.d.ts +0 -1
- package/dist/buildinschemas/index.d.ts.map +1 -1
- package/dist/buildinschemas/index.js +1 -3
- package/dist/buildinschemas/index.js.map +1 -1
- package/dist/buildinschemas/systemmessage.js +3 -3
- package/dist/buildinschemas/systemmessage.js.map +1 -1
- package/dist/buildinschemas/tenant.d.ts.map +1 -1
- package/dist/buildinschemas/tenant.js +1 -0
- package/dist/buildinschemas/tenant.js.map +1 -1
- package/dist/buildinschemas/user.d.ts.map +1 -1
- package/dist/buildinschemas/user.js +7 -0
- package/dist/buildinschemas/user.js.map +1 -1
- package/dist/buildinschemas/webhook.d.ts.map +1 -1
- package/dist/buildinschemas/webhook.js +20 -5
- package/dist/buildinschemas/webhook.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/index.ts +0 -1
- package/src/buildinschemas/systemmessage.ts +3 -3
- package/src/buildinschemas/tenant.ts +1 -0
- package/src/buildinschemas/user.ts +7 -0
- package/src/buildinschemas/webhook.ts +21 -7
- package/templates/nest/.env._eta +5 -0
- package/templates/nest/src/simpleapp/generate/commons/audittrail.service.ts.eta +31 -26
- package/templates/nest/src/simpleapp/generate/commons/dicts/documents.ts.eta +2 -1
- package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +161 -29
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +14 -9
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +4 -6
- package/templates/nest/src/simpleapp/generate/processors/webhook.processor.ts.eta +224 -0
- package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +16 -8
- package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +6 -4
- package/templates/nuxt/components/calendar/CalendarSmall.vue.eta +113 -110
- package/templates/nuxt/components/image/ImageAvatar.vue.eta._vue +47 -13
- package/templates/nuxt/components/image/ImageToBase64Uploader.vue.eta.vue +5 -5
- package/templates/nuxt/components/renderer/RendererDocHistories.vue.eta +8 -5
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +25 -18
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +13 -9
- package/templates/nuxt/pages/profile.vue.eta +3 -1
- package/templates/nuxt/server/api/profile/[...].ts.eta +11 -2
- package/templates/nuxt/simpleapp/generate/commons/documents.ts.eta +3 -1
- package/templates/nuxt/types/others.ts.eta +1 -0
- package/templates/nuxt/types/simpleappinput.ts.eta +2 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/buildinschemas/webhookhistory.ts +0 -42
|
@@ -210,7 +210,7 @@ export class UserContext {
|
|
|
210
210
|
},
|
|
211
211
|
{
|
|
212
212
|
$unwind: '$currentTenant',
|
|
213
|
-
}
|
|
213
|
+
},
|
|
214
214
|
],
|
|
215
215
|
},
|
|
216
216
|
};
|
|
@@ -219,12 +219,11 @@ export class UserContext {
|
|
|
219
219
|
|
|
220
220
|
if (this.tenantId > 0) {
|
|
221
221
|
pipeline.push(joinpermission);
|
|
222
|
-
pipeline.push({$unwind:'$permissions'})
|
|
223
|
-
|
|
222
|
+
pipeline.push({ $unwind: '$permissions' });
|
|
224
223
|
}
|
|
225
224
|
// console.log("obtainProfileFromDbobtainProfileFromDb ",pipeline)
|
|
226
225
|
// const users = await usermodel.find(filter)
|
|
227
|
-
const users = await this.usermodel.aggregate(pipeline);
|
|
226
|
+
const users = await this.usermodel.aggregate(pipeline);
|
|
228
227
|
this.logger.verbose(
|
|
229
228
|
`aggregate user profile from database`,
|
|
230
229
|
'obtainProfileFromDb',
|
|
@@ -241,7 +240,7 @@ export class UserContext {
|
|
|
241
240
|
|
|
242
241
|
if (myperm && myperm.groups) {
|
|
243
242
|
userinfo.groups = myperm.groups;
|
|
244
|
-
userinfo.roles = [] as Role[];
|
|
243
|
+
userinfo.roles = [Role.Everyone, Role.User] as Role[];
|
|
245
244
|
for (let g = 0; g < userinfo.groups.length; g++) {
|
|
246
245
|
const roles: Role[] = rolegroups[userinfo.groups[g]]();
|
|
247
246
|
for (let r = 0; r < roles.length; r++) {
|
|
@@ -608,7 +607,6 @@ export class UserContext {
|
|
|
608
607
|
},
|
|
609
608
|
} as PipelineStage;
|
|
610
609
|
|
|
611
|
-
|
|
612
610
|
const permission: PipelineStage = {
|
|
613
611
|
$lookup: {
|
|
614
612
|
from: 'permission',
|
|
@@ -639,12 +637,19 @@ export class UserContext {
|
|
|
639
637
|
};
|
|
640
638
|
|
|
641
639
|
const pipelines: PipelineStage[] = [
|
|
642
|
-
{ $match: { uid: this.uid, tenantId: { $gt: 0 }}},
|
|
643
|
-
{
|
|
640
|
+
{ $match: { uid: this.uid, tenantId: { $gt: 0 } } },
|
|
641
|
+
{
|
|
642
|
+
$lookup: {
|
|
643
|
+
from: 'tenant',
|
|
644
|
+
localField: 'tenantId',
|
|
645
|
+
foreignField: 'tenantId',
|
|
646
|
+
as: 'tenant',
|
|
647
|
+
},
|
|
648
|
+
},
|
|
644
649
|
permission,
|
|
645
650
|
];
|
|
646
651
|
// const users=[]
|
|
647
|
-
this.logger.warn(pipelines, 'pipelines');
|
|
652
|
+
// this.logger.warn(pipelines, 'pipelines');
|
|
648
653
|
const users = await this.usermodel.aggregate(pipelines);
|
|
649
654
|
|
|
650
655
|
if (users) {
|
|
@@ -367,7 +367,6 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
|
|
|
367
367
|
dbsession.startTransaction();
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
|
|
371
370
|
this.logger.debug(
|
|
372
371
|
'this.withDocNumberFormat :' +
|
|
373
372
|
this.withDocNumberFormat +
|
|
@@ -379,7 +378,6 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
|
|
|
379
378
|
await this.genNewDocNo(appuser, data);
|
|
380
379
|
}
|
|
381
380
|
|
|
382
|
-
|
|
383
381
|
let isolationFilter: any = { ...appuser.getCreateFilter() };
|
|
384
382
|
isolationFilter = this.polishIsolationFilter(isolationFilter, data);
|
|
385
383
|
|
|
@@ -623,14 +621,14 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
|
|
|
623
621
|
`You submit older version data "v${data.__v}"" but latest version = "v${existingdata.__v}"`,
|
|
624
622
|
);
|
|
625
623
|
}
|
|
626
|
-
this.logger.debug('warn1', existingdata);
|
|
624
|
+
// this.logger.debug('warn1', existingdata);
|
|
627
625
|
data.__v = existingdata.__v + 1;
|
|
628
626
|
// if (!existingdata) {
|
|
629
627
|
// throw new NotFoundException(`${id} not found`, 'not found');
|
|
630
628
|
// }
|
|
631
|
-
this.logger.debug('warn2');
|
|
629
|
+
// this.logger.debug('warn2');
|
|
632
630
|
if (this.hooks.beforeUpdate)
|
|
633
|
-
await this.hooks.beforeUpdate(appuser, id,
|
|
631
|
+
await this.hooks.beforeUpdate(appuser, id, existingdata,data);
|
|
634
632
|
|
|
635
633
|
const dbsession = appuser.getDBSession();
|
|
636
634
|
if (dbsession && !dbsession.inTransaction()) {
|
|
@@ -693,7 +691,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
|
|
|
693
691
|
data.__v = existingdata.__v + 1;
|
|
694
692
|
|
|
695
693
|
if (this.hooks.beforeUpdate)
|
|
696
|
-
await this.hooks.beforeUpdate(appuser, id, data
|
|
694
|
+
await this.hooks.beforeUpdate(appuser, id,existingdata, data);
|
|
697
695
|
|
|
698
696
|
const dbsession = appuser.getDBSession();
|
|
699
697
|
if (dbsession && !dbsession.inTransaction()) {
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by simpleapp generator. Every
|
|
3
|
+
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
4
|
+
* last change 2024-02-23
|
|
5
|
+
* Author: Ks Tan
|
|
6
|
+
*/
|
|
7
|
+
import { UserContext } from '../commons/user.context';
|
|
8
|
+
import * as sharelibs from '../sharelibs';
|
|
9
|
+
import { Injectable, InternalServerErrorException, } from '@nestjs/common';
|
|
10
|
+
import { InjectModel } from '@nestjs/mongoose';
|
|
11
|
+
import * as jsonpath from 'jsonpath';
|
|
12
|
+
import { Model } from 'mongoose';
|
|
13
|
+
import { WebhookJsonSchema } from '../jsonschemas/webhook.jsonschema';
|
|
14
|
+
import { SimpleAppService } from './simpleapp.processor';
|
|
15
|
+
import * as types from '../types';
|
|
16
|
+
import { DocNumberFormatGenerator } from '../commons/docnogenerator.service';
|
|
17
|
+
import {
|
|
18
|
+
WebhookBasicAuth,
|
|
19
|
+
WebhookHeaders,
|
|
20
|
+
Webhook,
|
|
21
|
+
} from '../types/webhook.type';
|
|
22
|
+
import {
|
|
23
|
+
DefaultWebhookBasicAuth,
|
|
24
|
+
DefaultWebhookHeaders,
|
|
25
|
+
DefaultWebhook,
|
|
26
|
+
} from '../defaults/webhook.default';
|
|
27
|
+
|
|
28
|
+
@Injectable()
|
|
29
|
+
export class WebhookProcessor extends SimpleAppService<Webhook> {
|
|
30
|
+
protected documentIdentityCode = 'title';
|
|
31
|
+
protected documentIdentityLabel = 'title';
|
|
32
|
+
private webhookApiKey = process.env.WEBHOOK_SERVER_APIKEY
|
|
33
|
+
private webhookAppId=process.env.WEBHOOK_SERVER_APP_ID
|
|
34
|
+
private webhookurl = process.env.WEBHOOK_SERVER_URL;
|
|
35
|
+
private webhookprefix = process.env.PROJECT_CODE+'.'
|
|
36
|
+
private webhooksubscribtionurl = `${process.env.WEBHOOK_SERVER_URL}/subscriptions/`;
|
|
37
|
+
|
|
38
|
+
protected hooks: types.WebhookHooks = {
|
|
39
|
+
beforeCreate: async (appuser: UserContext, data: types.Webhook) =>
|
|
40
|
+
this.beforeCreate(appuser, data),
|
|
41
|
+
beforeUpdate: async (
|
|
42
|
+
appuser: UserContext,
|
|
43
|
+
id: string,
|
|
44
|
+
prevdata: types.Webhook,
|
|
45
|
+
newdata: types.Webhook,
|
|
46
|
+
) => this.beforeUpdate(appuser, id, prevdata, newdata),
|
|
47
|
+
afterDelete: async (
|
|
48
|
+
appuser: UserContext,
|
|
49
|
+
result: types.DeleteResultType<types.Webhook>,
|
|
50
|
+
id: string,
|
|
51
|
+
) => this.afterDelete(appuser, result, id),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
protected foreignkeys = {};
|
|
56
|
+
constructor(mydoc: Model<Webhook>) {
|
|
57
|
+
super('WEBHOOK', 'webhook', mydoc, types.IsolationType.tenant);
|
|
58
|
+
this.setSchema(WebhookJsonSchema);
|
|
59
|
+
this.setData(DefaultWebhook(crypto.randomUUID()));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
reCalculateValue(data: Webhook) {
|
|
63
|
+
//console.log('trigger new recalculate')
|
|
64
|
+
const $data = data;
|
|
65
|
+
const jsopbj = new jsonpath['JSONPath']();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async beforeCreate(appuser: UserContext, data: types.Webhook) {
|
|
69
|
+
const createResult = await this.addRemoteWebhook(appuser, data);
|
|
70
|
+
if (!createResult['subscription_id'])
|
|
71
|
+
throw new InternalServerErrorException(
|
|
72
|
+
'syncronize webhook server failed',
|
|
73
|
+
);
|
|
74
|
+
data.serverSubscriptionId = createResult.subscription_id;
|
|
75
|
+
data.serverSubscriptionSecret = createResult.secret;
|
|
76
|
+
// throw new BadRequestException("fail purposely")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async beforeUpdate(
|
|
80
|
+
appuser: UserContext,
|
|
81
|
+
id: string,
|
|
82
|
+
prevdata: types.Webhook,
|
|
83
|
+
newdata: types.Webhook,
|
|
84
|
+
) {
|
|
85
|
+
|
|
86
|
+
if(!prevdata.serverSubscriptionId){
|
|
87
|
+
const createResult = await this.addRemoteWebhook(appuser, newdata);
|
|
88
|
+
if (!createResult['subscription_id'])
|
|
89
|
+
throw new InternalServerErrorException(
|
|
90
|
+
'syncronize webhook server failed',
|
|
91
|
+
);
|
|
92
|
+
newdata.serverSubscriptionId = createResult.subscription_id;
|
|
93
|
+
newdata.serverSubscriptionSecret = createResult.secret;
|
|
94
|
+
}else{
|
|
95
|
+
await this.updateRemoteWebhook(appuser,newdata)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async afterDelete(
|
|
100
|
+
appuser: UserContext,
|
|
101
|
+
result: types.DeleteResultType<types.Webhook>,
|
|
102
|
+
id: string,
|
|
103
|
+
) {
|
|
104
|
+
await this.removeRemoteWebhook(appuser,result,id)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async removeRemoteWebhook(
|
|
108
|
+
appuser: UserContext,
|
|
109
|
+
result: types.DeleteResultType<types.Webhook>,
|
|
110
|
+
id: string,
|
|
111
|
+
){
|
|
112
|
+
const options = {
|
|
113
|
+
method: 'DELETE',
|
|
114
|
+
headers: {Authorization: this.webhookApiKey}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
const subscriptionId=result.data.serverSubscriptionId
|
|
119
|
+
if(!subscriptionId)return
|
|
120
|
+
|
|
121
|
+
try{
|
|
122
|
+
const res = await fetch(
|
|
123
|
+
`${this.webhooksubscribtionurl}/${subscriptionId}?application_id=${this.webhookAppId}`,
|
|
124
|
+
options)
|
|
125
|
+
}catch(e){
|
|
126
|
+
throw new InternalServerErrorException(e)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
async addRemoteWebhook(appuser: UserContext, data: types.Webhook) {
|
|
131
|
+
const headers = {};
|
|
132
|
+
data.headers.forEach((h) => {
|
|
133
|
+
headers[h.name] = h.value;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const options = {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {
|
|
139
|
+
Authorization: this.webhookApiKey,
|
|
140
|
+
accept: 'application/json',
|
|
141
|
+
'content-type': 'application/json',
|
|
142
|
+
},
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
application_id: this.webhookAppId,
|
|
145
|
+
description: data.title,
|
|
146
|
+
metadata: {
|
|
147
|
+
tenantId: data.tenantId.toString(),
|
|
148
|
+
creator: appuser.getUname(),
|
|
149
|
+
},
|
|
150
|
+
is_enabled: data.active,
|
|
151
|
+
event_types: data.eventTypes.map(
|
|
152
|
+
(item) => this.webhookprefix + item,
|
|
153
|
+
),
|
|
154
|
+
label_key: 'tenantId',
|
|
155
|
+
label_value: data.tenantId.toString(),
|
|
156
|
+
target: {
|
|
157
|
+
headers: headers,
|
|
158
|
+
type: 'http',
|
|
159
|
+
method: data.requestMethod.toUpperCase(),
|
|
160
|
+
url: data.url,
|
|
161
|
+
},
|
|
162
|
+
}),
|
|
163
|
+
};
|
|
164
|
+
try {
|
|
165
|
+
const res = await fetch(this.webhooksubscribtionurl, options);
|
|
166
|
+
return await res.json();
|
|
167
|
+
if (res.status >= 300) {
|
|
168
|
+
this.logger.error(res.statusText, 'create webhook failed');
|
|
169
|
+
throw new InternalServerErrorException('create webhook failed');
|
|
170
|
+
}
|
|
171
|
+
} catch (e) {
|
|
172
|
+
throw new InternalServerErrorException(e);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async updateRemoteWebhook(appuser: UserContext, data: types.Webhook) {
|
|
177
|
+
const headers = {};
|
|
178
|
+
data.headers.forEach((h) => {
|
|
179
|
+
headers[h.name] = h.value;
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const options = {
|
|
183
|
+
method: 'PUT',
|
|
184
|
+
headers: {
|
|
185
|
+
Authorization: this.webhookApiKey,
|
|
186
|
+
accept: 'application/json',
|
|
187
|
+
'content-type': 'application/json',
|
|
188
|
+
},
|
|
189
|
+
body: JSON.stringify({
|
|
190
|
+
application_id: this.webhookAppId,
|
|
191
|
+
description: data.title,
|
|
192
|
+
metadata: {
|
|
193
|
+
tenantId: data.tenantId.toString(),
|
|
194
|
+
creator: appuser.getUname(),
|
|
195
|
+
},
|
|
196
|
+
is_enabled: data.active,
|
|
197
|
+
event_types: data.eventTypes.map(
|
|
198
|
+
(item) => this.webhookprefix + item,
|
|
199
|
+
),
|
|
200
|
+
label_key: 'tenantId',
|
|
201
|
+
label_value: data.tenantId.toString(),
|
|
202
|
+
target: {
|
|
203
|
+
headers: headers,
|
|
204
|
+
type: 'http',
|
|
205
|
+
method: data.requestMethod.toUpperCase(),
|
|
206
|
+
url: data.url,
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
};
|
|
210
|
+
try {
|
|
211
|
+
const subscriptionId = data.serverSubscriptionId
|
|
212
|
+
const res = await fetch(`${this.webhooksubscribtionurl}/${subscriptionId}`, options);
|
|
213
|
+
return await res.json();
|
|
214
|
+
if (res.status >= 300) {
|
|
215
|
+
this.logger.error(res.statusText, 'updateRemoteWebhook webhook failed');
|
|
216
|
+
throw new InternalServerErrorException('update webhook failed');
|
|
217
|
+
}
|
|
218
|
+
} catch (e) {
|
|
219
|
+
throw new InternalServerErrorException(e);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/***************************** additional execute *****************************************/
|
|
224
|
+
}
|
|
@@ -67,7 +67,6 @@ export class ProfileController {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
71
70
|
@Get('session')
|
|
72
71
|
@Roles(Role.Everyone, Role.User)
|
|
73
72
|
@ApiOperation({
|
|
@@ -80,15 +79,15 @@ export class ProfileController {
|
|
|
80
79
|
description: 'Success',
|
|
81
80
|
})
|
|
82
81
|
@ApiResponse({ status: 401, type: Object, description: 'Expired' })
|
|
83
|
-
async getSession(@AppUser() appuser: UserContext) {
|
|
84
|
-
const result = await this.profileservice.getSession(appuser);
|
|
82
|
+
async getSession(@AppUser() appuser: UserContext) {
|
|
83
|
+
const result = await this.profileservice.getSession(appuser);
|
|
85
84
|
if (result) {
|
|
86
85
|
return result;
|
|
87
86
|
} else {
|
|
88
87
|
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
|
-
|
|
90
|
+
|
|
92
91
|
@Get('/tenants')
|
|
93
92
|
@Roles(Role.Everyone, Role.User)
|
|
94
93
|
@ApiOperation({
|
|
@@ -127,9 +126,16 @@ export class ProfileController {
|
|
|
127
126
|
@AppUser() appuser: UserContext,
|
|
128
127
|
@Body('tenantName') tenantName: string,
|
|
129
128
|
@Body('timeZone') timeZone: string,
|
|
130
|
-
@Body('utcOffset') utcOffset:number
|
|
129
|
+
@Body('utcOffset') utcOffset: number,
|
|
130
|
+
@Body('businessType') businessType: string,
|
|
131
131
|
) {
|
|
132
|
-
const result = await this.profileservice.createTenant(
|
|
132
|
+
const result = await this.profileservice.createTenant(
|
|
133
|
+
appuser,
|
|
134
|
+
tenantName,
|
|
135
|
+
timeZone,
|
|
136
|
+
utcOffset,
|
|
137
|
+
businessType,
|
|
138
|
+
);
|
|
133
139
|
if (result) {
|
|
134
140
|
return result;
|
|
135
141
|
} else {
|
|
@@ -170,9 +176,11 @@ export class ProfileController {
|
|
|
170
176
|
async runTourComplete(
|
|
171
177
|
@AppUser() appuser: UserContext,
|
|
172
178
|
@Param('guidename') guidename: string,
|
|
173
|
-
|
|
174
179
|
) {
|
|
175
|
-
const result = await this.profileservice.runTourComplete(
|
|
180
|
+
const result = await this.profileservice.runTourComplete(
|
|
181
|
+
appuser,
|
|
182
|
+
guidename,
|
|
183
|
+
);
|
|
176
184
|
if (result) {
|
|
177
185
|
return result;
|
|
178
186
|
} else {
|
|
@@ -92,6 +92,7 @@ export class ProfileService {
|
|
|
92
92
|
tenantName: string,
|
|
93
93
|
timeZone: string,
|
|
94
94
|
utcOffset: number,
|
|
95
|
+
businessType: string,
|
|
95
96
|
) {
|
|
96
97
|
// try{
|
|
97
98
|
const timezonedata = countrytimezone.getCountriesForTimezone(timeZone)[0];
|
|
@@ -103,10 +104,11 @@ export class ProfileService {
|
|
|
103
104
|
const tenantdata: Tenant = {
|
|
104
105
|
tenantId: 1,
|
|
105
106
|
tenantName: tenantName,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
businessType: businessType,
|
|
108
|
+
clientSetting: {
|
|
109
|
+
auditTrail: false,
|
|
110
|
+
webhook: false,
|
|
111
|
+
support: false,
|
|
110
112
|
},
|
|
111
113
|
active: true,
|
|
112
114
|
owner: {
|
|
@@ -1,129 +1,132 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
:events="allevents"
|
|
16
|
-
@cell-focus="chooseDate"
|
|
17
|
-
xsmall
|
|
18
|
-
>
|
|
19
|
-
<template #today-button>
|
|
20
|
-
<!-- Using Vuetify (but we prefer Wave UI 🤘) -->
|
|
21
|
-
<div @click="chooseDate(new Date(), true)">{{ t("today") }}</div>
|
|
22
|
-
</template>
|
|
23
|
-
<template #cell-content="{ cell, events }">
|
|
24
|
-
<div>
|
|
25
|
-
<div>
|
|
26
|
-
<s
|
|
27
|
-
v-if="isHoliday(cell.formattedDate)"
|
|
28
|
-
v-tooltip="getHolidayName(new Date(cell.formattedDate))"
|
|
29
|
-
class="text text-red-400 dark:text-red-400 font-bold"
|
|
30
|
-
>{{ cell.content }}</s
|
|
31
|
-
>
|
|
32
|
-
<div v-else-if="isOffDay(cell)" class="text-gray-400">
|
|
33
|
-
<s v-tooltip="t('offDay')">{{ cell.content }}</s>
|
|
34
|
-
</div>
|
|
35
|
-
<span v-else>{{ cell.content }} </span>
|
|
36
|
-
</div>
|
|
1
|
+
<template>
|
|
2
|
+
<Calendar
|
|
3
|
+
v-model="selectedDate"
|
|
4
|
+
inline
|
|
5
|
+
@update:modelValue="chooseDate"
|
|
6
|
+
:pt="{root:{class:'w-full'}}"
|
|
7
|
+
@month-change="viewChange"
|
|
8
|
+
@year-change="viewChange"
|
|
9
|
+
class="smallcalendar">
|
|
10
|
+
<template #footer>
|
|
11
|
+
<div class="p-2 flex flex-row justify-between">
|
|
12
|
+
<ButtonPrimary @click="goToday()">{{ t('today') }}</ButtonPrimary>
|
|
13
|
+
<TextSubsubtitle class="text-right"
|
|
14
|
+
>{{ items.length }} {{ t("records") }}</TextSubsubtitle>
|
|
37
15
|
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
<template #date="{date}">
|
|
19
|
+
<div class="flex flex-col text-center" >
|
|
20
|
+
<s v-if="isHoliday(date)" class="text-red-600">
|
|
21
|
+
{{ date.day }}
|
|
22
|
+
</s>
|
|
23
|
+
<span v-else-if="isOffDay(date)" class="text-gray-400">
|
|
24
|
+
{{ date.day }}
|
|
25
|
+
</span>
|
|
26
|
+
<template v-else>
|
|
27
|
+
{{ date.day }}
|
|
28
|
+
</template>
|
|
40
29
|
<Badge
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
(
|
|
44
|
-
"
|
|
45
|
-
severity="info"
|
|
46
|
-
:value="events.length"
|
|
30
|
+
v-if="getEventQty(date) > 0"
|
|
31
|
+
severity="info"
|
|
32
|
+
:value="getEventQty(date)"
|
|
47
33
|
/>
|
|
48
|
-
</slot>
|
|
49
34
|
</div>
|
|
50
|
-
</div>
|
|
51
35
|
</template>
|
|
52
|
-
|
|
53
|
-
</ClientOnly>
|
|
36
|
+
</Calendar>
|
|
54
37
|
</template>
|
|
55
|
-
<script lang="ts"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
* IT IS NOT CHANGABLE
|
|
59
|
-
* last change 2024-02-22
|
|
60
|
-
* author: Ks Tan
|
|
61
|
-
*/
|
|
62
|
-
//, { Event, SplitDaysAttributes }
|
|
63
|
-
import VueCal from "vue-cal";
|
|
64
|
-
import "vue-cal/dist/vuecal.css";
|
|
38
|
+
<script setup lang="ts" generic="T">
|
|
39
|
+
import { CalendarDateSlotOptions,CalendarMonthChangeEvent } from "primevue/calendar";
|
|
40
|
+
|
|
65
41
|
import {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
42
|
+
CalEventType,
|
|
43
|
+
CalRightClickEvent,
|
|
44
|
+
OffDay,
|
|
45
|
+
CalViewChange,
|
|
70
46
|
} from "~/types";
|
|
71
|
-
|
|
47
|
+
|
|
72
48
|
const props = defineProps<{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
49
|
+
id: string;
|
|
50
|
+
items: CalEventType<T>[];
|
|
51
|
+
holidays: OffDay[];
|
|
76
52
|
}>();
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
53
|
+
const emits = defineEmits(["chooseDate", "viewChange"]);
|
|
54
|
+
|
|
55
|
+
|
|
80
56
|
const selectedDate = defineModel<Date>({ required: true });
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (item.end instanceof Date)
|
|
91
|
-
item.end = item.end.format("YYYY-MM-DD HH:mm");
|
|
92
|
-
else if (typeof item.end == "string") {
|
|
93
|
-
item.end = item.end.substring(0, 16).replace("T", " ");
|
|
94
|
-
}
|
|
95
|
-
return item;
|
|
96
|
-
});
|
|
97
|
-
return list;
|
|
98
|
-
});
|
|
99
|
-
const viewChange = (event: CalViewChange) => {
|
|
100
|
-
viewStatus.value = event;
|
|
101
|
-
emits('viewChange',event)
|
|
102
|
-
};
|
|
57
|
+
const offdays = ref<string[]>([]);
|
|
58
|
+
type DateType = {
|
|
59
|
+
day: number
|
|
60
|
+
month : number
|
|
61
|
+
otherMonth: boolean
|
|
62
|
+
selectable : boolean
|
|
63
|
+
today : boolean
|
|
64
|
+
year: number
|
|
65
|
+
}
|
|
103
66
|
|
|
104
|
-
const
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
67
|
+
const disableDays=computed(()=>{
|
|
68
|
+
return offdays.value.map(item=>{
|
|
69
|
+
if(item=='sun')return 0
|
|
70
|
+
else if(item=='mon')return 1
|
|
71
|
+
else if(item=='tue')return 2
|
|
72
|
+
else if(item=='wed')return 3
|
|
73
|
+
else if(item=='thu')return 4
|
|
74
|
+
else if(item=='fri')return 5
|
|
75
|
+
else if(item=='sat')return 6
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
function isHoliday(date:CalendarDateSlotOptions){
|
|
80
|
+
|
|
81
|
+
for(let i = 0 ; i<props.holidays.length;i++){
|
|
82
|
+
const item = props.holidays[i]
|
|
83
|
+
const currenyday = getDayJs()(item.date).date()
|
|
84
|
+
const currentmonth = getDayJs()(item.date).month()
|
|
85
|
+
const currentyear = getDayJs()(item.date).year()
|
|
86
|
+
if(currenyday==date.day && currentmonth==date.month && currentyear==date.year){
|
|
87
|
+
return true
|
|
88
|
+
}
|
|
120
89
|
}
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
function goToday(){
|
|
93
|
+
selectedDate.value= new Date(today())
|
|
94
|
+
chooseDate(new Date(today()))
|
|
95
|
+
}
|
|
96
|
+
function chooseDate(date: string | string[] | Date | Date[] | undefined){
|
|
97
|
+
emits('chooseDate',date)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const isOffDay = (date:CalendarDateSlotOptions) => {
|
|
101
|
+
const dayname: string = new Date(date.year,date.month, date.day)
|
|
102
|
+
|
|
103
|
+
.toLocaleString("en", { weekday: "short" })
|
|
104
|
+
.toLowerCase();
|
|
105
|
+
if (offdays.value.includes(dayname)) return true;
|
|
106
|
+
else return false;
|
|
121
107
|
};
|
|
122
|
-
|
|
123
|
-
|
|
108
|
+
|
|
109
|
+
const getEventQty = (date:CalendarDateSlotOptions)=>{
|
|
110
|
+
const checkdate = dateToISOWithoutConvert(new Date(date.year,date.month, date.day)).substring(0,10)
|
|
111
|
+
const recordlength = props.items.filter(item=>item.start==checkdate).length
|
|
112
|
+
return recordlength
|
|
113
|
+
}
|
|
114
|
+
const viewChange = (event: CalendarMonthChangeEvent) => {
|
|
115
|
+
emits("viewChange", event);
|
|
124
116
|
};
|
|
125
117
|
|
|
118
|
+
|
|
126
119
|
onMounted(() => {
|
|
127
|
-
|
|
120
|
+
offdays.value = getCurrentBranch()?.branch.offdays ?? [];
|
|
128
121
|
});
|
|
129
122
|
</script>
|
|
123
|
+
<style >
|
|
124
|
+
.smallcalendar td {
|
|
125
|
+
height: 3rem;
|
|
126
|
+
border: solid 1px #ccc;
|
|
127
|
+
}
|
|
128
|
+
.smallcalendar .p-datepicker table td > span {
|
|
129
|
+
widows: initial !important;
|
|
130
|
+
height: initial !important;
|
|
131
|
+
}
|
|
132
|
+
</style>
|