@yomotech/view-toolkit 0.0.32 → 0.0.33
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 +3591 -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,275 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { UtilityService } from './utility.service';
|
|
3
|
-
|
|
4
|
-
@Injectable({
|
|
5
|
-
providedIn: 'root',
|
|
6
|
-
})
|
|
7
|
-
export class Couchdb {
|
|
8
|
-
private readonly couchDbBaseUrl = 'https://couchdb.yomotech.de';
|
|
9
|
-
|
|
10
|
-
constructor(private utilityService: UtilityService) { }
|
|
11
|
-
|
|
12
|
-
async getTenantDatabases(tenantKey: any): Promise<any[]> {
|
|
13
|
-
if (!tenantKey || !tenantKey.trim()) {
|
|
14
|
-
throw new Error('Missing tenantKey');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const response = await fetch(`https://couchdb.yomotech.de/tenant-dbs`, {
|
|
18
|
-
method: 'GET',
|
|
19
|
-
headers: {
|
|
20
|
-
Accept: 'application/json',
|
|
21
|
-
'X-Tenant-Key': tenantKey.trim(),
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const data = await this.parseJsonOrText(response);
|
|
26
|
-
|
|
27
|
-
if (!response.ok) {
|
|
28
|
-
throw new Error(
|
|
29
|
-
`GET /tenant-dbs -> ${response.status} ${this.stringifyErrorDetails(data)}`
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return data;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private async parseJsonOrText(response: Response): Promise<any> {
|
|
37
|
-
const rawText = await response.text();
|
|
38
|
-
|
|
39
|
-
if (!rawText) return null;
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
return JSON.parse(rawText);
|
|
43
|
-
} catch {
|
|
44
|
-
return rawText;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private stringifyErrorDetails(data: any): string {
|
|
49
|
-
if (typeof data === 'string') return data;
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
return JSON.stringify(data);
|
|
53
|
-
} catch {
|
|
54
|
-
return 'Unknown error';
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async getFileContentFromCouchDb(
|
|
59
|
-
couchDbName: string,
|
|
60
|
-
filePath: string
|
|
61
|
-
): Promise<any | null> {
|
|
62
|
-
try {
|
|
63
|
-
|
|
64
|
-
const dbName = couchDbName;
|
|
65
|
-
const docId = filePath?.trim();
|
|
66
|
-
if (!docId) {
|
|
67
|
-
console.error('Missing file path');
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const response = await fetch(this.getDocumentUrl(dbName, docId), {
|
|
72
|
-
method: 'GET',
|
|
73
|
-
headers: await this.getReadHeaders(),
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const doc = await this.parseJsonOrText(response);
|
|
77
|
-
|
|
78
|
-
if (!response.ok) {
|
|
79
|
-
console.error(
|
|
80
|
-
`Failed to fetch file "${docId}" from "${dbName}": ${response.status}`,
|
|
81
|
-
doc
|
|
82
|
-
);
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!doc?.data) {
|
|
87
|
-
console.error(`Document "${docId}" does not contain file data`);
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// do not decode images as utf8 text
|
|
92
|
-
if (
|
|
93
|
-
doc.type === 'media' ||
|
|
94
|
-
doc.type === 'base64file' ||
|
|
95
|
-
this.isBinaryMediaFile(doc.name || doc.path || docId, doc.contentType)
|
|
96
|
-
) {
|
|
97
|
-
return {
|
|
98
|
-
type: doc.type || 'base64file',
|
|
99
|
-
mimeType: this.getMimeType(doc.name || doc.path || docId, doc.contentType),
|
|
100
|
-
base64: doc.data,
|
|
101
|
-
src: `data:${this.getMimeType(doc.name || doc.path || docId, doc.contentType)};base64,${doc.data}`,
|
|
102
|
-
name: doc.name,
|
|
103
|
-
path: doc.path,
|
|
104
|
-
metadata: doc.metadata || {},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const decodedContent = this.fromBase64(doc.data);
|
|
109
|
-
|
|
110
|
-
if (this.isJsonFile(doc.name || doc.path || docId, doc.contentType)) {
|
|
111
|
-
try {
|
|
112
|
-
return JSON.parse(decodedContent);
|
|
113
|
-
} catch (jsonError) {
|
|
114
|
-
console.error(`Failed to parse JSON for file "${docId}"`, jsonError);
|
|
115
|
-
return decodedContent;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return decodedContent;
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error(
|
|
122
|
-
`Unexpected error while fetching file "${filePath}" from "${couchDbName}"`,
|
|
123
|
-
error
|
|
124
|
-
);
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private isBinaryMediaFile(fileNameOrPath: string, contentType?: string): boolean {
|
|
130
|
-
const lower = (fileNameOrPath || '').toLowerCase();
|
|
131
|
-
const type = contentType || '';
|
|
132
|
-
|
|
133
|
-
return (
|
|
134
|
-
type.startsWith('image/') ||
|
|
135
|
-
type.startsWith('video/') ||
|
|
136
|
-
type.startsWith('audio/') ||
|
|
137
|
-
type === 'application/pdf' ||
|
|
138
|
-
|
|
139
|
-
lower.endsWith('.png') ||
|
|
140
|
-
lower.endsWith('.jpg') ||
|
|
141
|
-
lower.endsWith('.jpeg') ||
|
|
142
|
-
lower.endsWith('.ico') ||
|
|
143
|
-
lower.endsWith('.svg') ||
|
|
144
|
-
lower.endsWith('.webp') ||
|
|
145
|
-
lower.endsWith('.gif') ||
|
|
146
|
-
|
|
147
|
-
lower.endsWith('.mp4') ||
|
|
148
|
-
lower.endsWith('.webm') ||
|
|
149
|
-
lower.endsWith('.mp3') ||
|
|
150
|
-
lower.endsWith('.wav') ||
|
|
151
|
-
lower.endsWith('.m4a') ||
|
|
152
|
-
|
|
153
|
-
lower.endsWith('.pdf')
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private getMimeType(fileNameOrPath: string, contentType?: string): string {
|
|
158
|
-
if (contentType) return contentType;
|
|
159
|
-
|
|
160
|
-
const lower = (fileNameOrPath || '').toLowerCase();
|
|
161
|
-
|
|
162
|
-
if (lower.endsWith('.png')) return 'image/png';
|
|
163
|
-
if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg';
|
|
164
|
-
if (lower.endsWith('.ico')) return 'image/x-icon';
|
|
165
|
-
if (lower.endsWith('.svg')) return 'image/svg+xml';
|
|
166
|
-
if (lower.endsWith('.webp')) return 'image/webp';
|
|
167
|
-
if (lower.endsWith('.gif')) return 'image/gif';
|
|
168
|
-
|
|
169
|
-
if (lower.endsWith('.mp4')) return 'video/mp4';
|
|
170
|
-
if (lower.endsWith('.webm')) return 'video/webm';
|
|
171
|
-
|
|
172
|
-
if (lower.endsWith('.mp3')) return 'audio/mpeg';
|
|
173
|
-
if (lower.endsWith('.wav')) return 'audio/wav';
|
|
174
|
-
if (lower.endsWith('.m4a')) return 'audio/mp4';
|
|
175
|
-
|
|
176
|
-
if (lower.endsWith('.pdf')) return 'application/pdf';
|
|
177
|
-
|
|
178
|
-
return 'application/octet-stream';
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
private getImageMimeType(fileNameOrPath: string): string {
|
|
182
|
-
const lower = (fileNameOrPath || '').toLowerCase();
|
|
183
|
-
|
|
184
|
-
if (lower.endsWith('.png')) return 'image/png';
|
|
185
|
-
if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg';
|
|
186
|
-
if (lower.endsWith('.ico')) return 'image/x-icon';
|
|
187
|
-
if (lower.endsWith('.svg')) return 'image/svg+xml';
|
|
188
|
-
|
|
189
|
-
return 'image/png';
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private fromBase64(base64: string): string {
|
|
193
|
-
try {
|
|
194
|
-
return decodeURIComponent(escape(atob(base64)));
|
|
195
|
-
} catch {
|
|
196
|
-
return atob(base64);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
private isJsonFile(fileNameOrPath: string, contentType?: string): boolean {
|
|
201
|
-
const lower = (fileNameOrPath || '').toLowerCase();
|
|
202
|
-
return lower.endsWith('.json') || contentType === 'application/json';
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
private getDocumentUrl(dbName: string, docId: string): string {
|
|
206
|
-
return `${this.getDbUrl(dbName)}/${encodeURIComponent(docId)}`;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private getDbUrl(dbName: string): string {
|
|
210
|
-
return `${this.couchDbBaseUrl}/${dbName}`;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
private async getReadHeaders(): Promise<HeadersInit> {
|
|
214
|
-
return {
|
|
215
|
-
Accept: 'application/json',
|
|
216
|
-
...(await this.buildTenantHeaders()),
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
private async buildTenantHeaders(): Promise<HeadersInit> {
|
|
221
|
-
const tenantKey = await this.utilityService.getStorage('tenantKey');
|
|
222
|
-
const tenantName = await this.utilityService.getStorage('tenantName');
|
|
223
|
-
const selectedTenant = await this.utilityService.getLocalStorage('selectedTenant');
|
|
224
|
-
if (tenantKey) {
|
|
225
|
-
if (typeof tenantKey !== 'string' || !tenantKey.trim()) {
|
|
226
|
-
throw new Error('Missing tenantKey');
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
'X-Tenant-Key': tenantKey.trim(),
|
|
230
|
-
};
|
|
231
|
-
} else {
|
|
232
|
-
if ((typeof tenantName !== 'string' || !tenantName.trim() || !tenantName.trim()) || (typeof selectedTenant !== 'string' || !selectedTenant.trim() || !selectedTenant.trim())) {
|
|
233
|
-
throw new Error('Missing tenantName');
|
|
234
|
-
}
|
|
235
|
-
return {
|
|
236
|
-
'X-Tenant': tenantName ? tenantName.trim() : selectedTenant.trim(),
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
async getImageSrcFromCouchDb(
|
|
244
|
-
couchDbName: string,
|
|
245
|
-
filePath: string
|
|
246
|
-
): Promise<string> {
|
|
247
|
-
const dbName = couchDbName;
|
|
248
|
-
const docId = filePath?.trim();
|
|
249
|
-
|
|
250
|
-
if (!docId) {
|
|
251
|
-
throw new Error('Missing file path');
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const response = await fetch(this.getDocumentUrl(dbName, docId), {
|
|
255
|
-
method: 'GET',
|
|
256
|
-
headers: await this.getReadHeaders(),
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
const doc = await this.parseJsonOrText(response);
|
|
260
|
-
|
|
261
|
-
if (!response.ok) {
|
|
262
|
-
throw new Error(
|
|
263
|
-
`Failed to fetch image "${docId}" from "${dbName}": ${response.status} ${this.stringifyErrorDetails(doc)}`
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (!doc?.data) {
|
|
268
|
-
throw new Error(`Document "${docId}" does not contain image data`);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const mimeType = doc.contentType || 'image/png';
|
|
272
|
-
|
|
273
|
-
return `data:${mimeType};base64,${doc.data}`;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { ConfigService } from './config.service';
|
|
3
|
-
import { Capacitor } from '@capacitor/core';
|
|
4
|
-
import { App } from '@capacitor/app';
|
|
5
|
-
import { Browser } from '@capacitor/browser';
|
|
6
|
-
import { OAuth2Client } from '@byteowls/capacitor-oauth2';
|
|
7
|
-
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
8
|
-
import { Platform } from '@angular/cdk/platform';
|
|
9
|
-
import { UtilityService } from './utility.service';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export interface MobileAuthTokens {
|
|
13
|
-
access_token: string;
|
|
14
|
-
refresh_token?: string;
|
|
15
|
-
id_token?: string;
|
|
16
|
-
expires_in?: number;
|
|
17
|
-
token_type?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@Injectable({
|
|
22
|
-
providedIn: 'root'
|
|
23
|
-
})
|
|
24
|
-
export class MobileKeycloakService {
|
|
25
|
-
|
|
26
|
-
private tokens: MobileAuthTokens | any = null;
|
|
27
|
-
constructor(private config: ConfigService, private http: HttpClient, private utilityService: UtilityService, private platform: Platform) {
|
|
28
|
-
if (Capacitor.isNativePlatform()) {
|
|
29
|
-
App.addListener('appUrlOpen', async (url: any) => {
|
|
30
|
-
// Nothing to do here; capacitor-oauth2 resolves internally.
|
|
31
|
-
// Keep listener to satisfy deep link expectations.
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async login(): Promise<any> {
|
|
37
|
-
if (!Capacitor.isNativePlatform()) return null;
|
|
38
|
-
const cfg: any = this.config.getKeycloakMobileConfig();
|
|
39
|
-
const discoveryUrl = `${cfg.issuer}/.well-known/openid-configuration`;
|
|
40
|
-
const discovery: any = await (await fetch(discoveryUrl)).json();
|
|
41
|
-
const result = await OAuth2Client.authenticate({
|
|
42
|
-
appId: cfg.clientId, // <--- Keycloak clientId goes here
|
|
43
|
-
authorizationBaseUrl: discovery.authorization_endpoint,
|
|
44
|
-
accessTokenEndpoint: discovery.token_endpoint,
|
|
45
|
-
responseType: 'code',
|
|
46
|
-
redirectUrl: cfg.redirectUri,
|
|
47
|
-
scope: cfg.scope,
|
|
48
|
-
pkceEnabled: true,
|
|
49
|
-
logsEnabled: true
|
|
50
|
-
});
|
|
51
|
-
console.log('result-KEyClaok: ', result);
|
|
52
|
-
this.tokens = {
|
|
53
|
-
access_token: result?.access_token_response?.access_token ? result?.access_token_response?.access_token : result.access_token,
|
|
54
|
-
refresh_token: result?.access_token_response?.refresh_token,
|
|
55
|
-
id_token: result?.access_token_response?.id_token,
|
|
56
|
-
expires_in: result?.access_token_response?.expires_at ? result?.access_token_response?.expires_at : result?.access_token_response?.expires_in,
|
|
57
|
-
token_type: result?.access_token_response?.token_type
|
|
58
|
-
};
|
|
59
|
-
let keycloakLoginUser = "";
|
|
60
|
-
if (this.tokens.access_token) {
|
|
61
|
-
keycloakLoginUser = await this.getUserInfo(this.tokens.access_token, cfg.issuer);
|
|
62
|
-
console.log('keycloakLoginUser: ', keycloakLoginUser);
|
|
63
|
-
if (keycloakLoginUser) {
|
|
64
|
-
this.tokens['issuer'] = cfg.issuer;
|
|
65
|
-
this.utilityService.setLocalStorage("KeycloakInfo", this.tokens);
|
|
66
|
-
if (this.platform.ANDROID || this.platform.IOS) {
|
|
67
|
-
window.location.reload();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return keycloakLoginUser;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async getUserInfo(accessToken: any, issuer: any): Promise<any> {
|
|
75
|
-
try {
|
|
76
|
-
const headers = new HttpHeaders({
|
|
77
|
-
Authorization: `Bearer ${accessToken}`,
|
|
78
|
-
});
|
|
79
|
-
const url = `${issuer}/protocol/openid-connect/userinfo`;
|
|
80
|
-
return await this.http.get(url, { headers }).toPromise();
|
|
81
|
-
} catch (err) {
|
|
82
|
-
console.error('Error fetching user info:', err);
|
|
83
|
-
throw err;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
getAccessToken(): string | null {
|
|
88
|
-
return this.tokens?.access_token ?? null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getRefreshToken(): string | null {
|
|
92
|
-
return this.tokens?.refresh_token ?? null;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async logout(): Promise<void> {
|
|
96
|
-
const keycloakInfo: any = await this.utilityService.getLocalStorage('KeycloakInfo');
|
|
97
|
-
const cfg: any = this.config.getKeycloakMobileConfig();
|
|
98
|
-
const idToken = keycloakInfo?.keycloakInfo?.id_token;
|
|
99
|
-
const accessToken = keycloakInfo?.keycloakInfo?.access_token;
|
|
100
|
-
if (!idToken || !accessToken) {
|
|
101
|
-
console.warn('No tokens found for logout');
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const endSessionUrl =
|
|
105
|
-
`${cfg.issuer}/protocol/openid-connect/logout` +
|
|
106
|
-
`?id_token_hint=${encodeURIComponent(idToken)}` +
|
|
107
|
-
`&client_id=${encodeURIComponent(cfg.clientId)}` +
|
|
108
|
-
`&post_logout_redirect_uri=${encodeURIComponent(cfg.logoutRedirectUri)}`;
|
|
109
|
-
console.log('Logout URL:', endSessionUrl);
|
|
110
|
-
await Browser.open({ url: endSessionUrl });
|
|
111
|
-
this.tokens = null;
|
|
112
|
-
await this.utilityService.removeLocalStorage('KeycloakInfo');
|
|
113
|
-
window.location.reload();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
|
|
3
|
-
@Injectable({
|
|
4
|
-
providedIn: 'root'
|
|
5
|
-
})
|
|
6
|
-
export class NetworkLogService {
|
|
7
|
-
|
|
8
|
-
private logs: any[] = [];
|
|
9
|
-
|
|
10
|
-
addLog(log: any) {
|
|
11
|
-
this.logs.unshift(log); // latest first
|
|
12
|
-
localStorage.setItem('networkLogs', JSON.stringify(this.logs));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
getLogsByDate(date: string): any[] {
|
|
16
|
-
return this.logs.filter(l => l.date === date);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getAll(): any[] {
|
|
20
|
-
return [...this.logs];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
clear() {
|
|
24
|
-
this.logs = [];
|
|
25
|
-
localStorage.removeItem('networkLogs');
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { ToastrService } from 'ngx-toastr';
|
|
3
|
-
|
|
4
|
-
@Injectable({
|
|
5
|
-
providedIn: 'root'
|
|
6
|
-
})
|
|
7
|
-
export class NotificationService {
|
|
8
|
-
|
|
9
|
-
constructor(public toastr: ToastrService) { }
|
|
10
|
-
|
|
11
|
-
success(message: string, time: number = 5000) {
|
|
12
|
-
this.toastr.success(message, "", { messageClass: 'toaster-font', titleClass: 'toaster-font', closeButton: true, timeOut: time });
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
info(message: string, time: number = 5000) {
|
|
16
|
-
this.toastr.info(message, "", { messageClass: 'toaster-font', titleClass: 'toaster-font', closeButton: true, timeOut: time });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
warning(message: string, time: number = 20000) {
|
|
20
|
-
this.toastr.warning(message, "", { messageClass: 'toaster-font', titleClass: 'toaster-font', closeButton: true, timeOut: time });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
error(error: string, time: number = 20000, message?: string,) {
|
|
24
|
-
this.toastr.error(error, message, { messageClass: 'toaster-font', titleClass: 'toaster-font', closeButton: true, timeOut: time });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
|
|
4
|
-
@Injectable({
|
|
5
|
-
providedIn: 'root'
|
|
6
|
-
})
|
|
7
|
-
export class RequestService {
|
|
8
|
-
pageSize: number = 0;
|
|
9
|
-
constructor(private http: HttpClient) { }
|
|
10
|
-
|
|
11
|
-
getAllProject() {
|
|
12
|
-
return this.http.get("../assets/main/layout_schema.json");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
getEnvironmet(selectedProject: any) {
|
|
16
|
-
return this.http.get(`../../assets/projects/${selectedProject}/environments/environment.json`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getSectionInfo(url: string, envUrl?: any, passToken: boolean = false, selectedProject: string = '', userInfo: any = null) {
|
|
20
|
-
if (envUrl) {
|
|
21
|
-
if (passToken && selectedProject) {
|
|
22
|
-
return this.http.get(envUrl + url, {
|
|
23
|
-
headers: this.createAuthorizationHeader(userInfo),
|
|
24
|
-
})
|
|
25
|
-
} else {
|
|
26
|
-
return this.http.get(envUrl + url);
|
|
27
|
-
}
|
|
28
|
-
} else {
|
|
29
|
-
return this.http.get(url);
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getMainLayout(selectedProject: any) {
|
|
34
|
-
return this.http.get(`../assets/projects/${selectedProject}/main/layout_schema.json`)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getInfo(url: string) {
|
|
38
|
-
return this.http.get(url);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
dynamicCall(method: string = "get", body: any = null, url: string, passToken: boolean = false, selectedProject: string = '', userInfo: any = null) {
|
|
42
|
-
switch (method.toLowerCase()) {
|
|
43
|
-
case 'get':
|
|
44
|
-
if (passToken && selectedProject) {
|
|
45
|
-
return this.http.get(url, {
|
|
46
|
-
headers: this.createAuthorizationHeader(userInfo),
|
|
47
|
-
})
|
|
48
|
-
} else {
|
|
49
|
-
return this.http.get(url);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
case 'post':
|
|
53
|
-
if (passToken && selectedProject) {
|
|
54
|
-
return this.http.post(url, body, {
|
|
55
|
-
headers: this.createAuthorizationHeader(userInfo),
|
|
56
|
-
})
|
|
57
|
-
} else {
|
|
58
|
-
return this.http.post(url, body);
|
|
59
|
-
}
|
|
60
|
-
case 'put':
|
|
61
|
-
if (passToken && selectedProject) {
|
|
62
|
-
return this.http.put(url, body, {
|
|
63
|
-
headers: this.createAuthorizationHeader(userInfo),
|
|
64
|
-
})
|
|
65
|
-
} else {
|
|
66
|
-
return this.http.put(url, body);
|
|
67
|
-
}
|
|
68
|
-
case 'delete':
|
|
69
|
-
if (passToken && selectedProject) {
|
|
70
|
-
return this.http.delete(url, {
|
|
71
|
-
headers: this.createAuthorizationHeader(userInfo),
|
|
72
|
-
})
|
|
73
|
-
} else {
|
|
74
|
-
return this.http.delete(url);
|
|
75
|
-
};
|
|
76
|
-
case 'patch':
|
|
77
|
-
return this.http.patch(url, body);
|
|
78
|
-
default:
|
|
79
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
createAuthorizationHeader(userInfo: any, tokenExist: boolean = false) {
|
|
84
|
-
let authHeaders: HttpHeaders = new HttpHeaders();
|
|
85
|
-
let token = tokenExist ? userInfo : userInfo && userInfo.jwt ? userInfo.jwt : userInfo?.authToken ? userInfo?.authToken : '';
|
|
86
|
-
return authHeaders.set(
|
|
87
|
-
'Authorization',
|
|
88
|
-
'Bearer ' + token
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getLoginUser(token: any) {
|
|
93
|
-
return this.http.get("https://dev-78992019.okta.com/oauth2/default/v1/userinfo", {
|
|
94
|
-
headers: this.createAuthorizationHeader(token, true),
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
saveDb(token: any, userInfo: any, order: any = {}) {
|
|
99
|
-
if (token) {
|
|
100
|
-
const headers = new HttpHeaders({
|
|
101
|
-
'Authorization': `Bearer ${token}`,
|
|
102
|
-
'Accept': 'application/json'
|
|
103
|
-
});
|
|
104
|
-
let url2: any = `${userInfo.p5_backend_url}/assetsmobileservice/Zeiterfassung/registerTimeRecording?company=${userInfo.p5_group}/${userInfo.p5_client}/${userInfo.p5_plant ? userInfo.p5_plant : " "}&appVersion=1&resourceNo=${userInfo.p5_resource_no}`
|
|
105
|
-
console.log('userInfo: ', userInfo);
|
|
106
|
-
this.http.post(url2, order, { headers }).subscribe({
|
|
107
|
-
next: res => {
|
|
108
|
-
console.log('Save-res: ', res);
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
getSaveOrder(token: any, userInfo: any, fromDate: any, toDate: any) {
|
|
115
|
-
// if (token) {
|
|
116
|
-
const headers = new HttpHeaders({
|
|
117
|
-
'Authorization': `Bearer ${token}`,
|
|
118
|
-
'Accept': 'application/json'
|
|
119
|
-
});
|
|
120
|
-
let url = `${userInfo.p5_backend_url}/assetsmobileservice/Zeiterfassung/requestBookedTimeRecording?resourceNo=${userInfo.p5_resource_no}&workDayFrom=${fromDate}&workDayTo=${toDate}&company=${userInfo.p5_group}/${userInfo.p5_client}/${userInfo.p5_plant ? userInfo.p5_plant : " "}&appVersion=1`
|
|
121
|
-
return this.http.post(url, {}, { headers })
|
|
122
|
-
// }
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|