@yomotech/view-toolkit 0.0.32 → 0.0.34
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/fesm2022/yomotech-view-toolkit.mjs +3593 -0
- package/fesm2022/yomotech-view-toolkit.mjs.map +1 -0
- package/package.json +49 -38
- package/types/yomotech-view-toolkit.d.ts +648 -0
- package/ng-package.json +0 -7
- package/src/lib/app-version.ts +0 -2
- package/src/lib/components/autocomplete/autocomplete.css +0 -0
- package/src/lib/components/autocomplete/autocomplete.html +0 -23
- package/src/lib/components/autocomplete/autocomplete.ts +0 -71
- package/src/lib/components/button/button.css +0 -0
- package/src/lib/components/button/button.html +0 -1
- package/src/lib/components/button/button.ts +0 -11
- package/src/lib/components/date/date.css +0 -0
- package/src/lib/components/date/date.html +0 -1
- package/src/lib/components/date/date.ts +0 -11
- package/src/lib/components/dropdown/dropdown.css +0 -0
- package/src/lib/components/dropdown/dropdown.html +0 -1
- package/src/lib/components/dropdown/dropdown.ts +0 -11
- package/src/lib/components/error-message/error-message.css +0 -0
- package/src/lib/components/error-message/error-message.html +0 -1
- package/src/lib/components/error-message/error-message.ts +0 -11
- package/src/lib/components/label/label.css +0 -0
- package/src/lib/components/label/label.html +0 -7
- package/src/lib/components/label/label.ts +0 -33
- package/src/lib/components/string/string.css +0 -0
- package/src/lib/components/string/string.html +0 -4
- package/src/lib/components/string/string.ts +0 -22
- package/src/lib/components/textbox/textbox.css +0 -0
- package/src/lib/components/textbox/textbox.html +0 -7
- package/src/lib/components/textbox/textbox.ts +0 -33
- package/src/lib/components/time/time.css +0 -0
- package/src/lib/components/time/time.html +0 -1
- package/src/lib/components/time/time.ts +0 -11
- package/src/lib/containers/card/card.component.css +0 -0
- package/src/lib/containers/card/card.component.html +0 -450
- package/src/lib/containers/card/card.component.ts +0 -474
- package/src/lib/containers/form/form.component.css +0 -101
- package/src/lib/containers/form/form.component.html +0 -305
- package/src/lib/containers/form/form.component.ts +0 -333
- package/src/lib/containers/grid/grid.component.css +0 -0
- package/src/lib/containers/grid/grid.component.html +0 -212
- package/src/lib/containers/grid/grid.component.ts +0 -228
- package/src/lib/containers/header-menu/header-menu.component.css +0 -0
- package/src/lib/containers/header-menu/header-menu.component.html +0 -72
- package/src/lib/containers/header-menu/header-menu.component.ts +0 -105
- package/src/lib/containers/logs/logs.component.css +0 -160
- package/src/lib/containers/logs/logs.component.html +0 -89
- package/src/lib/containers/logs/logs.component.ts +0 -29
- package/src/lib/containers/model/model.component.css +0 -0
- package/src/lib/containers/model/model.component.html +0 -351
- package/src/lib/containers/model/model.component.ts +0 -436
- package/src/lib/containers/pagination/pagination.component.css +0 -0
- package/src/lib/containers/pagination/pagination.component.html +0 -41
- package/src/lib/containers/pagination/pagination.component.ts +0 -100
- package/src/lib/containers/side-menu/side-menu.component.css +0 -173
- package/src/lib/containers/side-menu/side-menu.component.html +0 -126
- package/src/lib/containers/side-menu/side-menu.component.ts +0 -458
- package/src/lib/services/app-version-reset.service.ts +0 -59
- package/src/lib/services/config.service.ts +0 -144
- package/src/lib/services/couchdb.ts +0 -275
- package/src/lib/services/mobile-keycloak.service.ts +0 -116
- package/src/lib/services/network-log.service.ts +0 -27
- package/src/lib/services/notification.service.ts +0 -26
- package/src/lib/services/request.service.ts +0 -125
- package/src/lib/services/utility.service.ts +0 -600
- package/src/lib/view-toolkit.module.ts +0 -57
- package/src/lib/view-toolkit.spec.ts +0 -23
- package/src/lib/view-toolkit.ts +0 -15
- package/src/public-api.ts +0 -25
- package/tsconfig.lib.json +0 -17
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -15
|
@@ -1,600 +0,0 @@
|
|
|
1
|
-
import { Platform } from '@angular/cdk/platform';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { Preferences } from '@capacitor/preferences';
|
|
4
|
-
import { RequestService } from './request.service';
|
|
5
|
-
import { loadStripe } from '@stripe/stripe-js';
|
|
6
|
-
import { lastValueFrom } from 'rxjs';
|
|
7
|
-
|
|
8
|
-
@Injectable({
|
|
9
|
-
providedIn: 'root'
|
|
10
|
-
})
|
|
11
|
-
export class UtilityService {
|
|
12
|
-
stripe: any = null;
|
|
13
|
-
|
|
14
|
-
constructor(private platform: Platform,
|
|
15
|
-
private requestService: RequestService) { }
|
|
16
|
-
|
|
17
|
-
getScope(scope: any) {
|
|
18
|
-
let propertyScope = "";
|
|
19
|
-
let start = scope?.indexOf("#/") + 2;
|
|
20
|
-
let end = scope?.indexOf("/", start);
|
|
21
|
-
if (start && end) {
|
|
22
|
-
propertyScope = scope.substring(start, end);
|
|
23
|
-
}
|
|
24
|
-
return propertyScope;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getProperty(scope: any, itemInfo?: any) {
|
|
28
|
-
const property = scope?.reference ? scope?.reference.split('/').pop() : '';
|
|
29
|
-
return { key: property, productSchema: itemInfo.propertySchema[property] };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async setStorage(key: string, value: any) {
|
|
33
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
34
|
-
await Preferences.set({ key, value });
|
|
35
|
-
} else {
|
|
36
|
-
sessionStorage.setItem(key, value);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async getStorage(key: string) {
|
|
41
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
42
|
-
const { value } = await Preferences.get({ key });
|
|
43
|
-
return value;
|
|
44
|
-
} else {
|
|
45
|
-
const storage = sessionStorage.getItem(key);
|
|
46
|
-
return storage;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async setLocalStorage(key: string, value: any) {
|
|
51
|
-
const stringValue = JSON.stringify(value);
|
|
52
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
53
|
-
await Preferences.set({ key, value: stringValue });
|
|
54
|
-
} else {
|
|
55
|
-
localStorage.setItem(key, stringValue);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async removeLocalStorage(keyName: string) {
|
|
60
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
61
|
-
await Preferences.remove({ key: keyName });
|
|
62
|
-
} else {
|
|
63
|
-
localStorage.removeItem(keyName);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async removeStorage(key: string) {
|
|
68
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
69
|
-
await Preferences.remove({ key });
|
|
70
|
-
} else {
|
|
71
|
-
sessionStorage.removeItem(key);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async getLocalStorage<T = unknown>(key: string) {
|
|
76
|
-
if ((this.platform.ANDROID || this.platform.IOS) && !this.platform?.isBrowser) {
|
|
77
|
-
const { value } = await Preferences.get({ key });
|
|
78
|
-
return value ? JSON.parse(value) : null;
|
|
79
|
-
} else {
|
|
80
|
-
const value = localStorage.getItem(key);
|
|
81
|
-
|
|
82
|
-
if (value === null) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
return JSON.parse(value) as T;
|
|
88
|
-
} catch {
|
|
89
|
-
return value;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async showAllProjects() {
|
|
95
|
-
await this.removeStorage('selectedProject');
|
|
96
|
-
window.location.reload();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
parseBodyObject(obj: any): any {
|
|
100
|
-
const jsonString = JSON.stringify(obj);
|
|
101
|
-
const replacedString = jsonString.replace(/{{(.*?)}}/g, (match, expression) => {
|
|
102
|
-
try {
|
|
103
|
-
return new Function(`return ${expression.trim()};`).call(this);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(`Error evaluating expression: ${expression}`, error);
|
|
106
|
-
return match;
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
return JSON.parse(replacedString);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
getTotalPrice(tableitemInfo: any): number {
|
|
113
|
-
const total = tableitemInfo.data.reduce((total: any, item: any) => {
|
|
114
|
-
if (item.quantity && !isNaN(item.quantity)) {
|
|
115
|
-
return total + (item.unitPrice * item.quantity);
|
|
116
|
-
}
|
|
117
|
-
return total;
|
|
118
|
-
}, 0);
|
|
119
|
-
return total.toFixed(2);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
getTotalQuantity(tableitemInfo: any) {
|
|
123
|
-
let quantity = 0;
|
|
124
|
-
tableitemInfo.data.forEach((cartItem: any) => {
|
|
125
|
-
if (cartItem.quantity) {
|
|
126
|
-
quantity = cartItem.quantity + quantity;
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
return quantity;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
replacePaginationParams(url: string, currentPage: number, pageSize: number): string {
|
|
133
|
-
if (url && url.includes('{{pageNumber}}')) {
|
|
134
|
-
url = url.replace(/{{pageNumber}}/g, currentPage.toString());
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (url && url.includes('{{pageSize}}') && pageSize !== undefined) {
|
|
138
|
-
url = url.replace(/{{pageSize}}/g, pageSize.toString());
|
|
139
|
-
}
|
|
140
|
-
return url;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
customButton(option: any, propertySchema: any, projectSeleted: any, environment: any) {
|
|
144
|
-
if (option.url) {
|
|
145
|
-
let body = {}
|
|
146
|
-
if (option.propertyKey) {
|
|
147
|
-
body = Object.keys(propertySchema[option.propertyKey]).reduce((acc, key) => {
|
|
148
|
-
acc[key] = propertySchema[option.propertyKey][key]?.value;
|
|
149
|
-
return acc;
|
|
150
|
-
}, {} as Record<string, string>);
|
|
151
|
-
}
|
|
152
|
-
let url = environment?.apiUrl + option.url;
|
|
153
|
-
this.requestService.dynamicCall(option.method, body, url, option.passToken, projectSeleted).subscribe((res) => {
|
|
154
|
-
window.location.reload();
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
setDefaultUser(item: any, userInfo: any, environment: any) {
|
|
160
|
-
let schema: any = item;
|
|
161
|
-
let role = "default";
|
|
162
|
-
if (environment?.login?.type === "keycloak") {
|
|
163
|
-
if (userInfo?.name && item.options?.userRoleMapping) {
|
|
164
|
-
schema = item.options[item.options?.userRoleMapping[role]];
|
|
165
|
-
}
|
|
166
|
-
} else if (environment?.login?.type === "jwtToken") {
|
|
167
|
-
if (item.options?.loginResponse && item.options?.loginResponse.storageType == "sessionStorage") {
|
|
168
|
-
if (userInfo) {
|
|
169
|
-
role = userInfo[item.options?.loginResponse.role]?.toLowerCase();
|
|
170
|
-
}
|
|
171
|
-
schema = item.options[item.options?.userRoleMapping[role]];
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return schema;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
setTableData(data: any, options: any = {}, tableitemInfo: any, projectSeleted: any) {
|
|
178
|
-
if (options?.pagination?.pageSize && options?.pagination?.scrollable) {
|
|
179
|
-
tableitemInfo.pageSize = options?.pagination?.pageSize;
|
|
180
|
-
}
|
|
181
|
-
let records: any;
|
|
182
|
-
if (options.dataKey) {
|
|
183
|
-
records = data[options.dataKey];
|
|
184
|
-
} else if (options.key && data?._embedded) {
|
|
185
|
-
records = data?._embedded[options.key];
|
|
186
|
-
} else {
|
|
187
|
-
if (!data?._embedded?.products && !Array.isArray(data)) {
|
|
188
|
-
records = [data];
|
|
189
|
-
} else {
|
|
190
|
-
records = data?._embedded?.products;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
tableitemInfo.totalRecords = data?.totalPages ? data?.totalPages : data?.page?.totalElements;
|
|
194
|
-
tableitemInfo.data = records.map((record: any) => ({
|
|
195
|
-
...record,
|
|
196
|
-
...(record.hasOwnProperty('imageUrl') && record.imageUrl
|
|
197
|
-
? { imageUrl: `${projectSeleted}/Media/` + record.imageUrl.split('/').pop() }
|
|
198
|
-
: {})
|
|
199
|
-
}));
|
|
200
|
-
return tableitemInfo;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
setOktaWebCredential(environment: any, projectName: any) {
|
|
204
|
-
return {
|
|
205
|
-
logo: `favicon.ico`,
|
|
206
|
-
baseUrl: environment.login.web.issuer.split('/oauth2')[0],
|
|
207
|
-
clientId: environment.login.web.clientId,
|
|
208
|
-
redirectUri: environment.login.web.redirectUri,
|
|
209
|
-
authParams: {
|
|
210
|
-
pkce: true,
|
|
211
|
-
issuer: environment.login.web.issuer,
|
|
212
|
-
scopes: environment.login.web.scopes
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
setOktaMobileCredential(environment: any) {
|
|
218
|
-
return {
|
|
219
|
-
appId: environment.login.mobile.clientId,
|
|
220
|
-
authorizationBaseUrl: environment.login.mobile.authorizationBaseUrl,
|
|
221
|
-
accessTokenEndpoint: environment.login.mobile.accessTokenEndpoint,
|
|
222
|
-
redirectUrl: environment.login.mobile.redirectUrl,
|
|
223
|
-
scope: environment.login.mobile.scope,
|
|
224
|
-
responseType: environment.login.mobile.responseType,
|
|
225
|
-
pkceEnabled: environment.login.mobile.pkceEnabled
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
async setupStripePaymentForm(
|
|
231
|
-
environment: any,
|
|
232
|
-
form: any,
|
|
233
|
-
onCardChange: (message: string) => void
|
|
234
|
-
): Promise<void> {
|
|
235
|
-
let hasCreditCard = false;
|
|
236
|
-
|
|
237
|
-
if (form.layoutSchema?.formSections) {
|
|
238
|
-
form.layoutSchema.formSections.forEach((formSection: any) => {
|
|
239
|
-
if (formSection.formFields?.length > 0) {
|
|
240
|
-
const foundCreditCard = formSection.formFields.some((formField: any) => {
|
|
241
|
-
const scopeKey = this.getScope(formField.scope?.reference);
|
|
242
|
-
return form.propertySchema[scopeKey] &&
|
|
243
|
-
form.propertySchema[scopeKey][formField.scope?.reference.split('/').pop()]?.type === 'carditCard';
|
|
244
|
-
});
|
|
245
|
-
if (foundCreditCard) {
|
|
246
|
-
hasCreditCard = true;
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (hasCreditCard) {
|
|
254
|
-
this.stripe = await loadStripe(environment.stripePublishableKey);
|
|
255
|
-
const elements = this.stripe.elements();
|
|
256
|
-
const cardElement = elements.create('card', { hidePostalCode: true });
|
|
257
|
-
cardElement.mount('#card-element');
|
|
258
|
-
|
|
259
|
-
cardElement.on('change', (event: { complete: boolean, error?: { message: string } }) => {
|
|
260
|
-
if (event.complete) {
|
|
261
|
-
onCardChange('');
|
|
262
|
-
} else if (event.error) {
|
|
263
|
-
onCardChange(event.error.message);
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async formData(form: any, environment: any, cartInfo: any): Promise<void> {
|
|
270
|
-
if (form.layoutSchema?.formSections) {
|
|
271
|
-
for (const formSection of form.layoutSchema.formSections) {
|
|
272
|
-
if (formSection.formFields?.length > 0) {
|
|
273
|
-
for (const formField of formSection.formFields) {
|
|
274
|
-
const scope = this.getScope(formField.scope?.reference);
|
|
275
|
-
const fieldKey = formField.scope?.reference.split('/').pop();
|
|
276
|
-
const field = form.propertySchema?.[scope]?.[fieldKey];
|
|
277
|
-
|
|
278
|
-
if (!field) continue;
|
|
279
|
-
|
|
280
|
-
// Checkbox logic with copy action
|
|
281
|
-
if (field.type === 'checkbox' && formField.option?.innerAction?.action === 'copy') {
|
|
282
|
-
const fromSchema = form.propertySchema[formField.option.innerAction.from];
|
|
283
|
-
const toSchema = form.propertySchema[formField.option.innerAction.to];
|
|
284
|
-
const keys = Object.keys(fromSchema);
|
|
285
|
-
|
|
286
|
-
keys.forEach((key: any) => {
|
|
287
|
-
if (toSchema[key]) {
|
|
288
|
-
const sourceValue = fromSchema?.[key]?.value;
|
|
289
|
-
toSchema[key].value = sourceValue || '';
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Dropdown logic (async data fetching)
|
|
295
|
-
if (field.type === 'dropdown' && formField.option?.data_url) {
|
|
296
|
-
try {
|
|
297
|
-
const res: any = await lastValueFrom(this.requestService.getInfo(environment.apiUrl + formField.option.data_url));
|
|
298
|
-
const key = Object.keys(res._embedded || {})[0];
|
|
299
|
-
if (key) {
|
|
300
|
-
field.data = res._embedded[key];
|
|
301
|
-
}
|
|
302
|
-
} catch (err) {
|
|
303
|
-
console.error('Failed to load dropdown data', err);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Cart info logic for string fields
|
|
308
|
-
if (field.type === 'string' && formField?.option?.cartInfo) {
|
|
309
|
-
if (field.value?.toString()?.includes('{{quantity}}')) {
|
|
310
|
-
field.value = cartInfo.quantity;
|
|
311
|
-
} else if (field.value?.toString()?.includes('{{totalPrice}}')) {
|
|
312
|
-
field.value = cartInfo.totalPrice;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// async processData(
|
|
322
|
-
// data: any,
|
|
323
|
-
// options: {
|
|
324
|
-
// dataKey?: string;
|
|
325
|
-
// setImageUrl?: boolean;
|
|
326
|
-
// showTable?: boolean;
|
|
327
|
-
// projectSelected: string;
|
|
328
|
-
// },
|
|
329
|
-
// tenantName: any
|
|
330
|
-
// ): Promise<any[]> {
|
|
331
|
-
// if (options.dataKey) {
|
|
332
|
-
// data = data[options.dataKey];
|
|
333
|
-
// } else {
|
|
334
|
-
// if (!data?._embedded?.products && !Array.isArray(data)) {
|
|
335
|
-
// data = [data];
|
|
336
|
-
// } else {
|
|
337
|
-
// data = data?._embedded?.products;
|
|
338
|
-
// }
|
|
339
|
-
// }
|
|
340
|
-
// const transformed = await Promise.all(
|
|
341
|
-
// data.map(async (record: any) => {
|
|
342
|
-
// let imageUrl = record.imageUrl;
|
|
343
|
-
// const imagePath = `Media/` +
|
|
344
|
-
// record?.imageUrl?.split('/').pop();
|
|
345
|
-
// if (
|
|
346
|
-
// tenantName &&
|
|
347
|
-
// record?.imageUrl &&
|
|
348
|
-
// options.setImageUrl
|
|
349
|
-
// ) {
|
|
350
|
-
// try {
|
|
351
|
-
// imageUrl = "";
|
|
352
|
-
// imageUrl = await this.couchdbService.getFileContentFromCouchDb(
|
|
353
|
-
// `${tenantName}_${options.projectSelected}`,
|
|
354
|
-
// imagePath
|
|
355
|
-
// );
|
|
356
|
-
// } catch (err) {
|
|
357
|
-
// console.warn(`Failed to fetch image from CouchDB for ${imagePath}`, err);
|
|
358
|
-
// imageUrl = '';
|
|
359
|
-
// }
|
|
360
|
-
// }
|
|
361
|
-
// return {
|
|
362
|
-
// ...record,
|
|
363
|
-
// ...(imageUrl ? { imageUrl } : {}),
|
|
364
|
-
// ...(imagePath ? { imagePath } : {}),
|
|
365
|
-
// };
|
|
366
|
-
// })
|
|
367
|
-
// );
|
|
368
|
-
|
|
369
|
-
// return transformed;
|
|
370
|
-
// }
|
|
371
|
-
|
|
372
|
-
// async setTableDataImages(records: any, tenantName: any, projectSelected: any): Promise<any[]> {
|
|
373
|
-
// const transformed = await Promise.all(
|
|
374
|
-
// records.map(async (record: any) => {
|
|
375
|
-
// let imageUrl = record.imageUrl;
|
|
376
|
-
// const imagePath = record?.imagePath ? record?.imagePath : `Media/` +
|
|
377
|
-
// record?.imageUrl?.split('/').pop();
|
|
378
|
-
// if (
|
|
379
|
-
// tenantName &&
|
|
380
|
-
// record?.imageUrl &&
|
|
381
|
-
// record.hasOwnProperty('imageUrl')
|
|
382
|
-
// ) {
|
|
383
|
-
// try {
|
|
384
|
-
// imageUrl = "";
|
|
385
|
-
// imageUrl = await this.couchdbService.getFileContentFromCouchDb(
|
|
386
|
-
// `${tenantName}_${projectSelected}`,
|
|
387
|
-
// imagePath
|
|
388
|
-
// );
|
|
389
|
-
// } catch (err) {
|
|
390
|
-
// console.warn(`Failed to fetch image from CouchDB for ${imagePath}`, err);
|
|
391
|
-
// imageUrl = '';
|
|
392
|
-
// }
|
|
393
|
-
// }
|
|
394
|
-
// return {
|
|
395
|
-
// ...record,
|
|
396
|
-
// ...(imageUrl ? { imageUrl } : {}),
|
|
397
|
-
// };
|
|
398
|
-
// })
|
|
399
|
-
// );
|
|
400
|
-
// return transformed;
|
|
401
|
-
// }
|
|
402
|
-
|
|
403
|
-
// set date in localstorage
|
|
404
|
-
normalizeDatesForStorage(obj: any): any {
|
|
405
|
-
const normalized: any = {};
|
|
406
|
-
Object.entries(obj).forEach(([key, value]: any) => {
|
|
407
|
-
if (this.isDateLike(value)) {
|
|
408
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
409
|
-
normalized[key] = this.toLocalISOString(date);
|
|
410
|
-
} else {
|
|
411
|
-
normalized[key] = value;
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
return normalized;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
isDateLike(value: any): boolean {
|
|
419
|
-
if (!value) return false;
|
|
420
|
-
|
|
421
|
-
// Actual Date object
|
|
422
|
-
if (value instanceof Date && !isNaN(value.getTime())) {
|
|
423
|
-
return true;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// ISO string (UTC or local)
|
|
427
|
-
if (typeof value === 'string') {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
toLocalISOString(date: Date): string {
|
|
435
|
-
const tzOffset = date.getTimezoneOffset() * 60000;
|
|
436
|
-
return new Date(date.getTime() - tzOffset)
|
|
437
|
-
.toISOString()
|
|
438
|
-
.slice(0, 19);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// restore date Field from localstorage
|
|
442
|
-
restoreDatesFromStorage(records: any[], propertySchema: any): any[] {
|
|
443
|
-
if (!Array.isArray(records)) return records;
|
|
444
|
-
if (!propertySchema) return records;
|
|
445
|
-
|
|
446
|
-
return records.map(record => {
|
|
447
|
-
const restored = { ...record };
|
|
448
|
-
|
|
449
|
-
Object.keys(propertySchema).forEach(scopeKey => {
|
|
450
|
-
const schemaGroup = propertySchema[scopeKey];
|
|
451
|
-
if (!schemaGroup) return;
|
|
452
|
-
|
|
453
|
-
Object.keys(schemaGroup).forEach(fieldKey => {
|
|
454
|
-
const fieldSchema = schemaGroup[fieldKey];
|
|
455
|
-
const value = restored[fieldKey];
|
|
456
|
-
if (!value || typeof value !== 'string') return;
|
|
457
|
-
|
|
458
|
-
// ✅ DATE or TIME fields only
|
|
459
|
-
if (fieldSchema.type === 'date' || fieldSchema.type === 'time') {
|
|
460
|
-
restored[fieldKey] = this.parseLocalISODate(value);
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
return restored;
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
parseLocalISODate(value: string): Date {
|
|
470
|
-
// Remove Z to avoid UTC shift
|
|
471
|
-
const clean = value.replace('Z', '');
|
|
472
|
-
const [datePart, timePart = '00:00:00.000'] = clean.split('T');
|
|
473
|
-
|
|
474
|
-
const [y, m, d] = datePart.split('-').map(Number);
|
|
475
|
-
const [hh = 0, mm = 0, ss = 0, ms = 0] =
|
|
476
|
-
timePart.split(/[:.]/).map(Number);
|
|
477
|
-
|
|
478
|
-
return new Date(y, m - 1, d, hh, mm, ss, ms);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
// savecard conversion
|
|
482
|
-
convertToDailyLogs(cardOrCards: any | any[]): any[] {
|
|
483
|
-
// Normalize input to array
|
|
484
|
-
const cards = Array.isArray(cardOrCards) ? cardOrCards : [cardOrCards];
|
|
485
|
-
|
|
486
|
-
const results: any[] = [];
|
|
487
|
-
|
|
488
|
-
for (const card of cards) {
|
|
489
|
-
|
|
490
|
-
const fromDate = new Date(card.fromDate);
|
|
491
|
-
const toDate = new Date(card.toDate);
|
|
492
|
-
|
|
493
|
-
const fromTime = new Date(card.workDayTimeFrom);
|
|
494
|
-
const toTime = new Date(card.workDayTimeTo);
|
|
495
|
-
|
|
496
|
-
// Normalize dates to midnight
|
|
497
|
-
const startDay = new Date(fromDate);
|
|
498
|
-
startDay.setHours(0, 0, 0, 0);
|
|
499
|
-
|
|
500
|
-
const endDay = new Date(toDate);
|
|
501
|
-
endDay.setHours(0, 0, 0, 0);
|
|
502
|
-
|
|
503
|
-
let currentDay = new Date(startDay);
|
|
504
|
-
|
|
505
|
-
while (currentDay <= endDay) {
|
|
506
|
-
const isFirstDay = this.isSameDay(currentDay, fromDate);
|
|
507
|
-
const isLastDay = this.isSameDay(currentDay, toDate);
|
|
508
|
-
const isSameDay = isFirstDay && isLastDay;
|
|
509
|
-
|
|
510
|
-
let workFrom: Date;
|
|
511
|
-
let workTo: Date;
|
|
512
|
-
|
|
513
|
-
// SAME DAY
|
|
514
|
-
if (isSameDay) {
|
|
515
|
-
workFrom = this.applyTimeToDay(currentDay, fromTime);
|
|
516
|
-
workTo = this.applyTimeToDay(currentDay, toTime);
|
|
517
|
-
}
|
|
518
|
-
// FIRST DAY
|
|
519
|
-
else if (isFirstDay) {
|
|
520
|
-
workFrom = this.applyTimeToDay(currentDay, fromTime);
|
|
521
|
-
workTo = this.endOfDay(currentDay);
|
|
522
|
-
}
|
|
523
|
-
// LAST DAY
|
|
524
|
-
else if (isLastDay) {
|
|
525
|
-
workFrom = this.startOfDay(currentDay);
|
|
526
|
-
workTo = this.applyTimeToDay(currentDay, toTime);
|
|
527
|
-
}
|
|
528
|
-
// MIDDLE DAY
|
|
529
|
-
else {
|
|
530
|
-
workFrom = this.startOfDay(currentDay);
|
|
531
|
-
workTo = this.endOfDay(currentDay);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
results.push({
|
|
535
|
-
comment: card.comments || "",
|
|
536
|
-
onCallDuty: false,
|
|
537
|
-
timeCredit: false,
|
|
538
|
-
workDay: this.toLocalISO(currentDay, 0, 0),
|
|
539
|
-
workDayTimeFrom: this.toLocalISO(workFrom),
|
|
540
|
-
workDayTimeTo: this.toLocalISO(workTo),
|
|
541
|
-
workOrderNo: card.workOrderNo,
|
|
542
|
-
workType: "A"
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
currentDay.setDate(currentDay.getDate() + 1);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return results;
|
|
550
|
-
}
|
|
551
|
-
private applyTimeToDay(day: Date, time: Date): Date {
|
|
552
|
-
const d = new Date(day);
|
|
553
|
-
d.setHours(time.getHours(), time.getMinutes(), 0, 0);
|
|
554
|
-
return d;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
private startOfDay(d: Date): Date {
|
|
558
|
-
const x = new Date(d);
|
|
559
|
-
x.setHours(0, 0, 0, 0);
|
|
560
|
-
return x;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
private endOfDay(d: Date): Date {
|
|
564
|
-
const x = new Date(d);
|
|
565
|
-
x.setHours(23, 59, 0, 0);
|
|
566
|
-
return x;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
private isSameDay(a: Date, b: Date): boolean {
|
|
570
|
-
return (
|
|
571
|
-
a.getFullYear() === b.getFullYear() &&
|
|
572
|
-
a.getMonth() === b.getMonth() &&
|
|
573
|
-
a.getDate() === b.getDate()
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
private toLocalISO(date: Date, hour?: number, minute?: number): string {
|
|
578
|
-
const d = new Date(date);
|
|
579
|
-
|
|
580
|
-
if (hour !== undefined && minute !== undefined) {
|
|
581
|
-
d.setHours(hour, minute, 0, 0);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
const pad = (n: number) => String(n).padStart(2, '0');
|
|
585
|
-
|
|
586
|
-
const year = d.getFullYear();
|
|
587
|
-
const month = pad(d.getMonth() + 1);
|
|
588
|
-
const day = pad(d.getDate());
|
|
589
|
-
const hrs = pad(d.getHours());
|
|
590
|
-
const mins = pad(d.getMinutes());
|
|
591
|
-
|
|
592
|
-
const offset = -d.getTimezoneOffset();
|
|
593
|
-
const sign = offset >= 0 ? '+' : '-';
|
|
594
|
-
const offH = pad(Math.floor(Math.abs(offset) / 60));
|
|
595
|
-
const offM = pad(Math.abs(offset) % 60);
|
|
596
|
-
|
|
597
|
-
return `${year}-${month}-${day}T${hrs}:${mins}:00${sign}${offH}:${offM}`;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// lib/view-toolkit.module.ts
|
|
2
|
-
|
|
3
|
-
import { CommonModule } from "@angular/common";
|
|
4
|
-
import { NgModule } from '@angular/core';
|
|
5
|
-
import { CardComponent } from "./containers/card/card.component";
|
|
6
|
-
import { FormComponent } from "./containers/form/form.component";
|
|
7
|
-
import { PaginationComponent } from "./containers/pagination/pagination.component";
|
|
8
|
-
import { GridComponent } from "./containers/grid/grid.component";
|
|
9
|
-
import { HeaderMenuComponent } from "./containers/header-menu/header-menu.component";
|
|
10
|
-
import { LogsComponent } from "./containers/logs/logs.component";
|
|
11
|
-
import { ModelComponent } from "./containers/model/model.component";
|
|
12
|
-
import { Autocomplete } from "./components/autocomplete/autocomplete";
|
|
13
|
-
import { Button } from "./components/button/button";
|
|
14
|
-
import { Date } from "./components/date/date";
|
|
15
|
-
import { Dropdown } from "./components/dropdown/dropdown";
|
|
16
|
-
import { ErrorMessage } from "./components/error-message/error-message";
|
|
17
|
-
import { Label } from "./components/label/label";
|
|
18
|
-
import { String } from "./components/string/string";
|
|
19
|
-
import { Textbox } from "./components/textbox/textbox";
|
|
20
|
-
import { Time } from "./components/time/time";
|
|
21
|
-
import { SideMenuComponent } from "./containers/side-menu/side-menu.component";
|
|
22
|
-
|
|
23
|
-
@NgModule({
|
|
24
|
-
imports: [
|
|
25
|
-
CommonModule,
|
|
26
|
-
CardComponent,
|
|
27
|
-
FormComponent,
|
|
28
|
-
GridComponent,
|
|
29
|
-
HeaderMenuComponent,
|
|
30
|
-
LogsComponent,
|
|
31
|
-
ModelComponent,
|
|
32
|
-
PaginationComponent,
|
|
33
|
-
SideMenuComponent,
|
|
34
|
-
|
|
35
|
-
Autocomplete,
|
|
36
|
-
Button,
|
|
37
|
-
Date,
|
|
38
|
-
Dropdown,
|
|
39
|
-
ErrorMessage,
|
|
40
|
-
Label,
|
|
41
|
-
String,
|
|
42
|
-
Textbox,
|
|
43
|
-
Time
|
|
44
|
-
],
|
|
45
|
-
exports: [
|
|
46
|
-
CardComponent,
|
|
47
|
-
FormComponent,
|
|
48
|
-
GridComponent,
|
|
49
|
-
HeaderMenuComponent,
|
|
50
|
-
LogsComponent,
|
|
51
|
-
ModelComponent,
|
|
52
|
-
PaginationComponent,
|
|
53
|
-
SideMenuComponent
|
|
54
|
-
|
|
55
|
-
]
|
|
56
|
-
})
|
|
57
|
-
export class ViewToolkitModule { }
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { ViewToolkit } from './view-toolkit';
|
|
4
|
-
|
|
5
|
-
describe('ViewToolkit', () => {
|
|
6
|
-
let component: ViewToolkit;
|
|
7
|
-
let fixture: ComponentFixture<ViewToolkit>;
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
await TestBed.configureTestingModule({
|
|
11
|
-
imports: [ViewToolkit]
|
|
12
|
-
})
|
|
13
|
-
.compileComponents();
|
|
14
|
-
|
|
15
|
-
fixture = TestBed.createComponent(ViewToolkit);
|
|
16
|
-
component = fixture.componentInstance;
|
|
17
|
-
await fixture.whenStable();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should create', () => {
|
|
21
|
-
expect(component).toBeTruthy();
|
|
22
|
-
});
|
|
23
|
-
});
|
package/src/lib/view-toolkit.ts
DELETED