@simitgroup/simpleapp-generator 1.6.4-e-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/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/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/processors/simpleapp.processor.ts.eta +4 -6
- package/templates/nest/src/simpleapp/generate/processors/webhook.processor.ts.eta +224 -0
- 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
|
@@ -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
|
+
}
|
|
@@ -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>
|
|
@@ -1,23 +1,57 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<ImageToBase64Uploader
|
|
3
|
+
v-if="changable"
|
|
4
|
+
#default
|
|
5
|
+
:class="`w-${sizenumber} h-${sizenumber} place-content-center bg-white`"
|
|
6
|
+
@image-uploaded="handleBase64"
|
|
7
|
+
>
|
|
8
|
+
<NuxtImg
|
|
6
9
|
class="w-full h-full"
|
|
10
|
+
:key="imageKey"
|
|
11
|
+
:src="imagepath"
|
|
7
12
|
/>
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
</ImageToBase64Uploader>
|
|
14
|
+
<div
|
|
15
|
+
v-else
|
|
16
|
+
:class="`inline-block border rounded-lg w-${sizenumber} h-${sizenumber} bg-white text-black`"
|
|
17
|
+
>
|
|
18
|
+
<NuxtImg class="w-full h-full" :src="imagepath" />
|
|
10
19
|
</div>
|
|
11
20
|
</template>
|
|
12
21
|
<script lang="ts" setup>
|
|
13
|
-
|
|
14
|
-
* This file was automatically generated by simpleapp generator during initialization.
|
|
15
|
-
* --remove-this-line-to-prevent-override--
|
|
16
|
-
* last change 2024-04-06
|
|
17
|
-
* author: Ks Tan
|
|
18
|
-
*/
|
|
22
|
+
// import {KeyValue} from ''
|
|
19
23
|
const props = defineProps<{
|
|
20
|
-
|
|
24
|
+
changable?: boolean;
|
|
25
|
+
uid?: string;
|
|
21
26
|
size: number;
|
|
22
27
|
}>();
|
|
28
|
+
const imageKey = ref(0);
|
|
29
|
+
const uid = computed(
|
|
30
|
+
() => props.uid ?? getUserProfile()?.uid,
|
|
31
|
+
);
|
|
32
|
+
// const xorgpath = getCurrentXorg() ? `${getCurrentXorg()}/` : "MC0wLTA/";
|
|
33
|
+
|
|
34
|
+
const sizenumber = props.size ?? 16;
|
|
35
|
+
const imagepath = getAvatarByUid(uid.value,sizenumber) //`${xorgpath}images/organization/${orgRecordId.value}`;
|
|
36
|
+
const imageData = ref("");
|
|
37
|
+
watch(
|
|
38
|
+
uid,
|
|
39
|
+
() => imageKey.value++,
|
|
40
|
+
);
|
|
41
|
+
const handleBase64 = async (data: string) => {
|
|
42
|
+
// const keyvalue = {
|
|
43
|
+
// key: "org-" + props.orgRecordId,
|
|
44
|
+
// value: data,
|
|
45
|
+
// };
|
|
46
|
+
// console.log("upload logo ", data);
|
|
47
|
+
// const uploadok = await useNuxtApp()
|
|
48
|
+
// .$OrganizationDoc()
|
|
49
|
+
// .getApi()
|
|
50
|
+
// .runUploadlogo(keyvalue);
|
|
51
|
+
// if (uploadok) {
|
|
52
|
+
// const realpath = `/api/${imagepath}`;
|
|
53
|
+
// await fetch(realpath, { cache: "reload", credentials: "include" });
|
|
54
|
+
// imageKey.value++;
|
|
55
|
+
// }
|
|
56
|
+
};
|
|
23
57
|
</script>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div
|
|
3
3
|
@click="openUploadDialog"
|
|
4
4
|
:title="selectedBase64Img"
|
|
5
|
-
class="
|
|
5
|
+
class="place-content-center image-to-base64-uploader rounded-lg border block"
|
|
6
6
|
>
|
|
7
7
|
<ClientOnly>
|
|
8
8
|
<slot name="default">
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
</slot>
|
|
12
12
|
|
|
13
13
|
<Dialog
|
|
14
|
-
v-if="dialogVisible"
|
|
14
|
+
v-if="dialogVisible" modal
|
|
15
15
|
v-model:visible="dialogVisible"
|
|
16
16
|
header="Image Upload"
|
|
17
|
-
:pt="{ root: { class: 'w-
|
|
17
|
+
:pt="{ root: { class: 'w-11/12' } }"
|
|
18
18
|
>
|
|
19
19
|
<div class="w-full grid grid-cols-2 gap-2">
|
|
20
20
|
<div class="w-7/8 border rounded p-4">
|
|
@@ -96,8 +96,8 @@ const handleImageUpload = (event) => {
|
|
|
96
96
|
reader.onload = (e) => {
|
|
97
97
|
const img = new Image();
|
|
98
98
|
img.onload = () => {
|
|
99
|
-
const maxWidth =
|
|
100
|
-
const maxHeight =
|
|
99
|
+
const maxWidth = 800; // Set your desired maximum width
|
|
100
|
+
const maxHeight = 600; // Set your desired maximum height
|
|
101
101
|
const scale = Math.min(maxWidth / img.width, maxHeight / img.height);
|
|
102
102
|
const scaledWidth = img.width * scale;
|
|
103
103
|
const scaledHeight = img.height * scale;
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
class="flex flex-row text-xs cursor-pointer justify-end
|
|
3
|
+
class="flex flex-row text-xs cursor-pointer justify-end"
|
|
4
4
|
v-if="data?.updated && data?.updated != ''"
|
|
5
5
|
@click="viewHistories"
|
|
6
6
|
>
|
|
7
|
-
<ImageAvatar
|
|
7
|
+
<ImageAvatar
|
|
8
8
|
v-if="data?.updatedBy"
|
|
9
9
|
:id="data.updatedBy"
|
|
10
|
-
:size="
|
|
10
|
+
:size="36"
|
|
11
11
|
></ImageAvatar>
|
|
12
12
|
<div class="flex flex-col flex-1">
|
|
13
|
-
<TextDocStatus
|
|
13
|
+
<TextDocStatus
|
|
14
|
+
v-if="data?.documentStatus"
|
|
15
|
+
:docStatus="data?.documentStatus"
|
|
16
|
+
/>
|
|
14
17
|
<!-- <TextSubsubtitle class="text-gray-400 italic"
|
|
15
18
|
>{{ t("updated") }}:</TextSubsubtitle
|
|
16
19
|
> -->
|
|
@@ -26,7 +29,7 @@
|
|
|
26
29
|
<Timeline :value="events" class="w-full md:w-20rem">
|
|
27
30
|
<template #opposite="{ item }">
|
|
28
31
|
<div class="flex flex-row">
|
|
29
|
-
<ImageAvatar :email="item.email" :id="item.uid"
|
|
32
|
+
<ImageAvatar :email="item.email" :id="item.uid" />
|
|
30
33
|
<div class="flex flex-col">
|
|
31
34
|
<span>{{ item.fullName }}</span>
|
|
32
35
|
<RendererDateAge
|