@flusys/ng-localization 4.0.0-lts
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/README.md +975 -0
- package/fesm2022/flusys-ng-localization.mjs +3303 -0
- package/fesm2022/flusys-ng-localization.mjs.map +1 -0
- package/package.json +33 -0
- package/types/flusys-ng-localization.d.ts +506 -0
|
@@ -0,0 +1,3303 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, PLATFORM_ID, ApplicationRef, signal, computed, effect, Injectable, DestroyRef, ElementRef, Component, APP_INITIALIZER } from '@angular/core';
|
|
3
|
+
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
4
|
+
import { PrimeNG } from 'primeng/config';
|
|
5
|
+
import { HttpClient } from '@angular/common/http';
|
|
6
|
+
import { APP_CONFIG, TRANSLATE_ADAPTER } from '@flusys/ng-core';
|
|
7
|
+
import { firstValueFrom, from, fromEvent, finalize, forkJoin } from 'rxjs';
|
|
8
|
+
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
9
|
+
import * as i1 from 'primeng/styleclass';
|
|
10
|
+
import { StyleClassModule } from 'primeng/styleclass';
|
|
11
|
+
import { filter } from 'rxjs/operators';
|
|
12
|
+
import { LAYOUT_LANGUAGE_SELECTOR, LAYOUT_LANGUAGE_SELECTOR_PANEL } from '@flusys/ng-layout';
|
|
13
|
+
import { resolveTranslationModule, SHARED_MESSAGES, PermissionValidatorService, LANGUAGE_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TRANSLATION_PERMISSIONS, TranslatePipe, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
|
|
14
|
+
import { RouterOutlet, RouterLink, RouterLinkActive, Router, ActivatedRoute } from '@angular/router';
|
|
15
|
+
import { ConfirmationService, MessageService } from 'primeng/api';
|
|
16
|
+
import * as i2 from 'primeng/button';
|
|
17
|
+
import * as i2$1 from 'primeng/confirmdialog';
|
|
18
|
+
import * as i8 from 'primeng/table';
|
|
19
|
+
import * as i4 from 'primeng/tag';
|
|
20
|
+
import * as i10 from 'primeng/toast';
|
|
21
|
+
import * as i6 from 'primeng/tooltip';
|
|
22
|
+
import * as i1$1 from '@angular/forms';
|
|
23
|
+
import { FormsModule } from '@angular/forms';
|
|
24
|
+
import { form, required, maxLength, FormField } from '@angular/forms/signals';
|
|
25
|
+
import * as i3 from 'primeng/card';
|
|
26
|
+
import * as i4$1 from 'primeng/inputtext';
|
|
27
|
+
import * as i5 from 'primeng/select';
|
|
28
|
+
import * as i4$2 from 'primeng/iconfield';
|
|
29
|
+
import * as i5$1 from 'primeng/inputicon';
|
|
30
|
+
import * as i7 from 'primeng/textarea';
|
|
31
|
+
import * as i9 from 'primeng/progressspinner';
|
|
32
|
+
import * as i3$1 from 'primeng/checkbox';
|
|
33
|
+
|
|
34
|
+
const LOCALIZATION_CONFIG = new InjectionToken('LOCALIZATION_CONFIG');
|
|
35
|
+
/** Get localization config with sensible defaults applied */
|
|
36
|
+
function getLocalizationConfig(overrides) {
|
|
37
|
+
const defaults = {
|
|
38
|
+
defaultLanguageCode: 'en',
|
|
39
|
+
loadStrategy: 'modules',
|
|
40
|
+
initialModules: [],
|
|
41
|
+
enableLayoutSelector: false,
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
...defaults,
|
|
45
|
+
...overrides,
|
|
46
|
+
defaultLanguageCode: overrides?.defaultLanguageCode || defaults.defaultLanguageCode,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const STORAGE_KEYS = {
|
|
51
|
+
CURRENT_LANGUAGE: 'flusys.language',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const LOCALIZATION_MESSAGES = {
|
|
55
|
+
// Container
|
|
56
|
+
'localization.title': 'Localization',
|
|
57
|
+
'localization.subtitle': 'Manage languages and translations',
|
|
58
|
+
// Tabs
|
|
59
|
+
'localization.tabs.languages': 'Languages',
|
|
60
|
+
'localization.tabs.keys': 'Keys',
|
|
61
|
+
'localization.tabs.translations': 'Translations',
|
|
62
|
+
// Languages
|
|
63
|
+
'localization.language.title': 'Languages',
|
|
64
|
+
'localization.language.subtitle': 'Manage available languages for your application',
|
|
65
|
+
'localization.language.create': 'Add Language',
|
|
66
|
+
'localization.language.edit': 'Edit Language',
|
|
67
|
+
'localization.language.code': 'Language Code',
|
|
68
|
+
'localization.language.name': 'Language Name',
|
|
69
|
+
'localization.language.native.name': 'Native Name',
|
|
70
|
+
'localization.language.direction': 'Text Direction',
|
|
71
|
+
'localization.language.ltr': 'LTR',
|
|
72
|
+
'localization.language.rtl': 'RTL',
|
|
73
|
+
'localization.language.active': 'Active',
|
|
74
|
+
'localization.language.default': 'Default',
|
|
75
|
+
'localization.language.set.default': 'Set as Default',
|
|
76
|
+
'localization.language.confirm.set.default': 'Set "{{name}}" as the default language?',
|
|
77
|
+
'localization.language.set.default.success': '{{name}} is now the default language.',
|
|
78
|
+
'localization.language.delete.title': 'Delete Language',
|
|
79
|
+
'localization.language.empty': 'No languages configured. Add a language to get started.',
|
|
80
|
+
'localization.language.display.order': 'Display Order',
|
|
81
|
+
'localization.language.iso.code.hint': 'ISO 639-1 language code (e.g., en, ar, fr)',
|
|
82
|
+
'localization.language.native.name.hint': 'Name in the native language (e.g., العربية for Arabic)',
|
|
83
|
+
'localization.language.create.success': 'Language created successfully',
|
|
84
|
+
'localization.language.update.success': 'Language updated successfully',
|
|
85
|
+
// Translation keys
|
|
86
|
+
'localization.key.title': 'Translation Keys',
|
|
87
|
+
'localization.key.subtitle': 'Manage translation keys for your application',
|
|
88
|
+
'localization.key.create': 'Add Key',
|
|
89
|
+
'localization.key.edit': 'Edit Key',
|
|
90
|
+
'localization.key.key': 'Key',
|
|
91
|
+
'localization.key.name': 'Key Name',
|
|
92
|
+
'localization.key.module': 'Module',
|
|
93
|
+
'localization.key.default.message': 'Default Message',
|
|
94
|
+
'localization.key.description': 'Description',
|
|
95
|
+
'localization.key.variables': 'Variables',
|
|
96
|
+
'localization.key.variables.hint': 'Enter variable names used in this translation',
|
|
97
|
+
'localization.key.variables.placeholder': 'e.g., name, count, date',
|
|
98
|
+
'localization.key.translations': 'Translations',
|
|
99
|
+
'localization.key.translations.section': 'Translations',
|
|
100
|
+
'localization.key.about': 'Key Information',
|
|
101
|
+
'localization.key.filter.module': 'Filter by module',
|
|
102
|
+
'localization.key.select.module': 'Select or enter module',
|
|
103
|
+
'localization.key.enter.translation': 'Enter translation',
|
|
104
|
+
'localization.key.no.languages': 'No active languages configured',
|
|
105
|
+
'localization.key.empty': 'No translation keys found',
|
|
106
|
+
'localization.key.delete.title': 'Delete Translation Key',
|
|
107
|
+
'localization.key.readonly': 'System Key',
|
|
108
|
+
'localization.key.readonly.hint': 'System keys cannot be deleted',
|
|
109
|
+
// Translations
|
|
110
|
+
'localization.translation.title': 'Translations',
|
|
111
|
+
'localization.translation.manage': 'Manage Translations',
|
|
112
|
+
'localization.translation.value': 'Translation',
|
|
113
|
+
'localization.translation.verified': 'Verified',
|
|
114
|
+
'localization.translation.missing': 'Missing',
|
|
115
|
+
'localization.translation.save.changes': 'Save Changes',
|
|
116
|
+
'localization.translation.unsaved.changes': '{{count}} unsaved changes',
|
|
117
|
+
'localization.translation.no.keys': 'No translation keys found for this module',
|
|
118
|
+
'localization.translation.select.module': 'Select a module to view translations',
|
|
119
|
+
'localization.translation.select.language': 'Select a language to view translations',
|
|
120
|
+
'localization.translation.module': 'Module',
|
|
121
|
+
'localization.translation.language': 'Language',
|
|
122
|
+
'localization.translation.key': 'Key',
|
|
123
|
+
'localization.translation.default.message': 'Default Message',
|
|
124
|
+
// Language selector
|
|
125
|
+
'localization.selector.language': 'Language',
|
|
126
|
+
'localization.selector.select.language': 'Select Language',
|
|
127
|
+
// Translation list page
|
|
128
|
+
'localization.translation.save.success': 'Success',
|
|
129
|
+
'localization.translation.save.success.detail': 'Translations saved successfully',
|
|
130
|
+
'localization.translation.search.keys': 'Search translation keys...',
|
|
131
|
+
'localization.translation.select.module.hint': 'Please select a module to view its translations',
|
|
132
|
+
'localization.translation.select.language.hint': 'Please select a language to view translations',
|
|
133
|
+
'localization.translation.all.modules': 'All Modules',
|
|
134
|
+
'localization.translation.pagination': 'Showing {first} to {last} of {totalRecords} keys',
|
|
135
|
+
// Language direction labels
|
|
136
|
+
'localization.language.direction.ltr': 'Left to Right (LTR)',
|
|
137
|
+
'localization.language.direction.rtl': 'Right to Left (RTL)',
|
|
138
|
+
// Placeholders
|
|
139
|
+
'localization.placeholder.code': 'en',
|
|
140
|
+
'localization.placeholder.name': 'English',
|
|
141
|
+
'localization.placeholder.native.name': 'English',
|
|
142
|
+
'localization.placeholder.key.name': 'button.submit',
|
|
143
|
+
'localization.placeholder.default.message': 'Enter default value (English)',
|
|
144
|
+
'localization.placeholder.key.description': 'Optional description for translators',
|
|
145
|
+
// Language CRUD (API keys)
|
|
146
|
+
'language.create.success': 'Language created successfully',
|
|
147
|
+
'language.create.many.success': '{{count}} languages created successfully',
|
|
148
|
+
'language.get.success': 'Language retrieved successfully',
|
|
149
|
+
'language.get.all.success': 'Languages retrieved successfully',
|
|
150
|
+
'language.update.success': 'Language updated successfully',
|
|
151
|
+
'language.update.many.success': '{{count}} languages updated successfully',
|
|
152
|
+
'language.delete.success': 'Language deleted successfully',
|
|
153
|
+
'language.restore.success': 'Language restored successfully',
|
|
154
|
+
'language.not.found': 'Language not found',
|
|
155
|
+
'language.active.success': 'Active languages retrieved successfully',
|
|
156
|
+
'language.set.default.success': 'Default language updated successfully',
|
|
157
|
+
'language.get.default.success': 'Default language retrieved successfully',
|
|
158
|
+
// Translation key CRUD (API keys)
|
|
159
|
+
'translation.key.create.success': 'Translation key created successfully',
|
|
160
|
+
'translation.key.create.many.success': '{{count}} translation keys created successfully',
|
|
161
|
+
'translation.key.get.success': 'Translation key retrieved successfully',
|
|
162
|
+
'translation.key.get.all.success': 'Translation keys retrieved successfully',
|
|
163
|
+
'translation.key.update.success': 'Translation key updated successfully',
|
|
164
|
+
'translation.key.update.many.success': '{{count}} translation keys updated successfully',
|
|
165
|
+
'translation.key.delete.success': 'Translation key deleted successfully',
|
|
166
|
+
'translation.key.restore.success': 'Translation key restored successfully',
|
|
167
|
+
'translation.key.not.found': 'Translation key not found',
|
|
168
|
+
'translation.key.import.success': 'Translation keys imported successfully',
|
|
169
|
+
'translation.key.export.success': 'Translation keys exported successfully',
|
|
170
|
+
'translation.key.readonly.delete.forbidden': 'Cannot delete readonly translation keys: {{keys}}',
|
|
171
|
+
'translation.key.readonly.update.forbidden': 'Cannot modify key or module of system translation keys',
|
|
172
|
+
'translation.key.duplicate.key.in.module': 'Translation key "{{key}}" already exists in module "{{module}}"',
|
|
173
|
+
'translation.key.modules.success': 'Modules retrieved successfully',
|
|
174
|
+
// Translation CRUD (API keys)
|
|
175
|
+
'translation.create.success': 'Translation created successfully',
|
|
176
|
+
'translation.create.many.success': '{{count}} translations created successfully',
|
|
177
|
+
'translation.get.success': 'Translation retrieved successfully',
|
|
178
|
+
'translation.get.all.success': 'Translations retrieved successfully',
|
|
179
|
+
'translation.update.success': 'Translation updated successfully',
|
|
180
|
+
'translation.update.many.success': '{{count}} translations updated successfully',
|
|
181
|
+
'translation.delete.success': 'Translation deleted successfully',
|
|
182
|
+
'translation.restore.success': 'Translation restored successfully',
|
|
183
|
+
'translation.not.found': 'Translation not found',
|
|
184
|
+
'translation.by.language.success': 'Translations retrieved successfully',
|
|
185
|
+
'translation.by.module.success': 'Translations by module retrieved successfully',
|
|
186
|
+
'translation.missing.success': 'Missing translations retrieved successfully',
|
|
187
|
+
'translation.sync.success': 'Translations synced successfully',
|
|
188
|
+
'translation.update.values.success': 'Translation values updated successfully',
|
|
189
|
+
// Validation messages
|
|
190
|
+
'localization.validation.code.required': 'Language code is required',
|
|
191
|
+
'localization.validation.code.max.length': 'Language code must be at most 10 characters',
|
|
192
|
+
'localization.validation.name.required': 'Language name is required',
|
|
193
|
+
'localization.validation.name.max.length': 'Language name must be at most 100 characters',
|
|
194
|
+
'localization.validation.key.required': 'Translation key is required',
|
|
195
|
+
'localization.validation.module.required': 'Module is required',
|
|
196
|
+
'localization.validation.default.message.required': 'Default message is required',
|
|
197
|
+
// Additional success messages
|
|
198
|
+
'localization.key.create.success': 'Translation key created successfully',
|
|
199
|
+
'localization.key.update.success': 'Translation key updated successfully',
|
|
200
|
+
'localization.key.delete.success': 'Translation key deleted successfully',
|
|
201
|
+
'localization.language.delete.success': 'Language deleted successfully',
|
|
202
|
+
'localization.language.load.failed': 'Failed to load languages',
|
|
203
|
+
'localization.key.load.failed': 'Failed to load translation keys',
|
|
204
|
+
// Translation key operation keys (used by form components)
|
|
205
|
+
'localization.translation.key.create.success': 'Translation key created successfully',
|
|
206
|
+
'localization.translation.key.update.success': 'Translation key updated successfully',
|
|
207
|
+
'localization.translation.key.delete.success': 'Translation key deleted successfully',
|
|
208
|
+
// Pagination templates
|
|
209
|
+
'localization.pagination.languages.template': 'Showing {first} to {last} of {totalRecords} languages',
|
|
210
|
+
'localization.pagination.keys.template': 'Showing {first} to {last} of {totalRecords} keys',
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
class LocalizationStateService {
|
|
214
|
+
platformId = inject(PLATFORM_ID);
|
|
215
|
+
document = inject(DOCUMENT);
|
|
216
|
+
appRef = inject(ApplicationRef);
|
|
217
|
+
primeNG = inject(PrimeNG);
|
|
218
|
+
_loadedModules = new Set();
|
|
219
|
+
_moduleFallbacks = new Map();
|
|
220
|
+
isBrowser = isPlatformBrowser(this.platformId);
|
|
221
|
+
_currentLanguage = signal(null, ...(ngDevMode ? [{ debugName: "_currentLanguage" }] : []));
|
|
222
|
+
_availableLanguages = signal([], ...(ngDevMode ? [{ debugName: "_availableLanguages" }] : []));
|
|
223
|
+
_translations = signal({}, ...(ngDevMode ? [{ debugName: "_translations" }] : []));
|
|
224
|
+
_fallbackMessages = signal({}, ...(ngDevMode ? [{ debugName: "_fallbackMessages" }] : []));
|
|
225
|
+
_isLoading = signal(false, ...(ngDevMode ? [{ debugName: "_isLoading" }] : []));
|
|
226
|
+
_isInitialized = signal(false, ...(ngDevMode ? [{ debugName: "_isInitialized" }] : []));
|
|
227
|
+
currentLanguage = this._currentLanguage.asReadonly();
|
|
228
|
+
availableLanguages = this._availableLanguages.asReadonly();
|
|
229
|
+
translations = this._translations.asReadonly();
|
|
230
|
+
fallbackMessages = this._fallbackMessages.asReadonly();
|
|
231
|
+
isLoading = this._isLoading.asReadonly();
|
|
232
|
+
isInitialized = this._isInitialized.asReadonly();
|
|
233
|
+
currentLanguageCode = computed(() => this._currentLanguage()?.code ?? 'en', ...(ngDevMode ? [{ debugName: "currentLanguageCode" }] : []));
|
|
234
|
+
isRtl = computed(() => this._currentLanguage()?.direction === 'rtl', ...(ngDevMode ? [{ debugName: "isRtl" }] : []));
|
|
235
|
+
constructor() {
|
|
236
|
+
effect(() => {
|
|
237
|
+
const language = this._currentLanguage();
|
|
238
|
+
if (language && this.isBrowser) {
|
|
239
|
+
this.document.documentElement.dir = language.direction ?? 'ltr';
|
|
240
|
+
this.document.documentElement.lang = language.code;
|
|
241
|
+
localStorage.setItem(STORAGE_KEYS.CURRENT_LANGUAGE, language.code);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
// Trigger zoneless change detection when translations update
|
|
245
|
+
effect(() => {
|
|
246
|
+
this._translations();
|
|
247
|
+
setTimeout(() => this.appRef.tick(), 0);
|
|
248
|
+
});
|
|
249
|
+
effect(() => {
|
|
250
|
+
const translations = this._translations();
|
|
251
|
+
const fallbacks = this._fallbackMessages();
|
|
252
|
+
this.syncPrimeNGTranslations(translations, fallbacks);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
dotToCamel(str) {
|
|
256
|
+
return str.replace(/\.([a-z])/g, (_, c) => c.toUpperCase());
|
|
257
|
+
}
|
|
258
|
+
syncPrimeNGTranslations(translations, fallbacks) {
|
|
259
|
+
const primeNGTranslations = {};
|
|
260
|
+
const ariaTranslations = {};
|
|
261
|
+
const prefix = 'primeng.';
|
|
262
|
+
const ariaPrefix = 'primeng.aria.';
|
|
263
|
+
const allMessages = { ...fallbacks, ...translations };
|
|
264
|
+
for (const [key, value] of Object.entries(allMessages)) {
|
|
265
|
+
if (key.startsWith(ariaPrefix)) {
|
|
266
|
+
const ariaKey = this.dotToCamel(key.substring(ariaPrefix.length));
|
|
267
|
+
ariaTranslations[ariaKey] = value;
|
|
268
|
+
}
|
|
269
|
+
else if (key.startsWith(prefix)) {
|
|
270
|
+
const primeKey = this.dotToCamel(key.substring(prefix.length));
|
|
271
|
+
primeNGTranslations[primeKey] = value;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (Object.keys(ariaTranslations).length > 0) {
|
|
275
|
+
primeNGTranslations['aria'] = ariaTranslations;
|
|
276
|
+
}
|
|
277
|
+
if (Object.keys(primeNGTranslations).length > 0) {
|
|
278
|
+
this.primeNG.setTranslation(primeNGTranslations);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
setCurrentLanguage(language) {
|
|
282
|
+
this._currentLanguage.set(language);
|
|
283
|
+
}
|
|
284
|
+
setAvailableLanguages(languages) {
|
|
285
|
+
this._availableLanguages.set(languages);
|
|
286
|
+
}
|
|
287
|
+
setTranslations(translations) {
|
|
288
|
+
this._translations.set(translations);
|
|
289
|
+
}
|
|
290
|
+
mergeTranslations(translations) {
|
|
291
|
+
this._translations.update((current) => ({ ...current, ...translations }));
|
|
292
|
+
}
|
|
293
|
+
setLoading(loading) {
|
|
294
|
+
this._isLoading.set(loading);
|
|
295
|
+
}
|
|
296
|
+
setInitialized(initialized) {
|
|
297
|
+
this._isInitialized.set(initialized);
|
|
298
|
+
}
|
|
299
|
+
getSavedLanguageCode() {
|
|
300
|
+
if (!this.isBrowser)
|
|
301
|
+
return null;
|
|
302
|
+
return localStorage.getItem(STORAGE_KEYS.CURRENT_LANGUAGE);
|
|
303
|
+
}
|
|
304
|
+
isModuleLoaded(module) {
|
|
305
|
+
return this._loadedModules.has(module);
|
|
306
|
+
}
|
|
307
|
+
markModuleLoaded(module) {
|
|
308
|
+
this._loadedModules.add(module);
|
|
309
|
+
}
|
|
310
|
+
getLoadedModules() {
|
|
311
|
+
return Array.from(this._loadedModules);
|
|
312
|
+
}
|
|
313
|
+
clearLoadedModules() {
|
|
314
|
+
this._loadedModules.clear();
|
|
315
|
+
}
|
|
316
|
+
registerModuleFallbacks(module, messages) {
|
|
317
|
+
this._moduleFallbacks.set(module, messages);
|
|
318
|
+
this._fallbackMessages.update((current) => ({ ...current, ...messages }));
|
|
319
|
+
}
|
|
320
|
+
hasModuleFallbacks(module) {
|
|
321
|
+
return this._moduleFallbacks.has(module);
|
|
322
|
+
}
|
|
323
|
+
static ɵfac = function LocalizationStateService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationStateService)(); };
|
|
324
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationStateService, factory: LocalizationStateService.ɵfac, providedIn: 'root' });
|
|
325
|
+
}
|
|
326
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationStateService, [{
|
|
327
|
+
type: Injectable,
|
|
328
|
+
args: [{ providedIn: 'root' }]
|
|
329
|
+
}], () => [], null); })();
|
|
330
|
+
|
|
331
|
+
class LocalizationApiService {
|
|
332
|
+
http = inject(HttpClient);
|
|
333
|
+
appConfig = inject(APP_CONFIG);
|
|
334
|
+
get baseUrl() {
|
|
335
|
+
return `${this.appConfig.apiBaseUrl}/localization`;
|
|
336
|
+
}
|
|
337
|
+
getActiveLanguages() {
|
|
338
|
+
return this.http.post(`${this.baseUrl}/language/get-active`, {});
|
|
339
|
+
}
|
|
340
|
+
getTranslationsByLanguage(languageCode, modules) {
|
|
341
|
+
return this.http.post(`${this.baseUrl}/translation/get-by-language`, { languageCode, ...(modules?.length ? { modules } : {}) });
|
|
342
|
+
}
|
|
343
|
+
static ɵfac = function LocalizationApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationApiService)(); };
|
|
344
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationApiService, factory: LocalizationApiService.ɵfac, providedIn: 'root' });
|
|
345
|
+
}
|
|
346
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationApiService, [{
|
|
347
|
+
type: Injectable,
|
|
348
|
+
args: [{ providedIn: 'root' }]
|
|
349
|
+
}], null, null); })();
|
|
350
|
+
|
|
351
|
+
class LocalizationInitializerService {
|
|
352
|
+
config = inject(LOCALIZATION_CONFIG, { optional: true });
|
|
353
|
+
apiService = inject(LocalizationApiService);
|
|
354
|
+
stateService = inject(LocalizationStateService);
|
|
355
|
+
async initialize() {
|
|
356
|
+
if (!this.config) {
|
|
357
|
+
this.stateService.setInitialized(true);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
this.stateService.setLoading(true);
|
|
362
|
+
const languagesResponse = await firstValueFrom(this.apiService.getActiveLanguages());
|
|
363
|
+
if (languagesResponse.success && languagesResponse.data) {
|
|
364
|
+
this.stateService.setAvailableLanguages(languagesResponse.data);
|
|
365
|
+
const savedCode = this.stateService.getSavedLanguageCode();
|
|
366
|
+
let selectedLanguage = languagesResponse.data.find((l) => l.code === savedCode);
|
|
367
|
+
if (!selectedLanguage) {
|
|
368
|
+
selectedLanguage = languagesResponse.data.find((l) => l.isDefault);
|
|
369
|
+
}
|
|
370
|
+
if (!selectedLanguage && languagesResponse.data.length > 0) {
|
|
371
|
+
selectedLanguage = languagesResponse.data[0];
|
|
372
|
+
}
|
|
373
|
+
if (selectedLanguage) {
|
|
374
|
+
this.stateService.setCurrentLanguage(selectedLanguage);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
// Silently fail - use default language
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
this.stateService.setLoading(false);
|
|
383
|
+
this.stateService.setInitialized(true);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
static ɵfac = function LocalizationInitializerService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationInitializerService)(); };
|
|
387
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationInitializerService, factory: LocalizationInitializerService.ɵfac, providedIn: 'root' });
|
|
388
|
+
}
|
|
389
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationInitializerService, [{
|
|
390
|
+
type: Injectable,
|
|
391
|
+
args: [{ providedIn: 'root' }]
|
|
392
|
+
}], null, null); })();
|
|
393
|
+
|
|
394
|
+
class TranslateService {
|
|
395
|
+
localizationState = inject(LocalizationStateService);
|
|
396
|
+
localizationConfig = inject(LOCALIZATION_CONFIG, { optional: true });
|
|
397
|
+
languageCode = this.localizationState.currentLanguageCode;
|
|
398
|
+
translate(key, params) {
|
|
399
|
+
if (!this.localizationConfig) {
|
|
400
|
+
return this.getFromFallback(key, params);
|
|
401
|
+
}
|
|
402
|
+
const translations = this.localizationState.translations();
|
|
403
|
+
const value = translations[key];
|
|
404
|
+
if (!value) {
|
|
405
|
+
return this.getFromFallback(key, params);
|
|
406
|
+
}
|
|
407
|
+
return this.interpolate(value, params);
|
|
408
|
+
}
|
|
409
|
+
translateSignal(key, params) {
|
|
410
|
+
return computed(() => {
|
|
411
|
+
this.localizationState.currentLanguage();
|
|
412
|
+
return this.translate(key, params);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
instant(key, params) {
|
|
416
|
+
return this.translate(key, params);
|
|
417
|
+
}
|
|
418
|
+
interpolate(template, params) {
|
|
419
|
+
if (!params || !template)
|
|
420
|
+
return template;
|
|
421
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, paramKey) => {
|
|
422
|
+
const value = params[paramKey];
|
|
423
|
+
return value !== undefined ? String(value) : match;
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
getFromFallback(key, params) {
|
|
427
|
+
const fallbacks = this.localizationState.fallbackMessages();
|
|
428
|
+
const value = fallbacks[key] ?? key;
|
|
429
|
+
return this.interpolate(value, params);
|
|
430
|
+
}
|
|
431
|
+
static ɵfac = function TranslateService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslateService)(); };
|
|
432
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslateService, factory: TranslateService.ɵfac, providedIn: 'root' });
|
|
433
|
+
}
|
|
434
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslateService, [{
|
|
435
|
+
type: Injectable,
|
|
436
|
+
args: [{ providedIn: 'root' }]
|
|
437
|
+
}], null, null); })();
|
|
438
|
+
|
|
439
|
+
class TranslationLoaderService {
|
|
440
|
+
DEFAULT_INITIAL_MODULES = ['shared', 'layout'];
|
|
441
|
+
config = inject(LOCALIZATION_CONFIG, { optional: true });
|
|
442
|
+
apiService = inject(LocalizationApiService);
|
|
443
|
+
stateService = inject(LocalizationStateService);
|
|
444
|
+
async loadTranslations(languageCode, clearModules = false) {
|
|
445
|
+
const strategy = this.config?.loadStrategy ?? 'all';
|
|
446
|
+
// Save currently loaded modules before clearing (for language switch)
|
|
447
|
+
const previouslyLoadedModules = clearModules ? this.stateService.getLoadedModules() : [];
|
|
448
|
+
if (clearModules) {
|
|
449
|
+
this.stateService.clearLoadedModules();
|
|
450
|
+
}
|
|
451
|
+
this.stateService.setLoading(true);
|
|
452
|
+
try {
|
|
453
|
+
if (strategy === 'all') {
|
|
454
|
+
await this.loadAndSetTranslations(languageCode);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
const modules = this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;
|
|
458
|
+
await this.loadAndSetTranslations(languageCode, modules);
|
|
459
|
+
// Reload all previously loaded modules for the new language
|
|
460
|
+
if (previouslyLoadedModules.length > 0) {
|
|
461
|
+
await this.reloadModules(languageCode, previouslyLoadedModules);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
finally {
|
|
466
|
+
this.stateService.setLoading(false);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
async loadAndSetTranslations(languageCode, modules) {
|
|
470
|
+
const response = await firstValueFrom(this.apiService.getTranslationsByLanguage(languageCode, modules));
|
|
471
|
+
if (response.success && response.data) {
|
|
472
|
+
this.stateService.setTranslations(response.data);
|
|
473
|
+
if (modules) {
|
|
474
|
+
modules.forEach((m) => this.stateService.markModuleLoaded(m));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async loadModulesOnDemand(languageCode, modules) {
|
|
479
|
+
const modulesToLoad = modules.filter((m) => !this.stateService.isModuleLoaded(m));
|
|
480
|
+
if (modulesToLoad.length === 0)
|
|
481
|
+
return;
|
|
482
|
+
const response = await firstValueFrom(this.apiService.getTranslationsByLanguage(languageCode, modulesToLoad));
|
|
483
|
+
if (response.success && response.data) {
|
|
484
|
+
this.stateService.mergeTranslations(response.data);
|
|
485
|
+
modulesToLoad.forEach((m) => this.stateService.markModuleLoaded(m));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async reloadModules(languageCode, modules) {
|
|
489
|
+
const initialModules = this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;
|
|
490
|
+
const additionalModules = modules.filter((m) => !initialModules.includes(m));
|
|
491
|
+
if (additionalModules.length === 0)
|
|
492
|
+
return;
|
|
493
|
+
const response = await firstValueFrom(this.apiService.getTranslationsByLanguage(languageCode, additionalModules));
|
|
494
|
+
if (response.success && response.data) {
|
|
495
|
+
this.stateService.mergeTranslations(response.data);
|
|
496
|
+
additionalModules.forEach((m) => this.stateService.markModuleLoaded(m));
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
loadTranslationsAsync(languageCode, clearModules = false) {
|
|
500
|
+
return from(this.loadTranslations(languageCode, clearModules));
|
|
501
|
+
}
|
|
502
|
+
static ɵfac = function TranslationLoaderService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationLoaderService)(); };
|
|
503
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslationLoaderService, factory: TranslationLoaderService.ɵfac, providedIn: 'root' });
|
|
504
|
+
}
|
|
505
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationLoaderService, [{
|
|
506
|
+
type: Injectable,
|
|
507
|
+
args: [{ providedIn: 'root' }]
|
|
508
|
+
}], null, null); })();
|
|
509
|
+
|
|
510
|
+
class LanguageApiService {
|
|
511
|
+
http = inject(HttpClient);
|
|
512
|
+
appConfig = inject(APP_CONFIG);
|
|
513
|
+
get baseUrl() {
|
|
514
|
+
return `${this.appConfig.apiBaseUrl}/localization/language`;
|
|
515
|
+
}
|
|
516
|
+
getAll() {
|
|
517
|
+
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
518
|
+
pagination: { currentPage: 0, pageSize: 100 },
|
|
519
|
+
filter: {},
|
|
520
|
+
sort: { serial: 'ASC', name: 'ASC' },
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
getById(id) {
|
|
524
|
+
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
525
|
+
}
|
|
526
|
+
create(dto) {
|
|
527
|
+
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
528
|
+
}
|
|
529
|
+
update(dto) {
|
|
530
|
+
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
531
|
+
}
|
|
532
|
+
delete(id) {
|
|
533
|
+
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
534
|
+
}
|
|
535
|
+
setDefault(id) {
|
|
536
|
+
return this.http.post(`${this.baseUrl}/set-default`, { id });
|
|
537
|
+
}
|
|
538
|
+
static ɵfac = function LanguageApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageApiService)(); };
|
|
539
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LanguageApiService, factory: LanguageApiService.ɵfac, providedIn: 'root' });
|
|
540
|
+
}
|
|
541
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageApiService, [{
|
|
542
|
+
type: Injectable,
|
|
543
|
+
args: [{ providedIn: 'root' }]
|
|
544
|
+
}], null, null); })();
|
|
545
|
+
|
|
546
|
+
class TranslationKeyApiService {
|
|
547
|
+
http = inject(HttpClient);
|
|
548
|
+
appConfig = inject(APP_CONFIG);
|
|
549
|
+
get baseUrl() {
|
|
550
|
+
return `${this.appConfig.apiBaseUrl}/localization/translation-key`;
|
|
551
|
+
}
|
|
552
|
+
getAll(filter = {}) {
|
|
553
|
+
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
554
|
+
pagination: { currentPage: 0, pageSize: 1000 },
|
|
555
|
+
filter,
|
|
556
|
+
sort: { module: 'ASC', key: 'ASC' },
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
getByModule(module) {
|
|
560
|
+
return this.http.post(`${this.baseUrl}/get-by-module`, {
|
|
561
|
+
module,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
getModules() {
|
|
565
|
+
return this.http.post(`${this.baseUrl}/get-modules`, {});
|
|
566
|
+
}
|
|
567
|
+
getById(id) {
|
|
568
|
+
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
569
|
+
}
|
|
570
|
+
create(dto) {
|
|
571
|
+
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
572
|
+
}
|
|
573
|
+
createMany(dtos) {
|
|
574
|
+
return this.http.post(`${this.baseUrl}/insert-many`, { items: dtos });
|
|
575
|
+
}
|
|
576
|
+
update(dto) {
|
|
577
|
+
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
578
|
+
}
|
|
579
|
+
delete(id) {
|
|
580
|
+
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
581
|
+
}
|
|
582
|
+
static ɵfac = function TranslationKeyApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationKeyApiService)(); };
|
|
583
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslationKeyApiService, factory: TranslationKeyApiService.ɵfac, providedIn: 'root' });
|
|
584
|
+
}
|
|
585
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationKeyApiService, [{
|
|
586
|
+
type: Injectable,
|
|
587
|
+
args: [{ providedIn: 'root' }]
|
|
588
|
+
}], null, null); })();
|
|
589
|
+
|
|
590
|
+
class TranslationApiService {
|
|
591
|
+
http = inject(HttpClient);
|
|
592
|
+
appConfig = inject(APP_CONFIG);
|
|
593
|
+
get baseUrl() {
|
|
594
|
+
return `${this.appConfig.apiBaseUrl}/localization/translation`;
|
|
595
|
+
}
|
|
596
|
+
getByLanguageId(languageId) {
|
|
597
|
+
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
598
|
+
pagination: { currentPage: 0, pageSize: 10000 },
|
|
599
|
+
filter: { languageId },
|
|
600
|
+
sort: {},
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
getByModuleAndLanguageId(module, languageId) {
|
|
604
|
+
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
605
|
+
pagination: { currentPage: 0, pageSize: 10000 },
|
|
606
|
+
filter: { languageId, module },
|
|
607
|
+
sort: {},
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
getById(id) {
|
|
611
|
+
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
612
|
+
}
|
|
613
|
+
create(dto) {
|
|
614
|
+
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
615
|
+
}
|
|
616
|
+
update(dto) {
|
|
617
|
+
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
618
|
+
}
|
|
619
|
+
bulkUpdate(translations) {
|
|
620
|
+
return this.http.post(`${this.baseUrl}/update-many-values`, { translations });
|
|
621
|
+
}
|
|
622
|
+
delete(id) {
|
|
623
|
+
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
624
|
+
}
|
|
625
|
+
getByKeyId(translationKeyId) {
|
|
626
|
+
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
627
|
+
pagination: { currentPage: 0, pageSize: 1000 },
|
|
628
|
+
filter: { translationKeyId },
|
|
629
|
+
sort: {},
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
getCounts() {
|
|
633
|
+
return this.http.post(`${this.baseUrl}/get-counts`, {});
|
|
634
|
+
}
|
|
635
|
+
static ɵfac = function TranslationApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationApiService)(); };
|
|
636
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslationApiService, factory: TranslationApiService.ɵfac, providedIn: 'root' });
|
|
637
|
+
}
|
|
638
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationApiService, [{
|
|
639
|
+
type: Injectable,
|
|
640
|
+
args: [{ providedIn: 'root' }]
|
|
641
|
+
}], null, null); })();
|
|
642
|
+
|
|
643
|
+
const _forTrack0$3 = ($index, $item) => $item.id;
|
|
644
|
+
function LanguageSelectorComponent_For_7_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
645
|
+
i0.ɵɵelement(0, "i", 9);
|
|
646
|
+
} }
|
|
647
|
+
function LanguageSelectorComponent_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
648
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
649
|
+
i0.ɵɵelementStart(0, "button", 6);
|
|
650
|
+
i0.ɵɵlistener("click", function LanguageSelectorComponent_For_7_Template_button_click_0_listener() { const lang_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onLanguageSelect(lang_r2.code)); });
|
|
651
|
+
i0.ɵɵelementStart(1, "span", 7);
|
|
652
|
+
i0.ɵɵtext(2);
|
|
653
|
+
i0.ɵɵelementEnd();
|
|
654
|
+
i0.ɵɵelementStart(3, "span", 8);
|
|
655
|
+
i0.ɵɵtext(4);
|
|
656
|
+
i0.ɵɵelementEnd();
|
|
657
|
+
i0.ɵɵconditionalCreate(5, LanguageSelectorComponent_For_7_Conditional_5_Template, 1, 0, "i", 9);
|
|
658
|
+
i0.ɵɵelementEnd();
|
|
659
|
+
} if (rf & 2) {
|
|
660
|
+
const lang_r2 = ctx.$implicit;
|
|
661
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
662
|
+
i0.ɵɵclassProp("bg-primary-50", lang_r2.code === ctx_r2.selectedLanguageCode())("text-primary", lang_r2.code === ctx_r2.selectedLanguageCode());
|
|
663
|
+
i0.ɵɵadvance(2);
|
|
664
|
+
i0.ɵɵtextInterpolate(lang_r2.nativeName || lang_r2.name);
|
|
665
|
+
i0.ɵɵadvance(2);
|
|
666
|
+
i0.ɵɵtextInterpolate1("(", lang_r2.code, ")");
|
|
667
|
+
i0.ɵɵadvance();
|
|
668
|
+
i0.ɵɵconditional(lang_r2.code === ctx_r2.selectedLanguageCode() ? 5 : -1);
|
|
669
|
+
} }
|
|
670
|
+
class LanguageSelectorComponent {
|
|
671
|
+
localizationState = inject(LocalizationStateService);
|
|
672
|
+
translationLoader = inject(TranslationLoaderService);
|
|
673
|
+
destroyRef = inject(DestroyRef);
|
|
674
|
+
document = inject(DOCUMENT);
|
|
675
|
+
elementRef = inject(ElementRef);
|
|
676
|
+
languages = this.localizationState.availableLanguages;
|
|
677
|
+
_isActive = signal(false, ...(ngDevMode ? [{ debugName: "_isActive" }] : []));
|
|
678
|
+
isActive = this._isActive.asReadonly();
|
|
679
|
+
selectedLanguageCode = this.localizationState.currentLanguageCode;
|
|
680
|
+
selectedLanguage = computed(() => this.languages().find((l) => l.code === this.selectedLanguageCode()) ?? null, ...(ngDevMode ? [{ debugName: "selectedLanguage" }] : []));
|
|
681
|
+
constructor() {
|
|
682
|
+
fromEvent(this.document, 'click')
|
|
683
|
+
.pipe(takeUntilDestroyed(this.destroyRef), filter(() => this._isActive()))
|
|
684
|
+
.subscribe((event) => {
|
|
685
|
+
const target = event.target;
|
|
686
|
+
if (!this.elementRef.nativeElement.contains(target)) {
|
|
687
|
+
this._isActive.set(false);
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
togglePanel() {
|
|
692
|
+
this._isActive.update((v) => !v);
|
|
693
|
+
}
|
|
694
|
+
onLanguageSelect(code) {
|
|
695
|
+
const language = this.languages().find((l) => l.code === code);
|
|
696
|
+
if (language) {
|
|
697
|
+
this.localizationState.setCurrentLanguage(language);
|
|
698
|
+
this._isActive.set(false);
|
|
699
|
+
this.translationLoader
|
|
700
|
+
.loadTranslationsAsync(code, true)
|
|
701
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
702
|
+
.subscribe();
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
static ɵfac = function LanguageSelectorComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageSelectorComponent)(); };
|
|
706
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LanguageSelectorComponent, selectors: [["lib-language-selector"]], hostAttrs: [1, "relative"], decls: 8, vars: 4, consts: [["type", "button", "pStyleClass", "@next", "enterFromClass", "hidden", "enterActiveClass", "animate-scalein", "leaveToClass", "hidden", "leaveActiveClass", "animate-fadeout", 1, "layout-topbar-action", 3, "click", "hideOnOutsideClick"], [1, "pi", "pi-globe"], [1, "font-semibold"], [1, "hidden", "absolute", "top-[3.25rem]", "z-50", "p-3", "border", "border-surface", "rounded-border", "origin-top", "shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]", "min-w-[180px]", 2, "background-color", "var(--surface-overlay)", "inset-inline-end", "0"], [1, "flex", "flex-col"], ["type", "button", 1, "flex", "items-center", "gap-3", "px-3", "py-2.5", "rounded-border", "cursor-pointer", "transition-all", "duration-200", "text-left", "w-full", "border-none", "bg-transparent", "hover:bg-emphasis", 3, "bg-primary-50", "text-primary"], ["type", "button", 1, "flex", "items-center", "gap-3", "px-3", "py-2.5", "rounded-border", "cursor-pointer", "transition-all", "duration-200", "text-left", "w-full", "border-none", "bg-transparent", "hover:bg-emphasis", 3, "click"], [1, "font-medium", "flex-1"], [1, "text-xs", "text-muted-color", "uppercase"], [1, "pi", "pi-check", "text-primary", "text-sm"]], template: function LanguageSelectorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
707
|
+
i0.ɵɵelementStart(0, "button", 0);
|
|
708
|
+
i0.ɵɵlistener("click", function LanguageSelectorComponent_Template_button_click_0_listener() { return ctx.togglePanel(); });
|
|
709
|
+
i0.ɵɵelement(1, "i", 1);
|
|
710
|
+
i0.ɵɵelementStart(2, "span", 2);
|
|
711
|
+
i0.ɵɵtext(3);
|
|
712
|
+
i0.ɵɵelementEnd()();
|
|
713
|
+
i0.ɵɵelementStart(4, "div", 3)(5, "div", 4);
|
|
714
|
+
i0.ɵɵrepeaterCreate(6, LanguageSelectorComponent_For_7_Template, 6, 7, "button", 5, _forTrack0$3);
|
|
715
|
+
i0.ɵɵelementEnd()();
|
|
716
|
+
} if (rf & 2) {
|
|
717
|
+
let tmp_2_0;
|
|
718
|
+
i0.ɵɵclassProp("layout-topbar-action-highlight", ctx.isActive());
|
|
719
|
+
i0.ɵɵproperty("hideOnOutsideClick", true);
|
|
720
|
+
i0.ɵɵadvance(3);
|
|
721
|
+
i0.ɵɵtextInterpolate(((tmp_2_0 = ctx.selectedLanguage()) == null ? null : tmp_2_0.nativeName) || ((tmp_2_0 = ctx.selectedLanguage()) == null ? null : tmp_2_0.name) || ctx.selectedLanguageCode());
|
|
722
|
+
i0.ɵɵadvance(3);
|
|
723
|
+
i0.ɵɵrepeater(ctx.languages());
|
|
724
|
+
} }, dependencies: [StyleClassModule, i1.StyleClass], encapsulation: 2 });
|
|
725
|
+
}
|
|
726
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageSelectorComponent, [{
|
|
727
|
+
type: Component,
|
|
728
|
+
args: [{
|
|
729
|
+
selector: 'lib-language-selector',
|
|
730
|
+
imports: [StyleClassModule],
|
|
731
|
+
host: { class: 'relative' },
|
|
732
|
+
template: `
|
|
733
|
+
<button
|
|
734
|
+
type="button"
|
|
735
|
+
class="layout-topbar-action"
|
|
736
|
+
[class.layout-topbar-action-highlight]="isActive()"
|
|
737
|
+
pStyleClass="@next"
|
|
738
|
+
enterFromClass="hidden"
|
|
739
|
+
enterActiveClass="animate-scalein"
|
|
740
|
+
leaveToClass="hidden"
|
|
741
|
+
leaveActiveClass="animate-fadeout"
|
|
742
|
+
[hideOnOutsideClick]="true"
|
|
743
|
+
(click)="togglePanel()">
|
|
744
|
+
<i class="pi pi-globe"></i>
|
|
745
|
+
<span class="font-semibold">{{ selectedLanguage()?.nativeName || selectedLanguage()?.name || selectedLanguageCode() }}</span>
|
|
746
|
+
</button>
|
|
747
|
+
<div
|
|
748
|
+
class="hidden absolute top-[3.25rem] z-50 p-3 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] min-w-[180px]"
|
|
749
|
+
style="background-color: var(--surface-overlay); inset-inline-end: 0;">
|
|
750
|
+
<div class="flex flex-col">
|
|
751
|
+
@for (lang of languages(); track lang.id) {
|
|
752
|
+
<button
|
|
753
|
+
type="button"
|
|
754
|
+
class="flex items-center gap-3 px-3 py-2.5 rounded-border cursor-pointer transition-all duration-200 text-left w-full border-none bg-transparent hover:bg-emphasis"
|
|
755
|
+
[class.bg-primary-50]="lang.code === selectedLanguageCode()"
|
|
756
|
+
[class.text-primary]="lang.code === selectedLanguageCode()"
|
|
757
|
+
(click)="onLanguageSelect(lang.code)">
|
|
758
|
+
<span class="font-medium flex-1">{{ lang.nativeName || lang.name }}</span>
|
|
759
|
+
<span class="text-xs text-muted-color uppercase">({{ lang.code }})</span>
|
|
760
|
+
@if (lang.code === selectedLanguageCode()) {
|
|
761
|
+
<i class="pi pi-check text-primary text-sm"></i>
|
|
762
|
+
}
|
|
763
|
+
</button>
|
|
764
|
+
}
|
|
765
|
+
</div>
|
|
766
|
+
</div>
|
|
767
|
+
`,
|
|
768
|
+
}]
|
|
769
|
+
}], () => [], null); })();
|
|
770
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LanguageSelectorComponent, { className: "LanguageSelectorComponent", filePath: "components/language-selector/language-selector.component.ts", lineNumber: 51 }); })();
|
|
771
|
+
|
|
772
|
+
const _forTrack0$2 = ($index, $item) => $item.id;
|
|
773
|
+
function LanguageSelectorPanelComponent_For_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
774
|
+
i0.ɵɵdomElement(0, "i", 5);
|
|
775
|
+
} }
|
|
776
|
+
function LanguageSelectorPanelComponent_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
777
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
778
|
+
i0.ɵɵdomElementStart(0, "button", 2);
|
|
779
|
+
i0.ɵɵdomListener("click", function LanguageSelectorPanelComponent_For_2_Template_button_click_0_listener() { const lang_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onLanguageSelect(lang_r2.code)); });
|
|
780
|
+
i0.ɵɵdomElementStart(1, "span", 3);
|
|
781
|
+
i0.ɵɵtext(2);
|
|
782
|
+
i0.ɵɵdomElementEnd();
|
|
783
|
+
i0.ɵɵdomElementStart(3, "span", 4);
|
|
784
|
+
i0.ɵɵtext(4);
|
|
785
|
+
i0.ɵɵdomElementEnd();
|
|
786
|
+
i0.ɵɵconditionalCreate(5, LanguageSelectorPanelComponent_For_2_Conditional_5_Template, 1, 0, "i", 5);
|
|
787
|
+
i0.ɵɵdomElementEnd();
|
|
788
|
+
} if (rf & 2) {
|
|
789
|
+
const lang_r2 = ctx.$implicit;
|
|
790
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
791
|
+
i0.ɵɵclassProp("bg-primary-50", lang_r2.code === ctx_r2.selectedLanguageCode())("text-primary", lang_r2.code === ctx_r2.selectedLanguageCode());
|
|
792
|
+
i0.ɵɵadvance(2);
|
|
793
|
+
i0.ɵɵtextInterpolate(lang_r2.nativeName || lang_r2.name);
|
|
794
|
+
i0.ɵɵadvance(2);
|
|
795
|
+
i0.ɵɵtextInterpolate1("(", lang_r2.code, ")");
|
|
796
|
+
i0.ɵɵadvance();
|
|
797
|
+
i0.ɵɵconditional(lang_r2.code === ctx_r2.selectedLanguageCode() ? 5 : -1);
|
|
798
|
+
} }
|
|
799
|
+
class LanguageSelectorPanelComponent {
|
|
800
|
+
localizationState = inject(LocalizationStateService);
|
|
801
|
+
translationLoader = inject(TranslationLoaderService);
|
|
802
|
+
destroyRef = inject(DestroyRef);
|
|
803
|
+
languages = this.localizationState.availableLanguages;
|
|
804
|
+
_selectedLanguageCode = signal(this.localizationState.currentLanguageCode(), ...(ngDevMode ? [{ debugName: "_selectedLanguageCode" }] : []));
|
|
805
|
+
selectedLanguageCode = this._selectedLanguageCode.asReadonly();
|
|
806
|
+
constructor() {
|
|
807
|
+
effect(() => {
|
|
808
|
+
const currentCode = this.localizationState.currentLanguageCode();
|
|
809
|
+
if (currentCode !== this._selectedLanguageCode()) {
|
|
810
|
+
this._selectedLanguageCode.set(currentCode);
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
onLanguageSelect(code) {
|
|
815
|
+
const language = this.languages().find((l) => l.code === code);
|
|
816
|
+
if (language) {
|
|
817
|
+
this._selectedLanguageCode.set(code);
|
|
818
|
+
this.localizationState.setCurrentLanguage(language);
|
|
819
|
+
this.translationLoader
|
|
820
|
+
.loadTranslationsAsync(code, true)
|
|
821
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
822
|
+
.subscribe();
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
static ɵfac = function LanguageSelectorPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageSelectorPanelComponent)(); };
|
|
826
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LanguageSelectorPanelComponent, selectors: [["lib-language-selector-panel"]], hostAttrs: [1, "hidden", "absolute", "top-[3.25rem]", "z-50", "p-3", "border", "border-surface", "rounded-border", "origin-top", "shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]", "min-w-[180px]", 2, "background-color", "var(--surface-overlay)", "inset-inline-end", "0"], decls: 3, vars: 0, consts: [[1, "flex", "flex-col"], ["type", "button", 1, "flex", "items-center", "gap-3", "px-3", "py-2.5", "rounded-border", "cursor-pointer", "transition-all", "duration-200", "text-left", "w-full", "border-none", "bg-transparent", "hover:bg-emphasis", 3, "bg-primary-50", "text-primary"], ["type", "button", 1, "flex", "items-center", "gap-3", "px-3", "py-2.5", "rounded-border", "cursor-pointer", "transition-all", "duration-200", "text-left", "w-full", "border-none", "bg-transparent", "hover:bg-emphasis", 3, "click"], [1, "font-medium", "flex-1"], [1, "text-xs", "text-muted-color", "uppercase"], [1, "pi", "pi-check", "text-primary", "text-sm"]], template: function LanguageSelectorPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
827
|
+
i0.ɵɵdomElementStart(0, "div", 0);
|
|
828
|
+
i0.ɵɵrepeaterCreate(1, LanguageSelectorPanelComponent_For_2_Template, 6, 7, "button", 1, _forTrack0$2);
|
|
829
|
+
i0.ɵɵdomElementEnd();
|
|
830
|
+
} if (rf & 2) {
|
|
831
|
+
i0.ɵɵadvance();
|
|
832
|
+
i0.ɵɵrepeater(ctx.languages());
|
|
833
|
+
} }, encapsulation: 2 });
|
|
834
|
+
}
|
|
835
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageSelectorPanelComponent, [{
|
|
836
|
+
type: Component,
|
|
837
|
+
args: [{
|
|
838
|
+
selector: 'lib-language-selector-panel',
|
|
839
|
+
imports: [],
|
|
840
|
+
host: {
|
|
841
|
+
class: 'hidden absolute top-[3.25rem] z-50 p-3 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)] min-w-[180px]',
|
|
842
|
+
style: 'background-color: var(--surface-overlay); inset-inline-end: 0;',
|
|
843
|
+
},
|
|
844
|
+
template: `
|
|
845
|
+
<div class="flex flex-col">
|
|
846
|
+
@for (lang of languages(); track lang.id) {
|
|
847
|
+
<button
|
|
848
|
+
type="button"
|
|
849
|
+
class="flex items-center gap-3 px-3 py-2.5 rounded-border cursor-pointer transition-all duration-200 text-left w-full border-none bg-transparent hover:bg-emphasis"
|
|
850
|
+
[class.bg-primary-50]="lang.code === selectedLanguageCode()"
|
|
851
|
+
[class.text-primary]="lang.code === selectedLanguageCode()"
|
|
852
|
+
(click)="onLanguageSelect(lang.code)">
|
|
853
|
+
<span class="font-medium flex-1">{{ lang.nativeName || lang.name }}</span>
|
|
854
|
+
<span class="text-xs text-muted-color uppercase">({{ lang.code }})</span>
|
|
855
|
+
@if (lang.code === selectedLanguageCode()) {
|
|
856
|
+
<i class="pi pi-check text-primary text-sm"></i>
|
|
857
|
+
}
|
|
858
|
+
</button>
|
|
859
|
+
}
|
|
860
|
+
</div>
|
|
861
|
+
`,
|
|
862
|
+
}]
|
|
863
|
+
}], () => [], null); })();
|
|
864
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LanguageSelectorPanelComponent, { className: "LanguageSelectorPanelComponent", filePath: "components/language-selector-panel/language-selector-panel.component.ts", lineNumber: 33 }); })();
|
|
865
|
+
|
|
866
|
+
function provideLocalization(config) {
|
|
867
|
+
const providers = [
|
|
868
|
+
{ provide: LOCALIZATION_CONFIG, useValue: config },
|
|
869
|
+
LocalizationStateService,
|
|
870
|
+
LocalizationApiService,
|
|
871
|
+
LocalizationInitializerService,
|
|
872
|
+
TranslateService,
|
|
873
|
+
{ provide: TRANSLATE_ADAPTER, useExisting: TranslateService },
|
|
874
|
+
{
|
|
875
|
+
provide: APP_INITIALIZER,
|
|
876
|
+
useFactory: (initializer) => () => initializer.initialize(),
|
|
877
|
+
deps: [LocalizationInitializerService],
|
|
878
|
+
multi: true,
|
|
879
|
+
},
|
|
880
|
+
];
|
|
881
|
+
if (config.enableLayoutSelector) {
|
|
882
|
+
providers.push({ provide: LAYOUT_LANGUAGE_SELECTOR, useValue: LanguageSelectorComponent }, { provide: LAYOUT_LANGUAGE_SELECTOR_PANEL, useValue: LanguageSelectorPanelComponent });
|
|
883
|
+
}
|
|
884
|
+
return providers;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
const LOCALIZATION_ROUTES = [
|
|
888
|
+
{
|
|
889
|
+
path: '',
|
|
890
|
+
resolve: { translations: resolveTranslationModule({ modules: ['localization'], fallbackMessages: { ...LOCALIZATION_MESSAGES, ...SHARED_MESSAGES } }) },
|
|
891
|
+
loadComponent: () => Promise.resolve().then(function () { return localizationContainer_page; }).then((m) => m.LocalizationContainerPage),
|
|
892
|
+
children: [
|
|
893
|
+
{
|
|
894
|
+
path: 'languages',
|
|
895
|
+
loadComponent: () => Promise.resolve().then(function () { return languageList_page; }).then((m) => m.LanguageListPage),
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
path: 'languages/new',
|
|
899
|
+
loadComponent: () => Promise.resolve().then(function () { return languageForm_page; }).then((m) => m.LanguageFormPage),
|
|
900
|
+
},
|
|
901
|
+
{
|
|
902
|
+
path: 'languages/:id',
|
|
903
|
+
loadComponent: () => Promise.resolve().then(function () { return languageForm_page; }).then((m) => m.LanguageFormPage),
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
path: 'keys',
|
|
907
|
+
loadComponent: () => Promise.resolve().then(function () { return translationKeyList_page; }).then((m) => m.TranslationKeyListPage),
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
path: 'keys/new',
|
|
911
|
+
loadComponent: () => Promise.resolve().then(function () { return translationKeyForm_page; }).then((m) => m.TranslationKeyFormPage),
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
path: 'keys/:id',
|
|
915
|
+
loadComponent: () => Promise.resolve().then(function () { return translationKeyForm_page; }).then((m) => m.TranslationKeyFormPage),
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
path: 'translations',
|
|
919
|
+
loadComponent: () => Promise.resolve().then(function () { return translationList_page; }).then((m) => m.TranslationListPage),
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
path: '',
|
|
923
|
+
redirectTo: 'languages',
|
|
924
|
+
pathMatch: 'full',
|
|
925
|
+
},
|
|
926
|
+
],
|
|
927
|
+
},
|
|
928
|
+
];
|
|
929
|
+
|
|
930
|
+
const _forTrack0$1 = ($index, $item) => $item.id;
|
|
931
|
+
function LocalizationContainerPage_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
932
|
+
i0.ɵɵelementStart(0, "a", 5);
|
|
933
|
+
i0.ɵɵelement(1, "i");
|
|
934
|
+
i0.ɵɵelementStart(2, "span");
|
|
935
|
+
i0.ɵɵtext(3);
|
|
936
|
+
i0.ɵɵpipe(4, "translate");
|
|
937
|
+
i0.ɵɵelementEnd()();
|
|
938
|
+
} if (rf & 2) {
|
|
939
|
+
const tab_r1 = ctx.$implicit;
|
|
940
|
+
i0.ɵɵproperty("routerLink", tab_r1.route);
|
|
941
|
+
i0.ɵɵadvance();
|
|
942
|
+
i0.ɵɵclassMap(tab_r1.icon);
|
|
943
|
+
i0.ɵɵadvance(2);
|
|
944
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(4, 4, tab_r1.labelKey));
|
|
945
|
+
} }
|
|
946
|
+
class LocalizationContainerPage {
|
|
947
|
+
permissionValidator = inject(PermissionValidatorService);
|
|
948
|
+
allTabs = [
|
|
949
|
+
{
|
|
950
|
+
id: 'languages',
|
|
951
|
+
labelKey: 'localization.tabs.languages',
|
|
952
|
+
icon: 'pi pi-globe',
|
|
953
|
+
route: 'languages',
|
|
954
|
+
permission: LANGUAGE_PERMISSIONS.READ,
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
id: 'keys',
|
|
958
|
+
labelKey: 'localization.tabs.keys',
|
|
959
|
+
icon: 'pi pi-key',
|
|
960
|
+
route: 'keys',
|
|
961
|
+
permission: TRANSLATION_KEY_PERMISSIONS.READ,
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
id: 'translations',
|
|
965
|
+
labelKey: 'localization.tabs.translations',
|
|
966
|
+
icon: 'pi pi-language',
|
|
967
|
+
route: 'translations',
|
|
968
|
+
permission: TRANSLATION_PERMISSIONS.READ,
|
|
969
|
+
},
|
|
970
|
+
];
|
|
971
|
+
visibleTabs = computed(() => {
|
|
972
|
+
// Explicitly track permissions signal for reactivity
|
|
973
|
+
const permissions = this.permissionValidator.permissions();
|
|
974
|
+
if (!permissions.length)
|
|
975
|
+
return [];
|
|
976
|
+
return this.allTabs.filter((tab) => this.permissionValidator.hasPermission(tab.permission));
|
|
977
|
+
}, ...(ngDevMode ? [{ debugName: "visibleTabs" }] : []));
|
|
978
|
+
static ɵfac = function LocalizationContainerPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationContainerPage)(); };
|
|
979
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LocalizationContainerPage, selectors: [["lib-localization-container"]], decls: 12, vars: 6, consts: [[1, "p-2", "sm:p-4"], [1, "mb-4"], [1, "text-xl", "sm:text-2xl", "font-bold", "m-0"], [1, "text-muted-color", "mt-1", "text-sm", "sm:text-base"], [1, "scrollbar-hide", "flex", "gap-1", "mb-4", "border-b", "border-surface", "overflow-x-auto", "flex-nowrap"], ["routerLinkActive", "tab-active", 1, "flex", "items-center", "gap-2", "px-4", "py-2", "rounded-t-lg", "cursor-pointer", "transition-colors", "text-muted-color", "no-underline", "border-b-2", "border-transparent", "-mb-px", "hover:bg-surface-hover", "[&.tab-active]:text-primary", "[&.tab-active]:border-primary", "[&.tab-active]:bg-surface-ground", "whitespace-nowrap", "shrink-0", 3, "routerLink"]], template: function LocalizationContainerPage_Template(rf, ctx) { if (rf & 1) {
|
|
980
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h1", 2);
|
|
981
|
+
i0.ɵɵtext(3);
|
|
982
|
+
i0.ɵɵpipe(4, "translate");
|
|
983
|
+
i0.ɵɵelementEnd();
|
|
984
|
+
i0.ɵɵelementStart(5, "p", 3);
|
|
985
|
+
i0.ɵɵtext(6);
|
|
986
|
+
i0.ɵɵpipe(7, "translate");
|
|
987
|
+
i0.ɵɵelementEnd()();
|
|
988
|
+
i0.ɵɵelementStart(8, "div", 4);
|
|
989
|
+
i0.ɵɵrepeaterCreate(9, LocalizationContainerPage_For_10_Template, 5, 6, "a", 5, _forTrack0$1);
|
|
990
|
+
i0.ɵɵelementEnd();
|
|
991
|
+
i0.ɵɵelement(11, "router-outlet");
|
|
992
|
+
i0.ɵɵelementEnd();
|
|
993
|
+
} if (rf & 2) {
|
|
994
|
+
i0.ɵɵadvance(3);
|
|
995
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(4, 2, "localization.title"));
|
|
996
|
+
i0.ɵɵadvance(3);
|
|
997
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 4, "localization.subtitle"));
|
|
998
|
+
i0.ɵɵadvance(3);
|
|
999
|
+
i0.ɵɵrepeater(ctx.visibleTabs());
|
|
1000
|
+
} }, dependencies: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], styles: [".scrollbar-hide[_ngcontent-%COMP%]{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide[_ngcontent-%COMP%]::-webkit-scrollbar{display:none}"] });
|
|
1001
|
+
}
|
|
1002
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationContainerPage, [{
|
|
1003
|
+
type: Component,
|
|
1004
|
+
args: [{ selector: 'lib-localization-container', imports: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], template: `
|
|
1005
|
+
<div class="p-2 sm:p-4">
|
|
1006
|
+
<div class="mb-4">
|
|
1007
|
+
<h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'localization.title' | translate }}</h1>
|
|
1008
|
+
<p class="text-muted-color mt-1 text-sm sm:text-base">{{ 'localization.subtitle' | translate }}</p>
|
|
1009
|
+
</div>
|
|
1010
|
+
|
|
1011
|
+
<div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
|
|
1012
|
+
@for (tab of visibleTabs(); track tab.id) {
|
|
1013
|
+
<a
|
|
1014
|
+
[routerLink]="tab.route"
|
|
1015
|
+
routerLinkActive="tab-active"
|
|
1016
|
+
class="flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0"
|
|
1017
|
+
>
|
|
1018
|
+
<i [class]="tab.icon"></i>
|
|
1019
|
+
<span>{{ tab.labelKey | translate }}</span>
|
|
1020
|
+
</a>
|
|
1021
|
+
}
|
|
1022
|
+
</div>
|
|
1023
|
+
|
|
1024
|
+
<router-outlet />
|
|
1025
|
+
</div>
|
|
1026
|
+
`, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"] }]
|
|
1027
|
+
}], null, null); })();
|
|
1028
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LocalizationContainerPage, { className: "LocalizationContainerPage", filePath: "pages/localization-container/localization-container.page.ts", lineNumber: 53 }); })();
|
|
1029
|
+
|
|
1030
|
+
var localizationContainer_page = /*#__PURE__*/Object.freeze({
|
|
1031
|
+
__proto__: null,
|
|
1032
|
+
LocalizationContainerPage: LocalizationContainerPage
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
const _c0$4 = () => ({ "min-width": "40rem" });
|
|
1036
|
+
function LanguageListPage_p_button_9_Template(rf, ctx) { if (rf & 1) {
|
|
1037
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
1038
|
+
i0.ɵɵelementStart(0, "p-button", 10);
|
|
1039
|
+
i0.ɵɵpipe(1, "translate");
|
|
1040
|
+
i0.ɵɵlistener("onClick", function LanguageListPage_p_button_9_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onCreate()); });
|
|
1041
|
+
i0.ɵɵelementEnd();
|
|
1042
|
+
} if (rf & 2) {
|
|
1043
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(1, 1, "localization.language.create"));
|
|
1044
|
+
} }
|
|
1045
|
+
function LanguageListPage_ng_template_12_Template(rf, ctx) { if (rf & 1) {
|
|
1046
|
+
i0.ɵɵelementStart(0, "tr")(1, "th");
|
|
1047
|
+
i0.ɵɵtext(2);
|
|
1048
|
+
i0.ɵɵpipe(3, "translate");
|
|
1049
|
+
i0.ɵɵelementEnd();
|
|
1050
|
+
i0.ɵɵelementStart(4, "th");
|
|
1051
|
+
i0.ɵɵtext(5);
|
|
1052
|
+
i0.ɵɵpipe(6, "translate");
|
|
1053
|
+
i0.ɵɵelementEnd();
|
|
1054
|
+
i0.ɵɵelementStart(7, "th");
|
|
1055
|
+
i0.ɵɵtext(8);
|
|
1056
|
+
i0.ɵɵpipe(9, "translate");
|
|
1057
|
+
i0.ɵɵelementEnd();
|
|
1058
|
+
i0.ɵɵelementStart(10, "th");
|
|
1059
|
+
i0.ɵɵtext(11);
|
|
1060
|
+
i0.ɵɵpipe(12, "translate");
|
|
1061
|
+
i0.ɵɵelementEnd();
|
|
1062
|
+
i0.ɵɵelementStart(13, "th");
|
|
1063
|
+
i0.ɵɵtext(14);
|
|
1064
|
+
i0.ɵɵpipe(15, "translate");
|
|
1065
|
+
i0.ɵɵelementEnd();
|
|
1066
|
+
i0.ɵɵelementStart(16, "th", 11);
|
|
1067
|
+
i0.ɵɵtext(17);
|
|
1068
|
+
i0.ɵɵpipe(18, "translate");
|
|
1069
|
+
i0.ɵɵelementEnd()();
|
|
1070
|
+
} if (rf & 2) {
|
|
1071
|
+
i0.ɵɵadvance(2);
|
|
1072
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 6, "localization.language.code"));
|
|
1073
|
+
i0.ɵɵadvance(3);
|
|
1074
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(6, 8, "localization.language.name"));
|
|
1075
|
+
i0.ɵɵadvance(3);
|
|
1076
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(9, 10, "localization.language.native.name"));
|
|
1077
|
+
i0.ɵɵadvance(3);
|
|
1078
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 12, "localization.language.direction"));
|
|
1079
|
+
i0.ɵɵadvance(3);
|
|
1080
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(15, 14, "shared.status"));
|
|
1081
|
+
i0.ɵɵadvance(3);
|
|
1082
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(18, 16, "shared.actions"));
|
|
1083
|
+
} }
|
|
1084
|
+
function LanguageListPage_ng_template_14_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
1085
|
+
i0.ɵɵelement(0, "p-tag", 15);
|
|
1086
|
+
i0.ɵɵpipe(1, "translate");
|
|
1087
|
+
} if (rf & 2) {
|
|
1088
|
+
i0.ɵɵproperty("value", i0.ɵɵpipeBind1(1, 1, "localization.language.default"));
|
|
1089
|
+
} }
|
|
1090
|
+
function LanguageListPage_ng_template_14_Conditional_21_p_button_0_Template(rf, ctx) { if (rf & 1) {
|
|
1091
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
1092
|
+
i0.ɵɵelementStart(0, "p-button", 21);
|
|
1093
|
+
i0.ɵɵpipe(1, "translate");
|
|
1094
|
+
i0.ɵɵlistener("onClick", function LanguageListPage_ng_template_14_Conditional_21_p_button_0_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r3); const lang_r4 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onSetDefault(lang_r4)); });
|
|
1095
|
+
i0.ɵɵelementEnd();
|
|
1096
|
+
} if (rf & 2) {
|
|
1097
|
+
i0.ɵɵproperty("text", true)("pTooltip", i0.ɵɵpipeBind1(1, 2, "localization.language.set.default"));
|
|
1098
|
+
} }
|
|
1099
|
+
function LanguageListPage_ng_template_14_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
1100
|
+
i0.ɵɵtemplate(0, LanguageListPage_ng_template_14_Conditional_21_p_button_0_Template, 2, 4, "p-button", 20);
|
|
1101
|
+
} if (rf & 2) {
|
|
1102
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
1103
|
+
i0.ɵɵproperty("hasPermission", ctx_r1.LANGUAGE_PERMISSIONS.UPDATE);
|
|
1104
|
+
} }
|
|
1105
|
+
function LanguageListPage_ng_template_14_p_button_22_Template(rf, ctx) { if (rf & 1) {
|
|
1106
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
1107
|
+
i0.ɵɵelementStart(0, "p-button", 22);
|
|
1108
|
+
i0.ɵɵpipe(1, "translate");
|
|
1109
|
+
i0.ɵɵlistener("onClick", function LanguageListPage_ng_template_14_p_button_22_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r5); const lang_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onEdit(lang_r4.id)); });
|
|
1110
|
+
i0.ɵɵelementEnd();
|
|
1111
|
+
} if (rf & 2) {
|
|
1112
|
+
i0.ɵɵproperty("text", true)("pTooltip", i0.ɵɵpipeBind1(1, 2, "shared.edit"));
|
|
1113
|
+
} }
|
|
1114
|
+
function LanguageListPage_ng_template_14_p_button_23_Template(rf, ctx) { if (rf & 1) {
|
|
1115
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
1116
|
+
i0.ɵɵelementStart(0, "p-button", 23);
|
|
1117
|
+
i0.ɵɵpipe(1, "translate");
|
|
1118
|
+
i0.ɵɵlistener("onClick", function LanguageListPage_ng_template_14_p_button_23_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r6); const lang_r4 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onDelete(lang_r4)); });
|
|
1119
|
+
i0.ɵɵelementEnd();
|
|
1120
|
+
} if (rf & 2) {
|
|
1121
|
+
const lang_r4 = i0.ɵɵnextContext().$implicit;
|
|
1122
|
+
i0.ɵɵproperty("text", true)("pTooltip", i0.ɵɵpipeBind1(1, 3, "shared.delete"))("disabled", lang_r4.isDefault);
|
|
1123
|
+
} }
|
|
1124
|
+
function LanguageListPage_ng_template_14_Template(rf, ctx) { if (rf & 1) {
|
|
1125
|
+
i0.ɵɵelementStart(0, "tr")(1, "td")(2, "span", 12);
|
|
1126
|
+
i0.ɵɵtext(3);
|
|
1127
|
+
i0.ɵɵelementEnd()();
|
|
1128
|
+
i0.ɵɵelementStart(4, "td");
|
|
1129
|
+
i0.ɵɵtext(5);
|
|
1130
|
+
i0.ɵɵelementEnd();
|
|
1131
|
+
i0.ɵɵelementStart(6, "td");
|
|
1132
|
+
i0.ɵɵtext(7);
|
|
1133
|
+
i0.ɵɵpipe(8, "translate");
|
|
1134
|
+
i0.ɵɵelementEnd();
|
|
1135
|
+
i0.ɵɵelementStart(9, "td");
|
|
1136
|
+
i0.ɵɵelement(10, "p-tag", 13);
|
|
1137
|
+
i0.ɵɵpipe(11, "translate");
|
|
1138
|
+
i0.ɵɵpipe(12, "translate");
|
|
1139
|
+
i0.ɵɵelementEnd();
|
|
1140
|
+
i0.ɵɵelementStart(13, "td")(14, "div", 14);
|
|
1141
|
+
i0.ɵɵelement(15, "p-tag", 13);
|
|
1142
|
+
i0.ɵɵpipe(16, "translate");
|
|
1143
|
+
i0.ɵɵpipe(17, "translate");
|
|
1144
|
+
i0.ɵɵconditionalCreate(18, LanguageListPage_ng_template_14_Conditional_18_Template, 2, 3, "p-tag", 15);
|
|
1145
|
+
i0.ɵɵelementEnd()();
|
|
1146
|
+
i0.ɵɵelementStart(19, "td")(20, "div", 16);
|
|
1147
|
+
i0.ɵɵconditionalCreate(21, LanguageListPage_ng_template_14_Conditional_21_Template, 1, 1, "p-button", 17);
|
|
1148
|
+
i0.ɵɵtemplate(22, LanguageListPage_ng_template_14_p_button_22_Template, 2, 4, "p-button", 18)(23, LanguageListPage_ng_template_14_p_button_23_Template, 2, 5, "p-button", 19);
|
|
1149
|
+
i0.ɵɵelementEnd()()();
|
|
1150
|
+
} if (rf & 2) {
|
|
1151
|
+
const lang_r4 = ctx.$implicit;
|
|
1152
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1153
|
+
i0.ɵɵadvance(3);
|
|
1154
|
+
i0.ɵɵtextInterpolate(lang_r4.code);
|
|
1155
|
+
i0.ɵɵadvance(2);
|
|
1156
|
+
i0.ɵɵtextInterpolate(lang_r4.name);
|
|
1157
|
+
i0.ɵɵadvance(2);
|
|
1158
|
+
i0.ɵɵtextInterpolate(lang_r4.nativeName || i0.ɵɵpipeBind1(8, 11, "shared.na"));
|
|
1159
|
+
i0.ɵɵadvance(3);
|
|
1160
|
+
i0.ɵɵproperty("value", lang_r4.direction === "rtl" ? i0.ɵɵpipeBind1(11, 13, "localization.language.rtl") : i0.ɵɵpipeBind1(12, 15, "localization.language.ltr"))("severity", lang_r4.direction === "rtl" ? "warn" : "info");
|
|
1161
|
+
i0.ɵɵadvance(5);
|
|
1162
|
+
i0.ɵɵproperty("value", lang_r4.isActive ? i0.ɵɵpipeBind1(16, 17, "shared.active") : i0.ɵɵpipeBind1(17, 19, "shared.inactive"))("severity", lang_r4.isActive ? "success" : "secondary");
|
|
1163
|
+
i0.ɵɵadvance(3);
|
|
1164
|
+
i0.ɵɵconditional(lang_r4.isDefault ? 18 : -1);
|
|
1165
|
+
i0.ɵɵadvance(3);
|
|
1166
|
+
i0.ɵɵconditional(!lang_r4.isDefault ? 21 : -1);
|
|
1167
|
+
i0.ɵɵadvance();
|
|
1168
|
+
i0.ɵɵproperty("hasPermission", ctx_r1.LANGUAGE_PERMISSIONS.UPDATE);
|
|
1169
|
+
i0.ɵɵadvance();
|
|
1170
|
+
i0.ɵɵproperty("hasPermission", ctx_r1.LANGUAGE_PERMISSIONS.DELETE);
|
|
1171
|
+
} }
|
|
1172
|
+
function LanguageListPage_ng_template_16_Template(rf, ctx) { if (rf & 1) {
|
|
1173
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 24);
|
|
1174
|
+
i0.ɵɵtext(2);
|
|
1175
|
+
i0.ɵɵpipe(3, "translate");
|
|
1176
|
+
i0.ɵɵelementEnd()();
|
|
1177
|
+
} if (rf & 2) {
|
|
1178
|
+
i0.ɵɵadvance(2);
|
|
1179
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(3, 1, "localization.language.empty"), " ");
|
|
1180
|
+
} }
|
|
1181
|
+
class LanguageListPage {
|
|
1182
|
+
LANGUAGE_PERMISSIONS = LANGUAGE_PERMISSIONS;
|
|
1183
|
+
router = inject(Router);
|
|
1184
|
+
languageService = inject(LanguageApiService);
|
|
1185
|
+
confirmationService = inject(ConfirmationService);
|
|
1186
|
+
messageService = inject(MessageService);
|
|
1187
|
+
translateService = inject(TranslateService);
|
|
1188
|
+
destroyRef = inject(DestroyRef);
|
|
1189
|
+
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1190
|
+
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
1191
|
+
ngOnInit() {
|
|
1192
|
+
this.loadLanguages();
|
|
1193
|
+
}
|
|
1194
|
+
onCreate() {
|
|
1195
|
+
this.router.navigate(['/localization/languages/new']);
|
|
1196
|
+
}
|
|
1197
|
+
onEdit(id) {
|
|
1198
|
+
this.router.navigate(['/localization/languages', id]);
|
|
1199
|
+
}
|
|
1200
|
+
loadLanguages() {
|
|
1201
|
+
this.isLoading.set(true);
|
|
1202
|
+
this.languageService.getAll()
|
|
1203
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1204
|
+
.subscribe({
|
|
1205
|
+
next: (response) => {
|
|
1206
|
+
if (response.success) {
|
|
1207
|
+
this.languages.set(response.data ?? []);
|
|
1208
|
+
}
|
|
1209
|
+
this.isLoading.set(false);
|
|
1210
|
+
},
|
|
1211
|
+
error: () => {
|
|
1212
|
+
this.isLoading.set(false);
|
|
1213
|
+
},
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
onSetDefault(lang) {
|
|
1217
|
+
this.confirmationService.confirm({
|
|
1218
|
+
message: this.translateService.translate('localization.language.confirm.set.default', { name: lang.name }),
|
|
1219
|
+
header: this.translateService.translate('localization.language.set.default'),
|
|
1220
|
+
icon: 'pi pi-star',
|
|
1221
|
+
accept: () => {
|
|
1222
|
+
this.languageService.setDefault(lang.id)
|
|
1223
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1224
|
+
.subscribe({
|
|
1225
|
+
next: (response) => {
|
|
1226
|
+
if (response.success) {
|
|
1227
|
+
this.messageService.add({
|
|
1228
|
+
severity: 'success',
|
|
1229
|
+
summary: this.translateService.translate('shared.success'),
|
|
1230
|
+
detail: this.translateService.translate('localization.language.set.default.success', { name: lang.name }),
|
|
1231
|
+
});
|
|
1232
|
+
this.loadLanguages();
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
});
|
|
1236
|
+
},
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
onDelete(lang) {
|
|
1240
|
+
this.confirmationService.confirm({
|
|
1241
|
+
message: this.translateService.translate('shared.confirm.delete'),
|
|
1242
|
+
header: this.translateService.translate('localization.language.delete.title'),
|
|
1243
|
+
icon: 'pi pi-exclamation-triangle',
|
|
1244
|
+
acceptButtonStyleClass: 'p-button-danger',
|
|
1245
|
+
accept: () => {
|
|
1246
|
+
this.languageService.delete(lang.id)
|
|
1247
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1248
|
+
.subscribe({
|
|
1249
|
+
next: (response) => {
|
|
1250
|
+
if (response.success) {
|
|
1251
|
+
this.messageService.add({
|
|
1252
|
+
severity: 'success',
|
|
1253
|
+
summary: this.translateService.translate('shared.success'),
|
|
1254
|
+
detail: this.translateService.translate('localization.language.delete.success'),
|
|
1255
|
+
});
|
|
1256
|
+
this.loadLanguages();
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
});
|
|
1260
|
+
},
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
static ɵfac = function LanguageListPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageListPage)(); };
|
|
1264
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LanguageListPage, selectors: [["lib-language-list-page"]], features: [i0.ɵɵProvidersFeature([ConfirmationService, MessageService])], decls: 20, vars: 11, consts: [["header", ""], ["body", ""], ["emptymessage", ""], [1, "card"], [1, "flex", "flex-col", "sm:flex-row", "justify-between", "items-start", "sm:items-center", "gap-3", "mb-4"], [1, "text-lg", "sm:text-xl", "font-semibold", "m-0"], [1, "text-sm", "text-muted-color", "mt-1"], ["icon", "pi pi-plus", "styleClass", "w-full sm:w-auto", 3, "label", "onClick", 4, "hasPermission"], [1, "overflow-x-auto", "-mx-4", "sm:mx-0"], ["styleClass", "p-datatable-sm", 3, "value", "loading", "tableStyle"], ["icon", "pi pi-plus", "styleClass", "w-full sm:w-auto", 3, "onClick", "label"], [1, "w-[150px]"], [1, "uppercase", "font-semibold"], [3, "value", "severity"], [1, "flex", "gap-1", "items-center"], ["severity", "contrast", 3, "value"], [1, "flex", "gap-1"], ["icon", "pi pi-star", "size", "small", 3, "text", "pTooltip"], ["icon", "pi pi-pencil", "severity", "secondary", "size", "small", 3, "text", "pTooltip", "onClick", 4, "hasPermission"], ["icon", "pi pi-trash", "severity", "danger", "size", "small", 3, "text", "pTooltip", "disabled", "onClick", 4, "hasPermission"], ["icon", "pi pi-star", "size", "small", 3, "text", "pTooltip", "onClick", 4, "hasPermission"], ["icon", "pi pi-star", "size", "small", 3, "onClick", "text", "pTooltip"], ["icon", "pi pi-pencil", "severity", "secondary", "size", "small", 3, "onClick", "text", "pTooltip"], ["icon", "pi pi-trash", "severity", "danger", "size", "small", 3, "onClick", "text", "pTooltip", "disabled"], ["colspan", "6", 1, "text-center", "py-4", "text-muted-color"]], template: function LanguageListPage_Template(rf, ctx) { if (rf & 1) {
|
|
1265
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "div")(3, "h3", 5);
|
|
1266
|
+
i0.ɵɵtext(4);
|
|
1267
|
+
i0.ɵɵpipe(5, "translate");
|
|
1268
|
+
i0.ɵɵelementEnd();
|
|
1269
|
+
i0.ɵɵelementStart(6, "p", 6);
|
|
1270
|
+
i0.ɵɵtext(7);
|
|
1271
|
+
i0.ɵɵpipe(8, "translate");
|
|
1272
|
+
i0.ɵɵelementEnd()();
|
|
1273
|
+
i0.ɵɵtemplate(9, LanguageListPage_p_button_9_Template, 2, 3, "p-button", 7);
|
|
1274
|
+
i0.ɵɵelementEnd();
|
|
1275
|
+
i0.ɵɵelementStart(10, "div", 8)(11, "p-table", 9);
|
|
1276
|
+
i0.ɵɵtemplate(12, LanguageListPage_ng_template_12_Template, 19, 18, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(14, LanguageListPage_ng_template_14_Template, 24, 21, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor)(16, LanguageListPage_ng_template_16_Template, 4, 3, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
|
|
1277
|
+
i0.ɵɵelementEnd()()();
|
|
1278
|
+
i0.ɵɵelement(18, "p-confirmDialog")(19, "p-toast");
|
|
1279
|
+
} if (rf & 2) {
|
|
1280
|
+
i0.ɵɵadvance(4);
|
|
1281
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(5, 6, "localization.language.title"));
|
|
1282
|
+
i0.ɵɵadvance(3);
|
|
1283
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(8, 8, "localization.language.subtitle"), " ");
|
|
1284
|
+
i0.ɵɵadvance(2);
|
|
1285
|
+
i0.ɵɵproperty("hasPermission", ctx.LANGUAGE_PERMISSIONS.CREATE);
|
|
1286
|
+
i0.ɵɵadvance(2);
|
|
1287
|
+
i0.ɵɵproperty("value", ctx.languages())("loading", ctx.isLoading())("tableStyle", i0.ɵɵpureFunction0(10, _c0$4));
|
|
1288
|
+
} }, dependencies: [AngularModule, PrimeModule, i2.Button, i2$1.ConfirmDialog, i8.Table, i4.Tag, i10.Toast, i6.Tooltip, HasPermissionDirective, TranslatePipe], encapsulation: 2 });
|
|
1289
|
+
}
|
|
1290
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageListPage, [{
|
|
1291
|
+
type: Component,
|
|
1292
|
+
args: [{
|
|
1293
|
+
selector: 'lib-language-list-page',
|
|
1294
|
+
imports: [AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe],
|
|
1295
|
+
providers: [ConfirmationService, MessageService],
|
|
1296
|
+
template: `
|
|
1297
|
+
<div class="card">
|
|
1298
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
|
|
1299
|
+
<div>
|
|
1300
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">{{ 'localization.language.title' | translate }}</h3>
|
|
1301
|
+
<p class="text-sm text-muted-color mt-1">
|
|
1302
|
+
{{ 'localization.language.subtitle' | translate }}
|
|
1303
|
+
</p>
|
|
1304
|
+
</div>
|
|
1305
|
+
<p-button
|
|
1306
|
+
*hasPermission="LANGUAGE_PERMISSIONS.CREATE"
|
|
1307
|
+
[label]="'localization.language.create' | translate"
|
|
1308
|
+
icon="pi pi-plus"
|
|
1309
|
+
(onClick)="onCreate()"
|
|
1310
|
+
styleClass="w-full sm:w-auto"
|
|
1311
|
+
/>
|
|
1312
|
+
</div>
|
|
1313
|
+
|
|
1314
|
+
<div class="overflow-x-auto -mx-4 sm:mx-0">
|
|
1315
|
+
<p-table
|
|
1316
|
+
[value]="languages()"
|
|
1317
|
+
[loading]="isLoading()"
|
|
1318
|
+
styleClass="p-datatable-sm"
|
|
1319
|
+
[tableStyle]="{ 'min-width': '40rem' }"
|
|
1320
|
+
>
|
|
1321
|
+
<ng-template #header>
|
|
1322
|
+
<tr>
|
|
1323
|
+
<th>{{ 'localization.language.code' | translate }}</th>
|
|
1324
|
+
<th>{{ 'localization.language.name' | translate }}</th>
|
|
1325
|
+
<th>{{ 'localization.language.native.name' | translate }}</th>
|
|
1326
|
+
<th>{{ 'localization.language.direction' | translate }}</th>
|
|
1327
|
+
<th>{{ 'shared.status' | translate }}</th>
|
|
1328
|
+
<th class="w-[150px]">{{ 'shared.actions' | translate }}</th>
|
|
1329
|
+
</tr>
|
|
1330
|
+
</ng-template>
|
|
1331
|
+
|
|
1332
|
+
<ng-template #body let-lang>
|
|
1333
|
+
<tr>
|
|
1334
|
+
<td>
|
|
1335
|
+
<span class="uppercase font-semibold">{{ lang.code }}</span>
|
|
1336
|
+
</td>
|
|
1337
|
+
<td>{{ lang.name }}</td>
|
|
1338
|
+
<td>{{ lang.nativeName || ('shared.na' | translate) }}</td>
|
|
1339
|
+
<td>
|
|
1340
|
+
<p-tag
|
|
1341
|
+
[value]="lang.direction === 'rtl' ? ('localization.language.rtl' | translate) : ('localization.language.ltr' | translate)"
|
|
1342
|
+
[severity]="lang.direction === 'rtl' ? 'warn' : 'info'"
|
|
1343
|
+
/>
|
|
1344
|
+
</td>
|
|
1345
|
+
<td>
|
|
1346
|
+
<div class="flex gap-1 items-center">
|
|
1347
|
+
<p-tag
|
|
1348
|
+
[value]="lang.isActive ? ('shared.active' | translate) : ('shared.inactive' | translate)"
|
|
1349
|
+
[severity]="lang.isActive ? 'success' : 'secondary'"
|
|
1350
|
+
/>
|
|
1351
|
+
@if (lang.isDefault) {
|
|
1352
|
+
<p-tag [value]="'localization.language.default' | translate" severity="contrast" />
|
|
1353
|
+
}
|
|
1354
|
+
</div>
|
|
1355
|
+
</td>
|
|
1356
|
+
<td>
|
|
1357
|
+
<div class="flex gap-1">
|
|
1358
|
+
@if (!lang.isDefault) {
|
|
1359
|
+
<p-button
|
|
1360
|
+
*hasPermission="LANGUAGE_PERMISSIONS.UPDATE"
|
|
1361
|
+
icon="pi pi-star"
|
|
1362
|
+
[text]="true"
|
|
1363
|
+
size="small"
|
|
1364
|
+
[pTooltip]="'localization.language.set.default' | translate"
|
|
1365
|
+
(onClick)="onSetDefault(lang)"
|
|
1366
|
+
/>
|
|
1367
|
+
}
|
|
1368
|
+
<p-button
|
|
1369
|
+
*hasPermission="LANGUAGE_PERMISSIONS.UPDATE"
|
|
1370
|
+
icon="pi pi-pencil"
|
|
1371
|
+
[text]="true"
|
|
1372
|
+
severity="secondary"
|
|
1373
|
+
size="small"
|
|
1374
|
+
[pTooltip]="'shared.edit' | translate"
|
|
1375
|
+
(onClick)="onEdit(lang.id)"
|
|
1376
|
+
/>
|
|
1377
|
+
<p-button
|
|
1378
|
+
*hasPermission="LANGUAGE_PERMISSIONS.DELETE"
|
|
1379
|
+
icon="pi pi-trash"
|
|
1380
|
+
[text]="true"
|
|
1381
|
+
severity="danger"
|
|
1382
|
+
size="small"
|
|
1383
|
+
[pTooltip]="'shared.delete' | translate"
|
|
1384
|
+
[disabled]="lang.isDefault"
|
|
1385
|
+
(onClick)="onDelete(lang)"
|
|
1386
|
+
/>
|
|
1387
|
+
</div>
|
|
1388
|
+
</td>
|
|
1389
|
+
</tr>
|
|
1390
|
+
</ng-template>
|
|
1391
|
+
|
|
1392
|
+
<ng-template #emptymessage>
|
|
1393
|
+
<tr>
|
|
1394
|
+
<td colspan="6" class="text-center py-4 text-muted-color">
|
|
1395
|
+
{{ 'localization.language.empty' | translate }}
|
|
1396
|
+
</td>
|
|
1397
|
+
</tr>
|
|
1398
|
+
</ng-template>
|
|
1399
|
+
</p-table>
|
|
1400
|
+
</div>
|
|
1401
|
+
</div>
|
|
1402
|
+
|
|
1403
|
+
<p-confirmDialog />
|
|
1404
|
+
<p-toast />
|
|
1405
|
+
`,
|
|
1406
|
+
}]
|
|
1407
|
+
}], null, null); })();
|
|
1408
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LanguageListPage, { className: "LanguageListPage", filePath: "pages/language-list/language-list.page.ts", lineNumber: 131 }); })();
|
|
1409
|
+
|
|
1410
|
+
var languageList_page = /*#__PURE__*/Object.freeze({
|
|
1411
|
+
__proto__: null,
|
|
1412
|
+
LanguageListPage: LanguageListPage
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
const _c0$3 = () => ({ standalone: true });
|
|
1416
|
+
function LanguageFormPage_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
1417
|
+
i0.ɵɵelementStart(0, "div", 21)(1, "h2", 22);
|
|
1418
|
+
i0.ɵɵtext(2);
|
|
1419
|
+
i0.ɵɵpipe(3, "translate");
|
|
1420
|
+
i0.ɵɵpipe(4, "translate");
|
|
1421
|
+
i0.ɵɵelementEnd()();
|
|
1422
|
+
} if (rf & 2) {
|
|
1423
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
1424
|
+
i0.ɵɵadvance(2);
|
|
1425
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.isEditMode() ? i0.ɵɵpipeBind1(3, 1, "localization.language.edit") : i0.ɵɵpipeBind1(4, 3, "localization.language.create"), " ");
|
|
1426
|
+
} }
|
|
1427
|
+
class LanguageFormPage {
|
|
1428
|
+
router = inject(Router);
|
|
1429
|
+
route = inject(ActivatedRoute);
|
|
1430
|
+
languageService = inject(LanguageApiService);
|
|
1431
|
+
messageService = inject(MessageService);
|
|
1432
|
+
translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
|
|
1433
|
+
destroyRef = inject(DestroyRef);
|
|
1434
|
+
routeParams = toSignal(this.route.paramMap);
|
|
1435
|
+
loadTriggered = false;
|
|
1436
|
+
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
1437
|
+
existingLanguage = signal(null, ...(ngDevMode ? [{ debugName: "existingLanguage" }] : []));
|
|
1438
|
+
isEditMode = computed(() => !!this.existingLanguage(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
1439
|
+
translate(key) {
|
|
1440
|
+
return this.translateAdapter?.translate(key) ?? key;
|
|
1441
|
+
}
|
|
1442
|
+
directionOptions = computed(() => [
|
|
1443
|
+
{ label: this.translate('localization.language.direction.ltr'), value: 'ltr' },
|
|
1444
|
+
{ label: this.translate('localization.language.direction.rtl'), value: 'rtl' },
|
|
1445
|
+
], ...(ngDevMode ? [{ debugName: "directionOptions" }] : []));
|
|
1446
|
+
formModel = signal({
|
|
1447
|
+
code: '',
|
|
1448
|
+
name: '',
|
|
1449
|
+
nativeName: '',
|
|
1450
|
+
direction: 'ltr',
|
|
1451
|
+
serial: '',
|
|
1452
|
+
isActive: true,
|
|
1453
|
+
isDefault: false,
|
|
1454
|
+
}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
1455
|
+
formTree = form(this.formModel, (f) => {
|
|
1456
|
+
required(f.code, { message: this.translate('localization.validation.code.required') });
|
|
1457
|
+
maxLength(f.code, 10, { message: this.translate('localization.validation.code.max.length') });
|
|
1458
|
+
required(f.name, { message: this.translate('localization.validation.name.required') });
|
|
1459
|
+
maxLength(f.name, 100, { message: this.translate('localization.validation.name.max.length') });
|
|
1460
|
+
});
|
|
1461
|
+
isFormValid = computed(() => {
|
|
1462
|
+
const model = this.formModel();
|
|
1463
|
+
return model.code.trim().length > 0 && model.name.trim().length > 0;
|
|
1464
|
+
}, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
|
|
1465
|
+
constructor() {
|
|
1466
|
+
effect(() => {
|
|
1467
|
+
const params = this.routeParams();
|
|
1468
|
+
if (!params || this.loadTriggered)
|
|
1469
|
+
return;
|
|
1470
|
+
this.loadTriggered = true;
|
|
1471
|
+
const id = params.get('id');
|
|
1472
|
+
if (id && id !== 'new') {
|
|
1473
|
+
this.loadLanguage(id);
|
|
1474
|
+
}
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
updateDirection(value) {
|
|
1478
|
+
this.formModel.update((m) => ({ ...m, direction: value }));
|
|
1479
|
+
}
|
|
1480
|
+
loadLanguage(id) {
|
|
1481
|
+
this.isSaving.set(true);
|
|
1482
|
+
this.languageService.getById(id)
|
|
1483
|
+
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
1484
|
+
.subscribe({
|
|
1485
|
+
next: (response) => {
|
|
1486
|
+
if (response.success && response.data) {
|
|
1487
|
+
this.existingLanguage.set(response.data);
|
|
1488
|
+
this.formModel.set(this.toFormModel(response.data));
|
|
1489
|
+
}
|
|
1490
|
+
},
|
|
1491
|
+
error: () => this.router.navigate(['/localization/languages']),
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
toFormModel(language) {
|
|
1495
|
+
return {
|
|
1496
|
+
code: language.code,
|
|
1497
|
+
name: language.name,
|
|
1498
|
+
nativeName: language.nativeName ?? '',
|
|
1499
|
+
direction: language.direction ?? 'ltr',
|
|
1500
|
+
serial: language.serial?.toString() ?? '',
|
|
1501
|
+
isActive: language.isActive,
|
|
1502
|
+
isDefault: language.isDefault,
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
onSubmit() {
|
|
1506
|
+
if (!this.isFormValid())
|
|
1507
|
+
return;
|
|
1508
|
+
this.isSaving.set(true);
|
|
1509
|
+
const model = this.formModel();
|
|
1510
|
+
const dto = {
|
|
1511
|
+
code: model.code,
|
|
1512
|
+
name: model.name,
|
|
1513
|
+
nativeName: model.nativeName || undefined,
|
|
1514
|
+
direction: model.direction,
|
|
1515
|
+
serial: model.serial ? parseInt(model.serial, 10) : undefined,
|
|
1516
|
+
isActive: model.isActive,
|
|
1517
|
+
isDefault: model.isDefault,
|
|
1518
|
+
};
|
|
1519
|
+
const operation$ = this.isEditMode()
|
|
1520
|
+
? this.languageService.update({ id: this.existingLanguage().id, ...dto })
|
|
1521
|
+
: this.languageService.create(dto);
|
|
1522
|
+
operation$
|
|
1523
|
+
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
1524
|
+
.subscribe({
|
|
1525
|
+
next: (response) => {
|
|
1526
|
+
if (response.success) {
|
|
1527
|
+
this.messageService.add({
|
|
1528
|
+
severity: 'success',
|
|
1529
|
+
summary: this.translate('shared.success'),
|
|
1530
|
+
detail: this.translate(this.isEditMode() ? 'localization.language.update.success' : 'localization.language.create.success'),
|
|
1531
|
+
});
|
|
1532
|
+
this.router.navigate(['/localization/languages']);
|
|
1533
|
+
}
|
|
1534
|
+
},
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
onCancel() {
|
|
1538
|
+
this.router.navigate(['/localization/languages']);
|
|
1539
|
+
}
|
|
1540
|
+
static ɵfac = function LanguageFormPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageFormPage)(); };
|
|
1541
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LanguageFormPage, selectors: [["lib-language-form-page"]], features: [i0.ɵɵProvidersFeature([MessageService])], decls: 58, vars: 66, consts: [["header", ""], [1, "grid", "grid-cols-1", "md:grid-cols-2", "gap-4", 3, "ngSubmit"], [1, "flex", "flex-col", "gap-2"], ["for", "code", 1, "font-medium"], ["pInputText", "", "id", "code", 3, "formField", "placeholder"], [1, "text-muted-color"], ["for", "name", 1, "font-medium"], ["pInputText", "", "id", "name", 3, "formField", "placeholder"], ["for", "nativeName", 1, "font-medium"], ["pInputText", "", "id", "nativeName", 3, "formField", "placeholder"], ["for", "direction", 1, "font-medium"], ["id", "direction", "optionLabel", "label", "optionValue", "value", 1, "w-full", 3, "ngModelChange", "ngModel", "ngModelOptions", "options"], ["for", "serial", 1, "font-medium"], ["pInputText", "", "id", "serial", "type", "number", 3, "formField", "placeholder"], [1, "hidden", "md:block"], [1, "flex", "items-center", "gap-6", "md:col-span-2", "pt-4"], [1, "p-checkbox-native"], ["type", "checkbox", 3, "formField"], [1, "flex", "justify-end", "gap-4", "md:col-span-2", "pt-4"], ["severity", "secondary", 3, "onClick", "label", "outlined"], ["type", "submit", 3, "label", "loading", "disabled"], [1, "flex", "justify-between", "items-center", "p-4"], [1, "text-xl", "font-semibold", "m-0"]], template: function LanguageFormPage_Template(rf, ctx) { if (rf & 1) {
|
|
1542
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
1543
|
+
i0.ɵɵelementStart(0, "p-card");
|
|
1544
|
+
i0.ɵɵtemplate(1, LanguageFormPage_ng_template_1_Template, 5, 5, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
1545
|
+
i0.ɵɵelementStart(3, "form", 1);
|
|
1546
|
+
i0.ɵɵlistener("ngSubmit", function LanguageFormPage_Template_form_ngSubmit_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSubmit()); });
|
|
1547
|
+
i0.ɵɵelementStart(4, "div", 2)(5, "label", 3);
|
|
1548
|
+
i0.ɵɵtext(6);
|
|
1549
|
+
i0.ɵɵpipe(7, "translate");
|
|
1550
|
+
i0.ɵɵelementEnd();
|
|
1551
|
+
i0.ɵɵelement(8, "input", 4);
|
|
1552
|
+
i0.ɵɵpipe(9, "translate");
|
|
1553
|
+
i0.ɵɵcontrolCreate();
|
|
1554
|
+
i0.ɵɵelementStart(10, "small", 5);
|
|
1555
|
+
i0.ɵɵtext(11);
|
|
1556
|
+
i0.ɵɵpipe(12, "translate");
|
|
1557
|
+
i0.ɵɵelementEnd()();
|
|
1558
|
+
i0.ɵɵelementStart(13, "div", 2)(14, "label", 6);
|
|
1559
|
+
i0.ɵɵtext(15);
|
|
1560
|
+
i0.ɵɵpipe(16, "translate");
|
|
1561
|
+
i0.ɵɵelementEnd();
|
|
1562
|
+
i0.ɵɵelement(17, "input", 7);
|
|
1563
|
+
i0.ɵɵpipe(18, "translate");
|
|
1564
|
+
i0.ɵɵcontrolCreate();
|
|
1565
|
+
i0.ɵɵelementEnd();
|
|
1566
|
+
i0.ɵɵelementStart(19, "div", 2)(20, "label", 8);
|
|
1567
|
+
i0.ɵɵtext(21);
|
|
1568
|
+
i0.ɵɵpipe(22, "translate");
|
|
1569
|
+
i0.ɵɵelementEnd();
|
|
1570
|
+
i0.ɵɵelement(23, "input", 9);
|
|
1571
|
+
i0.ɵɵpipe(24, "translate");
|
|
1572
|
+
i0.ɵɵcontrolCreate();
|
|
1573
|
+
i0.ɵɵelementStart(25, "small", 5);
|
|
1574
|
+
i0.ɵɵtext(26);
|
|
1575
|
+
i0.ɵɵpipe(27, "translate");
|
|
1576
|
+
i0.ɵɵelementEnd()();
|
|
1577
|
+
i0.ɵɵelementStart(28, "div", 2)(29, "label", 10);
|
|
1578
|
+
i0.ɵɵtext(30);
|
|
1579
|
+
i0.ɵɵpipe(31, "translate");
|
|
1580
|
+
i0.ɵɵelementEnd();
|
|
1581
|
+
i0.ɵɵelementStart(32, "p-select", 11);
|
|
1582
|
+
i0.ɵɵlistener("ngModelChange", function LanguageFormPage_Template_p_select_ngModelChange_32_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.updateDirection($event)); });
|
|
1583
|
+
i0.ɵɵelementEnd()();
|
|
1584
|
+
i0.ɵɵelementStart(33, "div", 2)(34, "label", 12);
|
|
1585
|
+
i0.ɵɵtext(35);
|
|
1586
|
+
i0.ɵɵpipe(36, "translate");
|
|
1587
|
+
i0.ɵɵelementEnd();
|
|
1588
|
+
i0.ɵɵelement(37, "input", 13);
|
|
1589
|
+
i0.ɵɵpipe(38, "translate");
|
|
1590
|
+
i0.ɵɵcontrolCreate();
|
|
1591
|
+
i0.ɵɵelementEnd();
|
|
1592
|
+
i0.ɵɵelement(39, "div", 14);
|
|
1593
|
+
i0.ɵɵelementStart(40, "div", 15)(41, "label", 16);
|
|
1594
|
+
i0.ɵɵelement(42, "input", 17);
|
|
1595
|
+
i0.ɵɵcontrolCreate();
|
|
1596
|
+
i0.ɵɵelementStart(43, "span");
|
|
1597
|
+
i0.ɵɵtext(44);
|
|
1598
|
+
i0.ɵɵpipe(45, "translate");
|
|
1599
|
+
i0.ɵɵelementEnd()();
|
|
1600
|
+
i0.ɵɵelementStart(46, "label", 16);
|
|
1601
|
+
i0.ɵɵelement(47, "input", 17);
|
|
1602
|
+
i0.ɵɵcontrolCreate();
|
|
1603
|
+
i0.ɵɵelementStart(48, "span");
|
|
1604
|
+
i0.ɵɵtext(49);
|
|
1605
|
+
i0.ɵɵpipe(50, "translate");
|
|
1606
|
+
i0.ɵɵelementEnd()()();
|
|
1607
|
+
i0.ɵɵelementStart(51, "div", 18)(52, "p-button", 19);
|
|
1608
|
+
i0.ɵɵpipe(53, "translate");
|
|
1609
|
+
i0.ɵɵlistener("onClick", function LanguageFormPage_Template_p_button_onClick_52_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onCancel()); });
|
|
1610
|
+
i0.ɵɵelementEnd();
|
|
1611
|
+
i0.ɵɵelement(54, "p-button", 20);
|
|
1612
|
+
i0.ɵɵpipe(55, "translate");
|
|
1613
|
+
i0.ɵɵpipe(56, "translate");
|
|
1614
|
+
i0.ɵɵelementEnd()()();
|
|
1615
|
+
i0.ɵɵelement(57, "p-toast");
|
|
1616
|
+
} if (rf & 2) {
|
|
1617
|
+
i0.ɵɵadvance(6);
|
|
1618
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(7, 33, "localization.language.code"), " *");
|
|
1619
|
+
i0.ɵɵadvance(2);
|
|
1620
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(9, 35, "localization.placeholder.code"));
|
|
1621
|
+
i0.ɵɵcontrol(ctx.formTree.code, "formField");
|
|
1622
|
+
i0.ɵɵadvance(3);
|
|
1623
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 37, "localization.language.iso.code.hint"));
|
|
1624
|
+
i0.ɵɵadvance(4);
|
|
1625
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(16, 39, "localization.language.name"), " *");
|
|
1626
|
+
i0.ɵɵadvance(2);
|
|
1627
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(18, 41, "localization.placeholder.name"));
|
|
1628
|
+
i0.ɵɵcontrol(ctx.formTree.name, "formField");
|
|
1629
|
+
i0.ɵɵadvance(4);
|
|
1630
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(22, 43, "localization.language.native.name"));
|
|
1631
|
+
i0.ɵɵadvance(2);
|
|
1632
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(24, 45, "localization.placeholder.native.name"));
|
|
1633
|
+
i0.ɵɵcontrol(ctx.formTree.nativeName, "formField");
|
|
1634
|
+
i0.ɵɵadvance(3);
|
|
1635
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(27, 47, "localization.language.native.name.hint"));
|
|
1636
|
+
i0.ɵɵadvance(4);
|
|
1637
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(31, 49, "localization.language.direction"), " *");
|
|
1638
|
+
i0.ɵɵadvance(2);
|
|
1639
|
+
i0.ɵɵproperty("ngModel", ctx.formModel().direction)("ngModelOptions", i0.ɵɵpureFunction0(65, _c0$3))("options", ctx.directionOptions());
|
|
1640
|
+
i0.ɵɵadvance(3);
|
|
1641
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(36, 51, "localization.language.display.order"));
|
|
1642
|
+
i0.ɵɵadvance(2);
|
|
1643
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(38, 53, "shared.display.order.placeholder"));
|
|
1644
|
+
i0.ɵɵcontrol(ctx.formTree.serial, "formField");
|
|
1645
|
+
i0.ɵɵadvance(5);
|
|
1646
|
+
i0.ɵɵcontrol(ctx.formTree.isActive, "formField");
|
|
1647
|
+
i0.ɵɵadvance(2);
|
|
1648
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(45, 55, "shared.active"));
|
|
1649
|
+
i0.ɵɵadvance(3);
|
|
1650
|
+
i0.ɵɵcontrol(ctx.formTree.isDefault, "formField");
|
|
1651
|
+
i0.ɵɵadvance(2);
|
|
1652
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(50, 57, "localization.language.default"));
|
|
1653
|
+
i0.ɵɵadvance(3);
|
|
1654
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(53, 59, "shared.cancel"))("outlined", true);
|
|
1655
|
+
i0.ɵɵadvance(2);
|
|
1656
|
+
i0.ɵɵproperty("label", ctx.isEditMode() ? i0.ɵɵpipeBind1(55, 61, "shared.update") : i0.ɵɵpipeBind1(56, 63, "shared.create"))("loading", ctx.isSaving())("disabled", !ctx.isFormValid() || ctx.isSaving());
|
|
1657
|
+
} }, dependencies: [AngularModule, i1$1.ɵNgNoValidate, i1$1.NgControlStatus, i1$1.NgControlStatusGroup, i1$1.NgModel, i1$1.NgForm, PrimeModule, i2.Button, i3.Card, i4$1.InputText, i5.Select, i10.Toast, FormsModule, FormField, TranslatePipe], encapsulation: 2 });
|
|
1658
|
+
}
|
|
1659
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageFormPage, [{
|
|
1660
|
+
type: Component,
|
|
1661
|
+
args: [{
|
|
1662
|
+
selector: 'lib-language-form-page',
|
|
1663
|
+
imports: [AngularModule, PrimeModule, FormsModule, FormField, TranslatePipe],
|
|
1664
|
+
providers: [MessageService],
|
|
1665
|
+
template: `
|
|
1666
|
+
<p-card>
|
|
1667
|
+
<ng-template #header>
|
|
1668
|
+
<div class="flex justify-between items-center p-4">
|
|
1669
|
+
<h2 class="text-xl font-semibold m-0">
|
|
1670
|
+
{{ isEditMode() ? ('localization.language.edit' | translate) : ('localization.language.create' | translate) }}
|
|
1671
|
+
</h2>
|
|
1672
|
+
</div>
|
|
1673
|
+
</ng-template>
|
|
1674
|
+
|
|
1675
|
+
<form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
1676
|
+
<!-- Language Code -->
|
|
1677
|
+
<div class="flex flex-col gap-2">
|
|
1678
|
+
<label for="code" class="font-medium">{{ 'localization.language.code' | translate }} *</label>
|
|
1679
|
+
<input
|
|
1680
|
+
pInputText
|
|
1681
|
+
id="code"
|
|
1682
|
+
[formField]="formTree.code"
|
|
1683
|
+
[placeholder]="'localization.placeholder.code' | translate" />
|
|
1684
|
+
<small class="text-muted-color">{{ 'localization.language.iso.code.hint' | translate }}</small>
|
|
1685
|
+
</div>
|
|
1686
|
+
|
|
1687
|
+
<!-- Language Name -->
|
|
1688
|
+
<div class="flex flex-col gap-2">
|
|
1689
|
+
<label for="name" class="font-medium">{{ 'localization.language.name' | translate }} *</label>
|
|
1690
|
+
<input
|
|
1691
|
+
pInputText
|
|
1692
|
+
id="name"
|
|
1693
|
+
[formField]="formTree.name"
|
|
1694
|
+
[placeholder]="'localization.placeholder.name' | translate" />
|
|
1695
|
+
</div>
|
|
1696
|
+
|
|
1697
|
+
<!-- Native Name -->
|
|
1698
|
+
<div class="flex flex-col gap-2">
|
|
1699
|
+
<label for="nativeName" class="font-medium">{{ 'localization.language.native.name' | translate }}</label>
|
|
1700
|
+
<input
|
|
1701
|
+
pInputText
|
|
1702
|
+
id="nativeName"
|
|
1703
|
+
[formField]="formTree.nativeName"
|
|
1704
|
+
[placeholder]="'localization.placeholder.native.name' | translate" />
|
|
1705
|
+
<small class="text-muted-color">{{ 'localization.language.native.name.hint' | translate }}</small>
|
|
1706
|
+
</div>
|
|
1707
|
+
|
|
1708
|
+
<!-- Text Direction -->
|
|
1709
|
+
<div class="flex flex-col gap-2">
|
|
1710
|
+
<label for="direction" class="font-medium">{{ 'localization.language.direction' | translate }} *</label>
|
|
1711
|
+
<p-select
|
|
1712
|
+
id="direction"
|
|
1713
|
+
[ngModel]="formModel().direction"
|
|
1714
|
+
(ngModelChange)="updateDirection($event)"
|
|
1715
|
+
[ngModelOptions]="{standalone: true}"
|
|
1716
|
+
[options]="directionOptions()"
|
|
1717
|
+
optionLabel="label"
|
|
1718
|
+
optionValue="value"
|
|
1719
|
+
class="w-full" />
|
|
1720
|
+
</div>
|
|
1721
|
+
|
|
1722
|
+
<!-- Display Order -->
|
|
1723
|
+
<div class="flex flex-col gap-2">
|
|
1724
|
+
<label for="serial" class="font-medium">{{ 'localization.language.display.order' | translate }}</label>
|
|
1725
|
+
<input
|
|
1726
|
+
pInputText
|
|
1727
|
+
id="serial"
|
|
1728
|
+
type="number"
|
|
1729
|
+
[formField]="formTree.serial"
|
|
1730
|
+
[placeholder]="'shared.display.order.placeholder' | translate" />
|
|
1731
|
+
</div>
|
|
1732
|
+
|
|
1733
|
+
<!-- Empty cell for alignment -->
|
|
1734
|
+
<div class="hidden md:block"></div>
|
|
1735
|
+
|
|
1736
|
+
<!-- Checkboxes -->
|
|
1737
|
+
<div class="flex items-center gap-6 md:col-span-2 pt-4">
|
|
1738
|
+
<label class="p-checkbox-native">
|
|
1739
|
+
<input type="checkbox" [formField]="formTree.isActive" />
|
|
1740
|
+
<span>{{ 'shared.active' | translate }}</span>
|
|
1741
|
+
</label>
|
|
1742
|
+
<label class="p-checkbox-native">
|
|
1743
|
+
<input type="checkbox" [formField]="formTree.isDefault" />
|
|
1744
|
+
<span>{{ 'localization.language.default' | translate }}</span>
|
|
1745
|
+
</label>
|
|
1746
|
+
</div>
|
|
1747
|
+
|
|
1748
|
+
<!-- Actions -->
|
|
1749
|
+
<div class="flex justify-end gap-4 md:col-span-2 pt-4">
|
|
1750
|
+
<p-button
|
|
1751
|
+
[label]="'shared.cancel' | translate"
|
|
1752
|
+
severity="secondary"
|
|
1753
|
+
[outlined]="true"
|
|
1754
|
+
(onClick)="onCancel()" />
|
|
1755
|
+
<p-button
|
|
1756
|
+
[label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
|
|
1757
|
+
type="submit"
|
|
1758
|
+
[loading]="isSaving()"
|
|
1759
|
+
[disabled]="!isFormValid() || isSaving()" />
|
|
1760
|
+
</div>
|
|
1761
|
+
</form>
|
|
1762
|
+
</p-card>
|
|
1763
|
+
|
|
1764
|
+
<p-toast />
|
|
1765
|
+
`,
|
|
1766
|
+
}]
|
|
1767
|
+
}], () => [], null); })();
|
|
1768
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LanguageFormPage, { className: "LanguageFormPage", filePath: "pages/language-form/language-form.page.ts", lineNumber: 136 }); })();
|
|
1769
|
+
|
|
1770
|
+
var languageForm_page = /*#__PURE__*/Object.freeze({
|
|
1771
|
+
__proto__: null,
|
|
1772
|
+
LanguageFormPage: LanguageFormPage
|
|
1773
|
+
});
|
|
1774
|
+
|
|
1775
|
+
const _c0$2 = () => ({ standalone: true });
|
|
1776
|
+
const _c1$1 = () => [10, 15, 25, 50];
|
|
1777
|
+
function TranslationKeyListPage_p_button_10_Template(rf, ctx) { if (rf & 1) {
|
|
1778
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
1779
|
+
i0.ɵɵelementStart(0, "p-button", 16);
|
|
1780
|
+
i0.ɵɵpipe(1, "translate");
|
|
1781
|
+
i0.ɵɵlistener("onClick", function TranslationKeyListPage_p_button_10_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onCreate()); });
|
|
1782
|
+
i0.ɵɵelementEnd();
|
|
1783
|
+
} if (rf & 2) {
|
|
1784
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(1, 1, "localization.key.create"));
|
|
1785
|
+
} }
|
|
1786
|
+
function TranslationKeyListPage_ng_template_21_Template(rf, ctx) { if (rf & 1) {
|
|
1787
|
+
i0.ɵɵelementStart(0, "tr")(1, "th", 17);
|
|
1788
|
+
i0.ɵɵtext(2);
|
|
1789
|
+
i0.ɵɵpipe(3, "translate");
|
|
1790
|
+
i0.ɵɵelementEnd();
|
|
1791
|
+
i0.ɵɵelementStart(4, "th", 18);
|
|
1792
|
+
i0.ɵɵtext(5);
|
|
1793
|
+
i0.ɵɵpipe(6, "translate");
|
|
1794
|
+
i0.ɵɵelementEnd();
|
|
1795
|
+
i0.ɵɵelementStart(7, "th", 19);
|
|
1796
|
+
i0.ɵɵtext(8);
|
|
1797
|
+
i0.ɵɵpipe(9, "translate");
|
|
1798
|
+
i0.ɵɵelementEnd();
|
|
1799
|
+
i0.ɵɵelementStart(10, "th", 20);
|
|
1800
|
+
i0.ɵɵtext(11);
|
|
1801
|
+
i0.ɵɵpipe(12, "translate");
|
|
1802
|
+
i0.ɵɵelementEnd();
|
|
1803
|
+
i0.ɵɵelementStart(13, "th", 17);
|
|
1804
|
+
i0.ɵɵtext(14);
|
|
1805
|
+
i0.ɵɵpipe(15, "translate");
|
|
1806
|
+
i0.ɵɵelementEnd()();
|
|
1807
|
+
} if (rf & 2) {
|
|
1808
|
+
i0.ɵɵadvance(2);
|
|
1809
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 5, "localization.key.module"));
|
|
1810
|
+
i0.ɵɵadvance(3);
|
|
1811
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(6, 7, "localization.key.name"));
|
|
1812
|
+
i0.ɵɵadvance(3);
|
|
1813
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(9, 9, "localization.key.default.message"));
|
|
1814
|
+
i0.ɵɵadvance(3);
|
|
1815
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 11, "localization.key.translations"));
|
|
1816
|
+
i0.ɵɵadvance(3);
|
|
1817
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(15, 13, "shared.actions"));
|
|
1818
|
+
} }
|
|
1819
|
+
function TranslationKeyListPage_ng_template_23_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
1820
|
+
i0.ɵɵelementStart(0, "small", 23);
|
|
1821
|
+
i0.ɵɵtext(1);
|
|
1822
|
+
i0.ɵɵelementEnd();
|
|
1823
|
+
} if (rf & 2) {
|
|
1824
|
+
const key_r4 = i0.ɵɵnextContext().$implicit;
|
|
1825
|
+
i0.ɵɵadvance();
|
|
1826
|
+
i0.ɵɵtextInterpolate(key_r4.description);
|
|
1827
|
+
} }
|
|
1828
|
+
function TranslationKeyListPage_ng_template_23_p_button_14_Template(rf, ctx) { if (rf & 1) {
|
|
1829
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
1830
|
+
i0.ɵɵelementStart(0, "p-button", 29);
|
|
1831
|
+
i0.ɵɵpipe(1, "translate");
|
|
1832
|
+
i0.ɵɵlistener("onClick", function TranslationKeyListPage_ng_template_23_p_button_14_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r5); const key_r4 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onEdit(key_r4)); });
|
|
1833
|
+
i0.ɵɵelementEnd();
|
|
1834
|
+
} if (rf & 2) {
|
|
1835
|
+
i0.ɵɵproperty("text", true)("pTooltip", i0.ɵɵpipeBind1(1, 2, "shared.edit"));
|
|
1836
|
+
} }
|
|
1837
|
+
function TranslationKeyListPage_ng_template_23_p_button_15_Template(rf, ctx) { if (rf & 1) {
|
|
1838
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
1839
|
+
i0.ɵɵelementStart(0, "p-button", 30);
|
|
1840
|
+
i0.ɵɵpipe(1, "translate");
|
|
1841
|
+
i0.ɵɵlistener("onClick", function TranslationKeyListPage_ng_template_23_p_button_15_Template_p_button_onClick_0_listener() { i0.ɵɵrestoreView(_r6); const key_r4 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDelete(key_r4)); });
|
|
1842
|
+
i0.ɵɵelementEnd();
|
|
1843
|
+
} if (rf & 2) {
|
|
1844
|
+
i0.ɵɵproperty("text", true)("pTooltip", i0.ɵɵpipeBind1(1, 2, "shared.delete"));
|
|
1845
|
+
} }
|
|
1846
|
+
function TranslationKeyListPage_ng_template_23_Template(rf, ctx) { if (rf & 1) {
|
|
1847
|
+
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
1848
|
+
i0.ɵɵelement(2, "p-tag", 21);
|
|
1849
|
+
i0.ɵɵelementEnd();
|
|
1850
|
+
i0.ɵɵelementStart(3, "td")(4, "div", 22);
|
|
1851
|
+
i0.ɵɵtext(5);
|
|
1852
|
+
i0.ɵɵelementEnd();
|
|
1853
|
+
i0.ɵɵconditionalCreate(6, TranslationKeyListPage_ng_template_23_Conditional_6_Template, 2, 1, "small", 23);
|
|
1854
|
+
i0.ɵɵelementEnd();
|
|
1855
|
+
i0.ɵɵelementStart(7, "td");
|
|
1856
|
+
i0.ɵɵtext(8);
|
|
1857
|
+
i0.ɵɵelementEnd();
|
|
1858
|
+
i0.ɵɵelementStart(9, "td", 24)(10, "span", 25);
|
|
1859
|
+
i0.ɵɵtext(11);
|
|
1860
|
+
i0.ɵɵelementEnd()();
|
|
1861
|
+
i0.ɵɵelementStart(12, "td")(13, "div", 26);
|
|
1862
|
+
i0.ɵɵtemplate(14, TranslationKeyListPage_ng_template_23_p_button_14_Template, 2, 4, "p-button", 27)(15, TranslationKeyListPage_ng_template_23_p_button_15_Template, 2, 4, "p-button", 28);
|
|
1863
|
+
i0.ɵɵelementEnd()()();
|
|
1864
|
+
} if (rf & 2) {
|
|
1865
|
+
const key_r4 = ctx.$implicit;
|
|
1866
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
1867
|
+
i0.ɵɵadvance(2);
|
|
1868
|
+
i0.ɵɵproperty("value", key_r4.module);
|
|
1869
|
+
i0.ɵɵadvance(3);
|
|
1870
|
+
i0.ɵɵtextInterpolate(key_r4.key);
|
|
1871
|
+
i0.ɵɵadvance();
|
|
1872
|
+
i0.ɵɵconditional(key_r4.description ? 6 : -1);
|
|
1873
|
+
i0.ɵɵadvance(2);
|
|
1874
|
+
i0.ɵɵtextInterpolate(key_r4.defaultMessage);
|
|
1875
|
+
i0.ɵɵadvance(2);
|
|
1876
|
+
i0.ɵɵclassProp("text-green-500", ctx_r2.getTranslationCount(key_r4.id) === ctx_r2.languages().length)("text-orange-500", ctx_r2.getTranslationCount(key_r4.id) < ctx_r2.languages().length && ctx_r2.getTranslationCount(key_r4.id) > 0)("text-muted-color", ctx_r2.getTranslationCount(key_r4.id) === 0);
|
|
1877
|
+
i0.ɵɵadvance();
|
|
1878
|
+
i0.ɵɵtextInterpolate2(" ", ctx_r2.getTranslationCount(key_r4.id), "/", ctx_r2.languages().length, " ");
|
|
1879
|
+
i0.ɵɵadvance(3);
|
|
1880
|
+
i0.ɵɵproperty("hasPermission", ctx_r2.TRANSLATION_KEY_PERMISSIONS.UPDATE);
|
|
1881
|
+
i0.ɵɵadvance();
|
|
1882
|
+
i0.ɵɵproperty("hasPermission", ctx_r2.TRANSLATION_KEY_PERMISSIONS.DELETE);
|
|
1883
|
+
} }
|
|
1884
|
+
function TranslationKeyListPage_ng_template_25_Template(rf, ctx) { if (rf & 1) {
|
|
1885
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 31);
|
|
1886
|
+
i0.ɵɵtext(2);
|
|
1887
|
+
i0.ɵɵpipe(3, "translate");
|
|
1888
|
+
i0.ɵɵelementEnd()();
|
|
1889
|
+
} if (rf & 2) {
|
|
1890
|
+
i0.ɵɵadvance(2);
|
|
1891
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(3, 1, "localization.key.empty"), " ");
|
|
1892
|
+
} }
|
|
1893
|
+
class TranslationKeyListPage {
|
|
1894
|
+
TRANSLATION_KEY_PERMISSIONS = TRANSLATION_KEY_PERMISSIONS;
|
|
1895
|
+
router = inject(Router);
|
|
1896
|
+
languageService = inject(LanguageApiService);
|
|
1897
|
+
translationKeyService = inject(TranslationKeyApiService);
|
|
1898
|
+
translationService = inject(TranslationApiService);
|
|
1899
|
+
confirmationService = inject(ConfirmationService);
|
|
1900
|
+
messageService = inject(MessageService);
|
|
1901
|
+
translateService = inject(TranslateService);
|
|
1902
|
+
destroyRef = inject(DestroyRef);
|
|
1903
|
+
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1904
|
+
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
1905
|
+
modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
|
|
1906
|
+
translationKeys = signal([], ...(ngDevMode ? [{ debugName: "translationKeys" }] : []));
|
|
1907
|
+
translationCounts = signal(new Map(), ...(ngDevMode ? [{ debugName: "translationCounts" }] : []));
|
|
1908
|
+
selectedModule = signal(null, ...(ngDevMode ? [{ debugName: "selectedModule" }] : []));
|
|
1909
|
+
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
1910
|
+
moduleOptions = computed(() => [
|
|
1911
|
+
{ label: this.translateService.instant('shared.all'), value: null },
|
|
1912
|
+
...this.modules().map((m) => ({ label: m, value: m })),
|
|
1913
|
+
], ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
1914
|
+
filteredKeys = computed(() => {
|
|
1915
|
+
let keys = this.translationKeys();
|
|
1916
|
+
const module = this.selectedModule();
|
|
1917
|
+
const search = this.searchTerm().toLowerCase().trim();
|
|
1918
|
+
if (module) {
|
|
1919
|
+
keys = keys.filter((k) => k.module === module);
|
|
1920
|
+
}
|
|
1921
|
+
if (search) {
|
|
1922
|
+
keys = keys.filter((k) => k.key.toLowerCase().includes(search) ||
|
|
1923
|
+
k.defaultMessage.toLowerCase().includes(search) ||
|
|
1924
|
+
k.module.toLowerCase().includes(search));
|
|
1925
|
+
}
|
|
1926
|
+
return keys;
|
|
1927
|
+
}, ...(ngDevMode ? [{ debugName: "filteredKeys" }] : []));
|
|
1928
|
+
ngOnInit() {
|
|
1929
|
+
this.loadData();
|
|
1930
|
+
}
|
|
1931
|
+
loadData() {
|
|
1932
|
+
this.isLoading.set(true);
|
|
1933
|
+
forkJoin({
|
|
1934
|
+
languages: this.languageService.getAll(),
|
|
1935
|
+
modules: this.translationKeyService.getModules(),
|
|
1936
|
+
keys: this.translationKeyService.getAll(),
|
|
1937
|
+
})
|
|
1938
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1939
|
+
.subscribe({
|
|
1940
|
+
next: ({ languages, modules, keys }) => {
|
|
1941
|
+
if (languages.success && languages.data) {
|
|
1942
|
+
this.languages.set(languages.data.filter((l) => l.isActive));
|
|
1943
|
+
}
|
|
1944
|
+
if (modules.success && modules.data) {
|
|
1945
|
+
this.modules.set(modules.data);
|
|
1946
|
+
}
|
|
1947
|
+
if (keys.success && keys.data) {
|
|
1948
|
+
this.translationKeys.set(keys.data);
|
|
1949
|
+
this.loadTranslationCounts();
|
|
1950
|
+
}
|
|
1951
|
+
this.isLoading.set(false);
|
|
1952
|
+
},
|
|
1953
|
+
error: () => {
|
|
1954
|
+
this.isLoading.set(false);
|
|
1955
|
+
},
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
loadTranslationCounts() {
|
|
1959
|
+
this.translationService.getCounts()
|
|
1960
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1961
|
+
.subscribe({
|
|
1962
|
+
next: (response) => {
|
|
1963
|
+
if (response.success && response.data) {
|
|
1964
|
+
this.translationCounts.set(new Map(Object.entries(response.data)));
|
|
1965
|
+
}
|
|
1966
|
+
},
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
getTranslationCount(keyId) {
|
|
1970
|
+
return this.translationCounts().get(keyId) ?? 0;
|
|
1971
|
+
}
|
|
1972
|
+
onModuleChange(value) {
|
|
1973
|
+
this.selectedModule.set(value);
|
|
1974
|
+
}
|
|
1975
|
+
onCreate() {
|
|
1976
|
+
this.router.navigate(['/localization/keys/new']);
|
|
1977
|
+
}
|
|
1978
|
+
onEdit(key) {
|
|
1979
|
+
this.router.navigate(['/localization/keys', key.id]);
|
|
1980
|
+
}
|
|
1981
|
+
onDelete(key) {
|
|
1982
|
+
this.confirmationService.confirm({
|
|
1983
|
+
message: this.translateService.translate('shared.confirm.delete'),
|
|
1984
|
+
header: this.translateService.translate('localization.key.delete.title'),
|
|
1985
|
+
icon: 'pi pi-exclamation-triangle',
|
|
1986
|
+
acceptButtonStyleClass: 'p-button-danger',
|
|
1987
|
+
accept: () => {
|
|
1988
|
+
this.translationKeyService.delete(key.id)
|
|
1989
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1990
|
+
.subscribe({
|
|
1991
|
+
next: (response) => {
|
|
1992
|
+
if (response.success) {
|
|
1993
|
+
this.messageService.add({
|
|
1994
|
+
severity: 'success',
|
|
1995
|
+
summary: this.translateService.instant('shared.success'),
|
|
1996
|
+
detail: this.translateService.instant('localization.translation.key.delete.success'),
|
|
1997
|
+
});
|
|
1998
|
+
this.loadData();
|
|
1999
|
+
}
|
|
2000
|
+
},
|
|
2001
|
+
});
|
|
2002
|
+
},
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
static ɵfac = function TranslationKeyListPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationKeyListPage)(); };
|
|
2006
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TranslationKeyListPage, selectors: [["lib-translation-key-list-page"]], features: [i0.ɵɵProvidersFeature([ConfirmationService, MessageService])], decls: 29, vars: 27, consts: [["header", ""], ["body", ""], ["emptymessage", ""], [1, "card"], [1, "flex", "flex-col", "sm:flex-row", "justify-between", "items-start", "sm:items-center", "gap-3", "mb-4"], [1, "text-lg", "sm:text-xl", "font-semibold", "m-0"], [1, "text-sm", "text-muted-color", "mt-1"], [1, "flex", "gap-2"], ["icon", "pi pi-plus", 3, "label", "onClick", 4, "hasPermission"], [1, "flex", "flex-col", "md:flex-row", "gap-4", "mb-4"], [1, "flex-1"], ["optionLabel", "label", "optionValue", "value", 1, "w-full", 3, "ngModelChange", "options", "ngModel", "ngModelOptions", "placeholder", "showClear"], [1, "w-full"], [1, "pi", "pi-search"], ["pInputText", "", 1, "w-full", 3, "ngModelChange", "ngModel", "ngModelOptions", "placeholder"], ["styleClass", "p-datatable-sm", 3, "value", "loading", "paginator", "rows", "rowsPerPageOptions"], ["icon", "pi pi-plus", 3, "onClick", "label"], [2, "width", "15%"], [2, "width", "25%"], [2, "width", "35%"], [2, "width", "10%"], ["severity", "secondary", 3, "value"], [1, "font-medium"], [1, "text-muted-color"], [1, "text-center"], [1, "text-sm"], [1, "flex", "gap-1"], ["icon", "pi pi-pencil", "severity", "secondary", "size", "small", 3, "text", "pTooltip", "onClick", 4, "hasPermission"], ["icon", "pi pi-trash", "severity", "danger", "size", "small", 3, "text", "pTooltip", "onClick", 4, "hasPermission"], ["icon", "pi pi-pencil", "severity", "secondary", "size", "small", 3, "onClick", "text", "pTooltip"], ["icon", "pi pi-trash", "severity", "danger", "size", "small", 3, "onClick", "text", "pTooltip"], ["colspan", "5", 1, "text-center", "py-4", "text-muted-color"]], template: function TranslationKeyListPage_Template(rf, ctx) { if (rf & 1) {
|
|
2007
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
2008
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "div")(3, "h3", 5);
|
|
2009
|
+
i0.ɵɵtext(4);
|
|
2010
|
+
i0.ɵɵpipe(5, "translate");
|
|
2011
|
+
i0.ɵɵelementEnd();
|
|
2012
|
+
i0.ɵɵelementStart(6, "p", 6);
|
|
2013
|
+
i0.ɵɵtext(7);
|
|
2014
|
+
i0.ɵɵpipe(8, "translate");
|
|
2015
|
+
i0.ɵɵelementEnd()();
|
|
2016
|
+
i0.ɵɵelementStart(9, "div", 7);
|
|
2017
|
+
i0.ɵɵtemplate(10, TranslationKeyListPage_p_button_10_Template, 2, 3, "p-button", 8);
|
|
2018
|
+
i0.ɵɵelementEnd()();
|
|
2019
|
+
i0.ɵɵelementStart(11, "div", 9)(12, "div", 10)(13, "p-select", 11);
|
|
2020
|
+
i0.ɵɵpipe(14, "translate");
|
|
2021
|
+
i0.ɵɵlistener("ngModelChange", function TranslationKeyListPage_Template_p_select_ngModelChange_13_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onModuleChange($event)); });
|
|
2022
|
+
i0.ɵɵelementEnd()();
|
|
2023
|
+
i0.ɵɵelementStart(15, "div", 10)(16, "p-iconfield", 12);
|
|
2024
|
+
i0.ɵɵelement(17, "p-inputicon", 13);
|
|
2025
|
+
i0.ɵɵelementStart(18, "input", 14);
|
|
2026
|
+
i0.ɵɵpipe(19, "translate");
|
|
2027
|
+
i0.ɵɵlistener("ngModelChange", function TranslationKeyListPage_Template_input_ngModelChange_18_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.searchTerm.set($event)); });
|
|
2028
|
+
i0.ɵɵelementEnd()()()();
|
|
2029
|
+
i0.ɵɵelementStart(20, "p-table", 15);
|
|
2030
|
+
i0.ɵɵtemplate(21, TranslationKeyListPage_ng_template_21_Template, 16, 15, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(23, TranslationKeyListPage_ng_template_23_Template, 16, 14, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor)(25, TranslationKeyListPage_ng_template_25_Template, 4, 3, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
|
|
2031
|
+
i0.ɵɵelementEnd()();
|
|
2032
|
+
i0.ɵɵelement(27, "p-confirmDialog")(28, "p-toast");
|
|
2033
|
+
} if (rf & 2) {
|
|
2034
|
+
i0.ɵɵadvance(4);
|
|
2035
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(5, 16, "localization.key.title"));
|
|
2036
|
+
i0.ɵɵadvance(3);
|
|
2037
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(8, 18, "localization.key.subtitle"));
|
|
2038
|
+
i0.ɵɵadvance(3);
|
|
2039
|
+
i0.ɵɵproperty("hasPermission", ctx.TRANSLATION_KEY_PERMISSIONS.CREATE);
|
|
2040
|
+
i0.ɵɵadvance(3);
|
|
2041
|
+
i0.ɵɵproperty("options", ctx.moduleOptions())("ngModel", ctx.selectedModule())("ngModelOptions", i0.ɵɵpureFunction0(24, _c0$2))("placeholder", i0.ɵɵpipeBind1(14, 20, "localization.key.filter.module"))("showClear", true);
|
|
2042
|
+
i0.ɵɵadvance(5);
|
|
2043
|
+
i0.ɵɵproperty("ngModel", ctx.searchTerm())("ngModelOptions", i0.ɵɵpureFunction0(25, _c0$2))("placeholder", i0.ɵɵpipeBind1(19, 22, "shared.search"));
|
|
2044
|
+
i0.ɵɵadvance(2);
|
|
2045
|
+
i0.ɵɵproperty("value", ctx.filteredKeys())("loading", ctx.isLoading())("paginator", true)("rows", 15)("rowsPerPageOptions", i0.ɵɵpureFunction0(26, _c1$1));
|
|
2046
|
+
} }, dependencies: [AngularModule, i1$1.DefaultValueAccessor, i1$1.NgControlStatus, i1$1.NgModel, PrimeModule, i2.Button, i2$1.ConfirmDialog, i4$2.IconField, i5$1.InputIcon, i4$1.InputText, i5.Select, i8.Table, i4.Tag, i10.Toast, i6.Tooltip, FormsModule, HasPermissionDirective, TranslatePipe], encapsulation: 2 });
|
|
2047
|
+
}
|
|
2048
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationKeyListPage, [{
|
|
2049
|
+
type: Component,
|
|
2050
|
+
args: [{
|
|
2051
|
+
selector: 'lib-translation-key-list-page',
|
|
2052
|
+
imports: [AngularModule, PrimeModule, FormsModule, HasPermissionDirective, TranslatePipe],
|
|
2053
|
+
providers: [ConfirmationService, MessageService],
|
|
2054
|
+
template: `
|
|
2055
|
+
<div class="card">
|
|
2056
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
|
|
2057
|
+
<div>
|
|
2058
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">{{ 'localization.key.title' | translate }}</h3>
|
|
2059
|
+
<p class="text-sm text-muted-color mt-1">{{ 'localization.key.subtitle' | translate }}</p>
|
|
2060
|
+
</div>
|
|
2061
|
+
<div class="flex gap-2">
|
|
2062
|
+
<p-button
|
|
2063
|
+
*hasPermission="TRANSLATION_KEY_PERMISSIONS.CREATE"
|
|
2064
|
+
[label]="'localization.key.create' | translate"
|
|
2065
|
+
icon="pi pi-plus"
|
|
2066
|
+
(onClick)="onCreate()"
|
|
2067
|
+
/>
|
|
2068
|
+
</div>
|
|
2069
|
+
</div>
|
|
2070
|
+
|
|
2071
|
+
<!-- Filters -->
|
|
2072
|
+
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
2073
|
+
<div class="flex-1">
|
|
2074
|
+
<p-select
|
|
2075
|
+
[options]="moduleOptions()"
|
|
2076
|
+
[ngModel]="selectedModule()"
|
|
2077
|
+
(ngModelChange)="onModuleChange($event)"
|
|
2078
|
+
[ngModelOptions]="{standalone: true}"
|
|
2079
|
+
optionLabel="label"
|
|
2080
|
+
optionValue="value"
|
|
2081
|
+
[placeholder]="'localization.key.filter.module' | translate"
|
|
2082
|
+
[showClear]="true"
|
|
2083
|
+
class="w-full"
|
|
2084
|
+
/>
|
|
2085
|
+
</div>
|
|
2086
|
+
<div class="flex-1">
|
|
2087
|
+
<p-iconfield class="w-full">
|
|
2088
|
+
<p-inputicon class="pi pi-search" />
|
|
2089
|
+
<input
|
|
2090
|
+
pInputText
|
|
2091
|
+
[ngModel]="searchTerm()"
|
|
2092
|
+
(ngModelChange)="searchTerm.set($event)"
|
|
2093
|
+
[ngModelOptions]="{standalone: true}"
|
|
2094
|
+
[placeholder]="'shared.search' | translate"
|
|
2095
|
+
class="w-full"
|
|
2096
|
+
/>
|
|
2097
|
+
</p-iconfield>
|
|
2098
|
+
</div>
|
|
2099
|
+
</div>
|
|
2100
|
+
|
|
2101
|
+
<!-- Table -->
|
|
2102
|
+
<p-table
|
|
2103
|
+
[value]="filteredKeys()"
|
|
2104
|
+
[loading]="isLoading()"
|
|
2105
|
+
[paginator]="true"
|
|
2106
|
+
[rows]="15"
|
|
2107
|
+
[rowsPerPageOptions]="[10, 15, 25, 50]"
|
|
2108
|
+
styleClass="p-datatable-sm"
|
|
2109
|
+
>
|
|
2110
|
+
<ng-template #header>
|
|
2111
|
+
<tr>
|
|
2112
|
+
<th style="width: 15%">{{ 'localization.key.module' | translate }}</th>
|
|
2113
|
+
<th style="width: 25%">{{ 'localization.key.name' | translate }}</th>
|
|
2114
|
+
<th style="width: 35%">{{ 'localization.key.default.message' | translate }}</th>
|
|
2115
|
+
<th style="width: 10%">{{ 'localization.key.translations' | translate }}</th>
|
|
2116
|
+
<th style="width: 15%">{{ 'shared.actions' | translate }}</th>
|
|
2117
|
+
</tr>
|
|
2118
|
+
</ng-template>
|
|
2119
|
+
<ng-template #body let-key>
|
|
2120
|
+
<tr>
|
|
2121
|
+
<td>
|
|
2122
|
+
<p-tag [value]="key.module" severity="secondary" />
|
|
2123
|
+
</td>
|
|
2124
|
+
<td>
|
|
2125
|
+
<div class="font-medium">{{ key.key }}</div>
|
|
2126
|
+
@if (key.description) {
|
|
2127
|
+
<small class="text-muted-color">{{ key.description }}</small>
|
|
2128
|
+
}
|
|
2129
|
+
</td>
|
|
2130
|
+
<td>{{ key.defaultMessage }}</td>
|
|
2131
|
+
<td class="text-center">
|
|
2132
|
+
<span class="text-sm" [class.text-green-500]="getTranslationCount(key.id) === languages().length" [class.text-orange-500]="getTranslationCount(key.id) < languages().length && getTranslationCount(key.id) > 0" [class.text-muted-color]="getTranslationCount(key.id) === 0">
|
|
2133
|
+
{{ getTranslationCount(key.id) }}/{{ languages().length }}
|
|
2134
|
+
</span>
|
|
2135
|
+
</td>
|
|
2136
|
+
<td>
|
|
2137
|
+
<div class="flex gap-1">
|
|
2138
|
+
<p-button
|
|
2139
|
+
*hasPermission="TRANSLATION_KEY_PERMISSIONS.UPDATE"
|
|
2140
|
+
icon="pi pi-pencil"
|
|
2141
|
+
[text]="true"
|
|
2142
|
+
severity="secondary"
|
|
2143
|
+
size="small"
|
|
2144
|
+
[pTooltip]="'shared.edit' | translate"
|
|
2145
|
+
(onClick)="onEdit(key)"
|
|
2146
|
+
/>
|
|
2147
|
+
<p-button
|
|
2148
|
+
*hasPermission="TRANSLATION_KEY_PERMISSIONS.DELETE"
|
|
2149
|
+
icon="pi pi-trash"
|
|
2150
|
+
[text]="true"
|
|
2151
|
+
severity="danger"
|
|
2152
|
+
size="small"
|
|
2153
|
+
[pTooltip]="'shared.delete' | translate"
|
|
2154
|
+
(onClick)="onDelete(key)"
|
|
2155
|
+
/>
|
|
2156
|
+
</div>
|
|
2157
|
+
</td>
|
|
2158
|
+
</tr>
|
|
2159
|
+
</ng-template>
|
|
2160
|
+
<ng-template #emptymessage>
|
|
2161
|
+
<tr>
|
|
2162
|
+
<td colspan="5" class="text-center py-4 text-muted-color">
|
|
2163
|
+
{{ 'localization.key.empty' | translate }}
|
|
2164
|
+
</td>
|
|
2165
|
+
</tr>
|
|
2166
|
+
</ng-template>
|
|
2167
|
+
</p-table>
|
|
2168
|
+
</div>
|
|
2169
|
+
|
|
2170
|
+
<p-confirmDialog />
|
|
2171
|
+
<p-toast />
|
|
2172
|
+
`,
|
|
2173
|
+
}]
|
|
2174
|
+
}], null, null); })();
|
|
2175
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TranslationKeyListPage, { className: "TranslationKeyListPage", filePath: "pages/translation-key-list/translation-key-list.page.ts", lineNumber: 146 }); })();
|
|
2176
|
+
|
|
2177
|
+
var translationKeyList_page = /*#__PURE__*/Object.freeze({
|
|
2178
|
+
__proto__: null,
|
|
2179
|
+
TranslationKeyListPage: TranslationKeyListPage
|
|
2180
|
+
});
|
|
2181
|
+
|
|
2182
|
+
const _c0$1 = () => ({ standalone: true });
|
|
2183
|
+
const _forTrack0 = ($index, $item) => $item.id;
|
|
2184
|
+
function TranslationKeyFormPage_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
2185
|
+
i0.ɵɵelementStart(0, "div", 23)(1, "h2", 24);
|
|
2186
|
+
i0.ɵɵtext(2);
|
|
2187
|
+
i0.ɵɵpipe(3, "translate");
|
|
2188
|
+
i0.ɵɵpipe(4, "translate");
|
|
2189
|
+
i0.ɵɵelementEnd()();
|
|
2190
|
+
} if (rf & 2) {
|
|
2191
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
2192
|
+
i0.ɵɵadvance(2);
|
|
2193
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.isEditMode() ? i0.ɵɵpipeBind1(3, 1, "localization.key.edit") : i0.ɵɵpipeBind1(4, 3, "localization.key.create"), " ");
|
|
2194
|
+
} }
|
|
2195
|
+
function TranslationKeyFormPage_Conditional_46_Template(rf, ctx) { if (rf & 1) {
|
|
2196
|
+
i0.ɵɵelementStart(0, "div", 18);
|
|
2197
|
+
i0.ɵɵelement(1, "p-progressSpinner", 25);
|
|
2198
|
+
i0.ɵɵelementEnd();
|
|
2199
|
+
} }
|
|
2200
|
+
function TranslationKeyFormPage_Conditional_47_Template(rf, ctx) { if (rf & 1) {
|
|
2201
|
+
i0.ɵɵelementStart(0, "p", 19);
|
|
2202
|
+
i0.ɵɵtext(1);
|
|
2203
|
+
i0.ɵɵpipe(2, "translate");
|
|
2204
|
+
i0.ɵɵelementEnd();
|
|
2205
|
+
} if (rf & 2) {
|
|
2206
|
+
i0.ɵɵadvance();
|
|
2207
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(2, 1, "localization.key.no.languages"), " ");
|
|
2208
|
+
} }
|
|
2209
|
+
function TranslationKeyFormPage_Conditional_48_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
2210
|
+
i0.ɵɵelementStart(0, "span", 17);
|
|
2211
|
+
i0.ɵɵtext(1);
|
|
2212
|
+
i0.ɵɵelementEnd();
|
|
2213
|
+
} if (rf & 2) {
|
|
2214
|
+
const lang_r4 = i0.ɵɵnextContext().$implicit;
|
|
2215
|
+
i0.ɵɵadvance();
|
|
2216
|
+
i0.ɵɵtextInterpolate1("(", lang_r4.nativeName, ")");
|
|
2217
|
+
} }
|
|
2218
|
+
function TranslationKeyFormPage_Conditional_48_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
2219
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
2220
|
+
i0.ɵɵelementStart(0, "div", 5)(1, "div", 26)(2, "label", 27);
|
|
2221
|
+
i0.ɵɵtext(3);
|
|
2222
|
+
i0.ɵɵconditionalCreate(4, TranslationKeyFormPage_Conditional_48_For_2_Conditional_4_Template, 2, 1, "span", 17);
|
|
2223
|
+
i0.ɵɵelementEnd();
|
|
2224
|
+
i0.ɵɵelement(5, "p-tag", 28);
|
|
2225
|
+
i0.ɵɵelementEnd();
|
|
2226
|
+
i0.ɵɵelementStart(6, "textarea", 29);
|
|
2227
|
+
i0.ɵɵpipe(7, "translate");
|
|
2228
|
+
i0.ɵɵlistener("ngModelChange", function TranslationKeyFormPage_Conditional_48_For_2_Template_textarea_ngModelChange_6_listener($event) { const lang_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.setTranslationValue(lang_r4.id, $event)); });
|
|
2229
|
+
i0.ɵɵelementEnd()();
|
|
2230
|
+
} if (rf & 2) {
|
|
2231
|
+
const lang_r4 = ctx.$implicit;
|
|
2232
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
2233
|
+
i0.ɵɵadvance(3);
|
|
2234
|
+
i0.ɵɵtextInterpolate1(" ", lang_r4.name, " ");
|
|
2235
|
+
i0.ɵɵadvance();
|
|
2236
|
+
i0.ɵɵconditional(lang_r4.nativeName && lang_r4.nativeName !== lang_r4.name ? 4 : -1);
|
|
2237
|
+
i0.ɵɵadvance();
|
|
2238
|
+
i0.ɵɵproperty("value", lang_r4.code);
|
|
2239
|
+
i0.ɵɵadvance();
|
|
2240
|
+
i0.ɵɵproperty("ngModel", ctx_r1.getTranslationValue(lang_r4.id))("ngModelOptions", i0.ɵɵpureFunction0(9, _c0$1))("rows", 2)("placeholder", ctx_r1.formModel().defaultMessage || i0.ɵɵpipeBind1(7, 7, "localization.key.enter.translation"));
|
|
2241
|
+
} }
|
|
2242
|
+
function TranslationKeyFormPage_Conditional_48_Template(rf, ctx) { if (rf & 1) {
|
|
2243
|
+
i0.ɵɵelementStart(0, "div", 4);
|
|
2244
|
+
i0.ɵɵrepeaterCreate(1, TranslationKeyFormPage_Conditional_48_For_2_Template, 8, 10, "div", 5, _forTrack0);
|
|
2245
|
+
i0.ɵɵelementEnd();
|
|
2246
|
+
} if (rf & 2) {
|
|
2247
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
2248
|
+
i0.ɵɵadvance();
|
|
2249
|
+
i0.ɵɵrepeater(ctx_r1.languages());
|
|
2250
|
+
} }
|
|
2251
|
+
class TranslationKeyFormPage {
|
|
2252
|
+
router = inject(Router);
|
|
2253
|
+
route = inject(ActivatedRoute);
|
|
2254
|
+
languageService = inject(LanguageApiService);
|
|
2255
|
+
translationKeyService = inject(TranslationKeyApiService);
|
|
2256
|
+
translationService = inject(TranslationApiService);
|
|
2257
|
+
messageService = inject(MessageService);
|
|
2258
|
+
translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
|
|
2259
|
+
destroyRef = inject(DestroyRef);
|
|
2260
|
+
routeParams = toSignal(this.route.paramMap);
|
|
2261
|
+
loadTriggered = false;
|
|
2262
|
+
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
2263
|
+
isLoadingLanguages = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingLanguages" }] : []));
|
|
2264
|
+
existingKey = signal(null, ...(ngDevMode ? [{ debugName: "existingKey" }] : []));
|
|
2265
|
+
isEditMode = computed(() => !!this.existingKey(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
2266
|
+
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
2267
|
+
modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
|
|
2268
|
+
translations = signal([], ...(ngDevMode ? [{ debugName: "translations" }] : []));
|
|
2269
|
+
translate(key) {
|
|
2270
|
+
return this.translateAdapter?.translate(key) ?? key;
|
|
2271
|
+
}
|
|
2272
|
+
moduleOptions = computed(() => this.modules().map((m) => ({ label: m, value: m })), ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
2273
|
+
formModel = signal({
|
|
2274
|
+
key: '',
|
|
2275
|
+
module: '',
|
|
2276
|
+
defaultMessage: '',
|
|
2277
|
+
description: '',
|
|
2278
|
+
variables: '',
|
|
2279
|
+
}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
2280
|
+
formTree = form(this.formModel, (f) => {
|
|
2281
|
+
required(f.key, { message: this.translate('localization.validation.key.required') });
|
|
2282
|
+
required(f.defaultMessage, { message: this.translate('localization.validation.default.message.required') });
|
|
2283
|
+
});
|
|
2284
|
+
isFormValid = computed(() => {
|
|
2285
|
+
const model = this.formModel();
|
|
2286
|
+
return model.key.trim().length > 0 && model.module.trim().length > 0 && model.defaultMessage.trim().length > 0;
|
|
2287
|
+
}, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
|
|
2288
|
+
constructor() {
|
|
2289
|
+
effect(() => {
|
|
2290
|
+
const params = this.routeParams();
|
|
2291
|
+
if (!params || this.loadTriggered)
|
|
2292
|
+
return;
|
|
2293
|
+
this.loadTriggered = true;
|
|
2294
|
+
const id = params.get('id');
|
|
2295
|
+
if (id && id !== 'new') {
|
|
2296
|
+
this.loadTranslationKey(id);
|
|
2297
|
+
}
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2300
|
+
ngOnInit() {
|
|
2301
|
+
this.loadInitialData();
|
|
2302
|
+
}
|
|
2303
|
+
loadInitialData() {
|
|
2304
|
+
this.isLoadingLanguages.set(true);
|
|
2305
|
+
forkJoin({
|
|
2306
|
+
languages: this.languageService.getAll(),
|
|
2307
|
+
modules: this.translationKeyService.getModules(),
|
|
2308
|
+
})
|
|
2309
|
+
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isLoadingLanguages.set(false)))
|
|
2310
|
+
.subscribe({
|
|
2311
|
+
next: ({ languages, modules }) => {
|
|
2312
|
+
if (languages.success && languages.data) {
|
|
2313
|
+
const activeLanguages = languages.data.filter((l) => l.isActive);
|
|
2314
|
+
this.languages.set(activeLanguages);
|
|
2315
|
+
this.initializeTranslations(activeLanguages);
|
|
2316
|
+
}
|
|
2317
|
+
if (modules.success && modules.data) {
|
|
2318
|
+
this.modules.set(modules.data);
|
|
2319
|
+
}
|
|
2320
|
+
},
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
initializeTranslations(languages) {
|
|
2324
|
+
const current = this.translations();
|
|
2325
|
+
if (current.length === 0) {
|
|
2326
|
+
this.translations.set(languages.map((lang) => ({ languageId: lang.id, value: '' })));
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
updateModule(value) {
|
|
2330
|
+
this.formModel.update((m) => ({ ...m, module: value ?? '' }));
|
|
2331
|
+
}
|
|
2332
|
+
getTranslationValue(languageId) {
|
|
2333
|
+
return this.translations().find((t) => t.languageId === languageId)?.value ?? '';
|
|
2334
|
+
}
|
|
2335
|
+
setTranslationValue(languageId, value) {
|
|
2336
|
+
this.translations.update((list) => {
|
|
2337
|
+
const existing = list.find((t) => t.languageId === languageId);
|
|
2338
|
+
if (existing) {
|
|
2339
|
+
return list.map((t) => (t.languageId === languageId ? { ...t, value } : t));
|
|
2340
|
+
}
|
|
2341
|
+
return [...list, { languageId, value }];
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2344
|
+
loadTranslationKey(id) {
|
|
2345
|
+
this.isSaving.set(true);
|
|
2346
|
+
this.translationKeyService.getById(id)
|
|
2347
|
+
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
2348
|
+
.subscribe({
|
|
2349
|
+
next: (response) => {
|
|
2350
|
+
if (response.success && response.data) {
|
|
2351
|
+
this.existingKey.set(response.data);
|
|
2352
|
+
this.formModel.set(this.toFormModel(response.data));
|
|
2353
|
+
this.loadExistingTranslations(id);
|
|
2354
|
+
}
|
|
2355
|
+
},
|
|
2356
|
+
error: () => this.router.navigate(['/localization/keys']),
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
loadExistingTranslations(keyId) {
|
|
2360
|
+
this.translationService.getByKeyId(keyId)
|
|
2361
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2362
|
+
.subscribe({
|
|
2363
|
+
next: (response) => {
|
|
2364
|
+
if (response.success && response.data) {
|
|
2365
|
+
this.translations.update((list) => {
|
|
2366
|
+
const updated = [...list];
|
|
2367
|
+
response.data.forEach((t) => {
|
|
2368
|
+
const existing = updated.find((tr) => tr.languageId === t.languageId);
|
|
2369
|
+
if (existing) {
|
|
2370
|
+
existing.value = t.value;
|
|
2371
|
+
existing.translationId = t.id;
|
|
2372
|
+
}
|
|
2373
|
+
else {
|
|
2374
|
+
updated.push({ languageId: t.languageId, value: t.value, translationId: t.id });
|
|
2375
|
+
}
|
|
2376
|
+
});
|
|
2377
|
+
return updated;
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
},
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
toFormModel(key) {
|
|
2384
|
+
return {
|
|
2385
|
+
key: key.key,
|
|
2386
|
+
module: key.module,
|
|
2387
|
+
defaultMessage: key.defaultMessage,
|
|
2388
|
+
description: key.description ?? '',
|
|
2389
|
+
variables: key.variables?.join(', ') ?? '',
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
onSubmit() {
|
|
2393
|
+
if (!this.isFormValid())
|
|
2394
|
+
return;
|
|
2395
|
+
this.isSaving.set(true);
|
|
2396
|
+
const model = this.formModel();
|
|
2397
|
+
const variables = model.variables
|
|
2398
|
+
.split(',')
|
|
2399
|
+
.map((v) => v.trim())
|
|
2400
|
+
.filter((v) => v.length > 0);
|
|
2401
|
+
if (this.isEditMode()) {
|
|
2402
|
+
this.updateKey(model, variables);
|
|
2403
|
+
}
|
|
2404
|
+
else {
|
|
2405
|
+
this.createKey(model, variables);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
createKey(model, variables) {
|
|
2409
|
+
const createDto = {
|
|
2410
|
+
key: model.key,
|
|
2411
|
+
module: model.module,
|
|
2412
|
+
defaultMessage: model.defaultMessage,
|
|
2413
|
+
description: model.description || undefined,
|
|
2414
|
+
variables: variables.length > 0 ? variables : undefined,
|
|
2415
|
+
};
|
|
2416
|
+
this.translationKeyService.create(createDto)
|
|
2417
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2418
|
+
.subscribe({
|
|
2419
|
+
next: (response) => {
|
|
2420
|
+
if (response.success && response.data) {
|
|
2421
|
+
this.saveTranslations(response.data.id);
|
|
2422
|
+
}
|
|
2423
|
+
else {
|
|
2424
|
+
this.isSaving.set(false);
|
|
2425
|
+
}
|
|
2426
|
+
},
|
|
2427
|
+
error: () => this.isSaving.set(false),
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
updateKey(model, variables) {
|
|
2431
|
+
const updateDto = {
|
|
2432
|
+
id: this.existingKey().id,
|
|
2433
|
+
key: model.key,
|
|
2434
|
+
module: model.module,
|
|
2435
|
+
defaultMessage: model.defaultMessage,
|
|
2436
|
+
description: model.description || undefined,
|
|
2437
|
+
variables: variables.length > 0 ? variables : undefined,
|
|
2438
|
+
};
|
|
2439
|
+
this.translationKeyService.update(updateDto)
|
|
2440
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2441
|
+
.subscribe({
|
|
2442
|
+
next: (response) => {
|
|
2443
|
+
if (response.success) {
|
|
2444
|
+
this.saveTranslations(this.existingKey().id);
|
|
2445
|
+
}
|
|
2446
|
+
else {
|
|
2447
|
+
this.isSaving.set(false);
|
|
2448
|
+
}
|
|
2449
|
+
},
|
|
2450
|
+
error: () => this.isSaving.set(false),
|
|
2451
|
+
});
|
|
2452
|
+
}
|
|
2453
|
+
saveTranslations(keyId) {
|
|
2454
|
+
const translationsToSave = this.translations()
|
|
2455
|
+
.filter((t) => t.value?.trim())
|
|
2456
|
+
.map((t) => ({
|
|
2457
|
+
id: t.translationId,
|
|
2458
|
+
languageId: t.languageId,
|
|
2459
|
+
translationKeyId: keyId,
|
|
2460
|
+
value: t.value,
|
|
2461
|
+
isVerified: false,
|
|
2462
|
+
}));
|
|
2463
|
+
if (translationsToSave.length === 0) {
|
|
2464
|
+
this.onSaveSuccess();
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2467
|
+
this.translationService.bulkUpdate(translationsToSave)
|
|
2468
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2469
|
+
.subscribe({
|
|
2470
|
+
next: () => this.onSaveSuccess(),
|
|
2471
|
+
error: () => this.onSaveSuccess(),
|
|
2472
|
+
});
|
|
2473
|
+
}
|
|
2474
|
+
onSaveSuccess() {
|
|
2475
|
+
this.messageService.add({
|
|
2476
|
+
severity: 'success',
|
|
2477
|
+
summary: this.translate('shared.success'),
|
|
2478
|
+
detail: this.translate(this.isEditMode() ? 'localization.translation.key.update.success' : 'localization.translation.key.create.success'),
|
|
2479
|
+
});
|
|
2480
|
+
this.isSaving.set(false);
|
|
2481
|
+
this.router.navigate(['/localization/keys']);
|
|
2482
|
+
}
|
|
2483
|
+
onCancel() {
|
|
2484
|
+
this.router.navigate(['/localization/keys']);
|
|
2485
|
+
}
|
|
2486
|
+
static ɵfac = function TranslationKeyFormPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationKeyFormPage)(); };
|
|
2487
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TranslationKeyFormPage, selectors: [["lib-translation-key-form-page"]], features: [i0.ɵɵProvidersFeature([MessageService])], decls: 56, vars: 65, consts: [["header", ""], [1, "flex", "flex-col", "gap-6", 3, "ngSubmit"], [1, "p-4", "surface-ground", "rounded-lg"], [1, "font-semibold", "mt-0", "mb-4"], [1, "grid", "grid-cols-1", "md:grid-cols-2", "gap-4"], [1, "flex", "flex-col", "gap-2"], ["for", "key", 1, "font-medium"], ["pInputText", "", "id", "key", 3, "formField", "placeholder"], ["for", "module", 1, "font-medium"], ["id", "module", "optionLabel", "label", "optionValue", "value", 1, "w-full", 3, "ngModelChange", "ngModel", "ngModelOptions", "options", "editable", "placeholder"], [1, "flex", "flex-col", "gap-2", "md:col-span-2"], ["for", "defaultMessage", 1, "font-medium"], ["pInputTextarea", "", "id", "defaultMessage", 3, "formField", "rows", "placeholder"], ["for", "description", 1, "font-medium"], ["pInputText", "", "id", "description", 3, "formField", "placeholder"], ["for", "variables", 1, "font-medium"], ["pInputText", "", "id", "variables", 3, "formField", "placeholder"], [1, "text-muted-color"], [1, "flex", "justify-center", "py-4"], [1, "text-muted-color", "text-center", "py-4"], [1, "flex", "justify-end", "gap-4", "pt-4"], ["severity", "secondary", 3, "onClick", "label", "outlined"], ["type", "submit", 3, "label", "loading", "disabled"], [1, "flex", "justify-between", "items-center", "p-4"], [1, "text-xl", "font-semibold", "m-0"], ["strokeWidth", "4"], [1, "flex", "justify-between", "items-center"], [1, "font-medium"], ["severity", "secondary", 1, "uppercase", 3, "value"], ["pInputTextarea", "", 3, "ngModelChange", "ngModel", "ngModelOptions", "rows", "placeholder"]], template: function TranslationKeyFormPage_Template(rf, ctx) { if (rf & 1) {
|
|
2488
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
2489
|
+
i0.ɵɵelementStart(0, "p-card");
|
|
2490
|
+
i0.ɵɵtemplate(1, TranslationKeyFormPage_ng_template_1_Template, 5, 5, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
2491
|
+
i0.ɵɵelementStart(3, "form", 1);
|
|
2492
|
+
i0.ɵɵlistener("ngSubmit", function TranslationKeyFormPage_Template_form_ngSubmit_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSubmit()); });
|
|
2493
|
+
i0.ɵɵelementStart(4, "div", 2)(5, "h4", 3);
|
|
2494
|
+
i0.ɵɵtext(6);
|
|
2495
|
+
i0.ɵɵpipe(7, "translate");
|
|
2496
|
+
i0.ɵɵelementEnd();
|
|
2497
|
+
i0.ɵɵelementStart(8, "div", 4)(9, "div", 5)(10, "label", 6);
|
|
2498
|
+
i0.ɵɵtext(11);
|
|
2499
|
+
i0.ɵɵpipe(12, "translate");
|
|
2500
|
+
i0.ɵɵelementEnd();
|
|
2501
|
+
i0.ɵɵelement(13, "input", 7);
|
|
2502
|
+
i0.ɵɵpipe(14, "translate");
|
|
2503
|
+
i0.ɵɵcontrolCreate();
|
|
2504
|
+
i0.ɵɵelementEnd();
|
|
2505
|
+
i0.ɵɵelementStart(15, "div", 5)(16, "label", 8);
|
|
2506
|
+
i0.ɵɵtext(17);
|
|
2507
|
+
i0.ɵɵpipe(18, "translate");
|
|
2508
|
+
i0.ɵɵelementEnd();
|
|
2509
|
+
i0.ɵɵelementStart(19, "p-select", 9);
|
|
2510
|
+
i0.ɵɵpipe(20, "translate");
|
|
2511
|
+
i0.ɵɵlistener("ngModelChange", function TranslationKeyFormPage_Template_p_select_ngModelChange_19_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.updateModule($event)); });
|
|
2512
|
+
i0.ɵɵelementEnd()();
|
|
2513
|
+
i0.ɵɵelementStart(21, "div", 10)(22, "label", 11);
|
|
2514
|
+
i0.ɵɵtext(23);
|
|
2515
|
+
i0.ɵɵpipe(24, "translate");
|
|
2516
|
+
i0.ɵɵelementEnd();
|
|
2517
|
+
i0.ɵɵelement(25, "textarea", 12);
|
|
2518
|
+
i0.ɵɵpipe(26, "translate");
|
|
2519
|
+
i0.ɵɵcontrolCreate();
|
|
2520
|
+
i0.ɵɵelementEnd();
|
|
2521
|
+
i0.ɵɵelementStart(27, "div", 10)(28, "label", 13);
|
|
2522
|
+
i0.ɵɵtext(29);
|
|
2523
|
+
i0.ɵɵpipe(30, "translate");
|
|
2524
|
+
i0.ɵɵelementEnd();
|
|
2525
|
+
i0.ɵɵelement(31, "input", 14);
|
|
2526
|
+
i0.ɵɵpipe(32, "translate");
|
|
2527
|
+
i0.ɵɵcontrolCreate();
|
|
2528
|
+
i0.ɵɵelementEnd();
|
|
2529
|
+
i0.ɵɵelementStart(33, "div", 10)(34, "label", 15);
|
|
2530
|
+
i0.ɵɵtext(35);
|
|
2531
|
+
i0.ɵɵpipe(36, "translate");
|
|
2532
|
+
i0.ɵɵelementEnd();
|
|
2533
|
+
i0.ɵɵelement(37, "input", 16);
|
|
2534
|
+
i0.ɵɵpipe(38, "translate");
|
|
2535
|
+
i0.ɵɵcontrolCreate();
|
|
2536
|
+
i0.ɵɵelementStart(39, "small", 17);
|
|
2537
|
+
i0.ɵɵtext(40);
|
|
2538
|
+
i0.ɵɵpipe(41, "translate");
|
|
2539
|
+
i0.ɵɵelementEnd()()()();
|
|
2540
|
+
i0.ɵɵelementStart(42, "div", 2)(43, "h4", 3);
|
|
2541
|
+
i0.ɵɵtext(44);
|
|
2542
|
+
i0.ɵɵpipe(45, "translate");
|
|
2543
|
+
i0.ɵɵelementEnd();
|
|
2544
|
+
i0.ɵɵconditionalCreate(46, TranslationKeyFormPage_Conditional_46_Template, 2, 0, "div", 18)(47, TranslationKeyFormPage_Conditional_47_Template, 3, 3, "p", 19)(48, TranslationKeyFormPage_Conditional_48_Template, 3, 0, "div", 4);
|
|
2545
|
+
i0.ɵɵelementEnd();
|
|
2546
|
+
i0.ɵɵelementStart(49, "div", 20)(50, "p-button", 21);
|
|
2547
|
+
i0.ɵɵpipe(51, "translate");
|
|
2548
|
+
i0.ɵɵlistener("onClick", function TranslationKeyFormPage_Template_p_button_onClick_50_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onCancel()); });
|
|
2549
|
+
i0.ɵɵelementEnd();
|
|
2550
|
+
i0.ɵɵelement(52, "p-button", 22);
|
|
2551
|
+
i0.ɵɵpipe(53, "translate");
|
|
2552
|
+
i0.ɵɵpipe(54, "translate");
|
|
2553
|
+
i0.ɵɵelementEnd()()();
|
|
2554
|
+
i0.ɵɵelement(55, "p-toast");
|
|
2555
|
+
} if (rf & 2) {
|
|
2556
|
+
i0.ɵɵadvance(6);
|
|
2557
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 32, "localization.key.about"));
|
|
2558
|
+
i0.ɵɵadvance(5);
|
|
2559
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(12, 34, "localization.key.name"), " *");
|
|
2560
|
+
i0.ɵɵadvance(2);
|
|
2561
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(14, 36, "localization.placeholder.key.name"));
|
|
2562
|
+
i0.ɵɵcontrol(ctx.formTree.key, "formField");
|
|
2563
|
+
i0.ɵɵadvance(4);
|
|
2564
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(18, 38, "localization.key.module"), " *");
|
|
2565
|
+
i0.ɵɵadvance(2);
|
|
2566
|
+
i0.ɵɵproperty("ngModel", ctx.formModel().module)("ngModelOptions", i0.ɵɵpureFunction0(64, _c0$1))("options", ctx.moduleOptions())("editable", true)("placeholder", i0.ɵɵpipeBind1(20, 40, "localization.key.select.module"));
|
|
2567
|
+
i0.ɵɵadvance(4);
|
|
2568
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(24, 42, "localization.key.default.message"), " *");
|
|
2569
|
+
i0.ɵɵadvance(2);
|
|
2570
|
+
i0.ɵɵproperty("rows", 2)("placeholder", i0.ɵɵpipeBind1(26, 44, "localization.placeholder.default.message"));
|
|
2571
|
+
i0.ɵɵcontrol(ctx.formTree.defaultMessage, "formField");
|
|
2572
|
+
i0.ɵɵadvance(4);
|
|
2573
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(30, 46, "localization.key.description"));
|
|
2574
|
+
i0.ɵɵadvance(2);
|
|
2575
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(32, 48, "localization.placeholder.key.description"));
|
|
2576
|
+
i0.ɵɵcontrol(ctx.formTree.description, "formField");
|
|
2577
|
+
i0.ɵɵadvance(4);
|
|
2578
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(36, 50, "localization.key.variables"));
|
|
2579
|
+
i0.ɵɵadvance(2);
|
|
2580
|
+
i0.ɵɵproperty("placeholder", i0.ɵɵpipeBind1(38, 52, "localization.key.variables.placeholder"));
|
|
2581
|
+
i0.ɵɵcontrol(ctx.formTree.variables, "formField");
|
|
2582
|
+
i0.ɵɵadvance(3);
|
|
2583
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(41, 54, "localization.key.variables.hint"));
|
|
2584
|
+
i0.ɵɵadvance(4);
|
|
2585
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(45, 56, "localization.key.translations.section"));
|
|
2586
|
+
i0.ɵɵadvance(2);
|
|
2587
|
+
i0.ɵɵconditional(ctx.isLoadingLanguages() ? 46 : ctx.languages().length === 0 ? 47 : 48);
|
|
2588
|
+
i0.ɵɵadvance(4);
|
|
2589
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(51, 58, "shared.cancel"))("outlined", true);
|
|
2590
|
+
i0.ɵɵadvance(2);
|
|
2591
|
+
i0.ɵɵproperty("label", ctx.isEditMode() ? i0.ɵɵpipeBind1(53, 60, "shared.update") : i0.ɵɵpipeBind1(54, 62, "shared.create"))("loading", ctx.isSaving())("disabled", !ctx.isFormValid() || ctx.isSaving());
|
|
2592
|
+
} }, dependencies: [AngularModule, i1$1.ɵNgNoValidate, i1$1.DefaultValueAccessor, i1$1.NgControlStatus, i1$1.NgControlStatusGroup, i1$1.NgModel, i1$1.NgForm, PrimeModule, i2.Button, i3.Card, i4$1.InputText, i5.Select, i4.Tag, i7.Textarea, i10.Toast, i9.ProgressSpinner, FormsModule, FormField, TranslatePipe], encapsulation: 2 });
|
|
2593
|
+
}
|
|
2594
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationKeyFormPage, [{
|
|
2595
|
+
type: Component,
|
|
2596
|
+
args: [{
|
|
2597
|
+
selector: 'lib-translation-key-form-page',
|
|
2598
|
+
imports: [AngularModule, PrimeModule, FormsModule, FormField, TranslatePipe],
|
|
2599
|
+
providers: [MessageService],
|
|
2600
|
+
template: `
|
|
2601
|
+
<p-card>
|
|
2602
|
+
<ng-template #header>
|
|
2603
|
+
<div class="flex justify-between items-center p-4">
|
|
2604
|
+
<h2 class="text-xl font-semibold m-0">
|
|
2605
|
+
{{ isEditMode() ? ('localization.key.edit' | translate) : ('localization.key.create' | translate) }}
|
|
2606
|
+
</h2>
|
|
2607
|
+
</div>
|
|
2608
|
+
</ng-template>
|
|
2609
|
+
|
|
2610
|
+
<form (ngSubmit)="onSubmit()" class="flex flex-col gap-6">
|
|
2611
|
+
<!-- Key Info Section -->
|
|
2612
|
+
<div class="p-4 surface-ground rounded-lg">
|
|
2613
|
+
<h4 class="font-semibold mt-0 mb-4">{{ 'localization.key.about' | translate }}</h4>
|
|
2614
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
2615
|
+
<!-- Key Name -->
|
|
2616
|
+
<div class="flex flex-col gap-2">
|
|
2617
|
+
<label for="key" class="font-medium">{{ 'localization.key.name' | translate }} *</label>
|
|
2618
|
+
<input
|
|
2619
|
+
pInputText
|
|
2620
|
+
id="key"
|
|
2621
|
+
[formField]="formTree.key"
|
|
2622
|
+
[placeholder]="'localization.placeholder.key.name' | translate" />
|
|
2623
|
+
</div>
|
|
2624
|
+
|
|
2625
|
+
<!-- Module -->
|
|
2626
|
+
<div class="flex flex-col gap-2">
|
|
2627
|
+
<label for="module" class="font-medium">{{ 'localization.key.module' | translate }} *</label>
|
|
2628
|
+
<p-select
|
|
2629
|
+
id="module"
|
|
2630
|
+
[ngModel]="formModel().module"
|
|
2631
|
+
(ngModelChange)="updateModule($event)"
|
|
2632
|
+
[ngModelOptions]="{standalone: true}"
|
|
2633
|
+
[options]="moduleOptions()"
|
|
2634
|
+
optionLabel="label"
|
|
2635
|
+
optionValue="value"
|
|
2636
|
+
[editable]="true"
|
|
2637
|
+
[placeholder]="'localization.key.select.module' | translate"
|
|
2638
|
+
class="w-full" />
|
|
2639
|
+
</div>
|
|
2640
|
+
|
|
2641
|
+
<!-- Default Message -->
|
|
2642
|
+
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2643
|
+
<label for="defaultMessage" class="font-medium">{{ 'localization.key.default.message' | translate }} *</label>
|
|
2644
|
+
<textarea
|
|
2645
|
+
pInputTextarea
|
|
2646
|
+
id="defaultMessage"
|
|
2647
|
+
[formField]="formTree.defaultMessage"
|
|
2648
|
+
[rows]="2"
|
|
2649
|
+
[placeholder]="'localization.placeholder.default.message' | translate"></textarea>
|
|
2650
|
+
</div>
|
|
2651
|
+
|
|
2652
|
+
<!-- Description -->
|
|
2653
|
+
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2654
|
+
<label for="description" class="font-medium">{{ 'localization.key.description' | translate }}</label>
|
|
2655
|
+
<input
|
|
2656
|
+
pInputText
|
|
2657
|
+
id="description"
|
|
2658
|
+
[formField]="formTree.description"
|
|
2659
|
+
[placeholder]="'localization.placeholder.key.description' | translate" />
|
|
2660
|
+
</div>
|
|
2661
|
+
|
|
2662
|
+
<!-- Variables -->
|
|
2663
|
+
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2664
|
+
<label for="variables" class="font-medium">{{ 'localization.key.variables' | translate }}</label>
|
|
2665
|
+
<input
|
|
2666
|
+
pInputText
|
|
2667
|
+
id="variables"
|
|
2668
|
+
[formField]="formTree.variables"
|
|
2669
|
+
[placeholder]="'localization.key.variables.placeholder' | translate" />
|
|
2670
|
+
<small class="text-muted-color">{{ 'localization.key.variables.hint' | translate }}</small>
|
|
2671
|
+
</div>
|
|
2672
|
+
</div>
|
|
2673
|
+
</div>
|
|
2674
|
+
|
|
2675
|
+
<!-- Translations Section -->
|
|
2676
|
+
<div class="p-4 surface-ground rounded-lg">
|
|
2677
|
+
<h4 class="font-semibold mt-0 mb-4">{{ 'localization.key.translations.section' | translate }}</h4>
|
|
2678
|
+
@if (isLoadingLanguages()) {
|
|
2679
|
+
<div class="flex justify-center py-4">
|
|
2680
|
+
<p-progressSpinner strokeWidth="4" />
|
|
2681
|
+
</div>
|
|
2682
|
+
} @else if (languages().length === 0) {
|
|
2683
|
+
<p class="text-muted-color text-center py-4">
|
|
2684
|
+
{{ 'localization.key.no.languages' | translate }}
|
|
2685
|
+
</p>
|
|
2686
|
+
} @else {
|
|
2687
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
2688
|
+
@for (lang of languages(); track lang.id) {
|
|
2689
|
+
<div class="flex flex-col gap-2">
|
|
2690
|
+
<div class="flex justify-between items-center">
|
|
2691
|
+
<label class="font-medium">
|
|
2692
|
+
{{ lang.name }}
|
|
2693
|
+
@if (lang.nativeName && lang.nativeName !== lang.name) {
|
|
2694
|
+
<span class="text-muted-color">({{ lang.nativeName }})</span>
|
|
2695
|
+
}
|
|
2696
|
+
</label>
|
|
2697
|
+
<p-tag [value]="lang.code" severity="secondary" class="uppercase" />
|
|
2698
|
+
</div>
|
|
2699
|
+
<textarea
|
|
2700
|
+
pInputTextarea
|
|
2701
|
+
[ngModel]="getTranslationValue(lang.id)"
|
|
2702
|
+
(ngModelChange)="setTranslationValue(lang.id, $event)"
|
|
2703
|
+
[ngModelOptions]="{standalone: true}"
|
|
2704
|
+
[rows]="2"
|
|
2705
|
+
[placeholder]="formModel().defaultMessage || ('localization.key.enter.translation' | translate)"></textarea>
|
|
2706
|
+
</div>
|
|
2707
|
+
}
|
|
2708
|
+
</div>
|
|
2709
|
+
}
|
|
2710
|
+
</div>
|
|
2711
|
+
|
|
2712
|
+
<!-- Actions -->
|
|
2713
|
+
<div class="flex justify-end gap-4 pt-4">
|
|
2714
|
+
<p-button
|
|
2715
|
+
[label]="'shared.cancel' | translate"
|
|
2716
|
+
severity="secondary"
|
|
2717
|
+
[outlined]="true"
|
|
2718
|
+
(onClick)="onCancel()" />
|
|
2719
|
+
<p-button
|
|
2720
|
+
[label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
|
|
2721
|
+
type="submit"
|
|
2722
|
+
[loading]="isSaving()"
|
|
2723
|
+
[disabled]="!isFormValid() || isSaving()" />
|
|
2724
|
+
</div>
|
|
2725
|
+
</form>
|
|
2726
|
+
</p-card>
|
|
2727
|
+
|
|
2728
|
+
<p-toast />
|
|
2729
|
+
`,
|
|
2730
|
+
}]
|
|
2731
|
+
}], () => [], null); })();
|
|
2732
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TranslationKeyFormPage, { className: "TranslationKeyFormPage", filePath: "pages/translation-key-form/translation-key-form.page.ts", lineNumber: 173 }); })();
|
|
2733
|
+
|
|
2734
|
+
var translationKeyForm_page = /*#__PURE__*/Object.freeze({
|
|
2735
|
+
__proto__: null,
|
|
2736
|
+
TranslationKeyFormPage: TranslationKeyFormPage
|
|
2737
|
+
});
|
|
2738
|
+
|
|
2739
|
+
const _c0 = () => ({ standalone: true });
|
|
2740
|
+
const _c1 = () => [10, 20, 50, 100];
|
|
2741
|
+
const _c2 = a0 => ({ count: a0 });
|
|
2742
|
+
function TranslationListPage_Conditional_29_Template(rf, ctx) { if (rf & 1) {
|
|
2743
|
+
i0.ɵɵelementStart(0, "div", 15);
|
|
2744
|
+
i0.ɵɵelement(1, "p-progressSpinner", 21);
|
|
2745
|
+
i0.ɵɵelementEnd();
|
|
2746
|
+
} }
|
|
2747
|
+
function TranslationListPage_Conditional_30_Template(rf, ctx) { if (rf & 1) {
|
|
2748
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "p");
|
|
2749
|
+
i0.ɵɵtext(2);
|
|
2750
|
+
i0.ɵɵpipe(3, "translate");
|
|
2751
|
+
i0.ɵɵelementEnd()();
|
|
2752
|
+
} if (rf & 2) {
|
|
2753
|
+
i0.ɵɵadvance(2);
|
|
2754
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 1, "localization.translation.select.language.hint"));
|
|
2755
|
+
} }
|
|
2756
|
+
function TranslationListPage_Conditional_31_Template(rf, ctx) { if (rf & 1) {
|
|
2757
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "p");
|
|
2758
|
+
i0.ɵɵtext(2);
|
|
2759
|
+
i0.ɵɵpipe(3, "translate");
|
|
2760
|
+
i0.ɵɵelementEnd()();
|
|
2761
|
+
} if (rf & 2) {
|
|
2762
|
+
i0.ɵɵadvance(2);
|
|
2763
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 1, "localization.translation.no.keys"));
|
|
2764
|
+
} }
|
|
2765
|
+
function TranslationListPage_Conditional_32_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
2766
|
+
i0.ɵɵelementStart(0, "tr")(1, "th", 22);
|
|
2767
|
+
i0.ɵɵtext(2);
|
|
2768
|
+
i0.ɵɵpipe(3, "translate");
|
|
2769
|
+
i0.ɵɵelementEnd();
|
|
2770
|
+
i0.ɵɵelementStart(4, "th", 23);
|
|
2771
|
+
i0.ɵɵtext(5);
|
|
2772
|
+
i0.ɵɵpipe(6, "translate");
|
|
2773
|
+
i0.ɵɵelementEnd();
|
|
2774
|
+
i0.ɵɵelementStart(7, "th", 24);
|
|
2775
|
+
i0.ɵɵtext(8);
|
|
2776
|
+
i0.ɵɵpipe(9, "translate");
|
|
2777
|
+
i0.ɵɵelementEnd();
|
|
2778
|
+
i0.ɵɵelementStart(10, "th", 25);
|
|
2779
|
+
i0.ɵɵtext(11);
|
|
2780
|
+
i0.ɵɵpipe(12, "translate");
|
|
2781
|
+
i0.ɵɵelementEnd()();
|
|
2782
|
+
} if (rf & 2) {
|
|
2783
|
+
i0.ɵɵadvance(2);
|
|
2784
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 4, "localization.translation.key"));
|
|
2785
|
+
i0.ɵɵadvance(3);
|
|
2786
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(6, 6, "localization.translation.default.message"));
|
|
2787
|
+
i0.ɵɵadvance(3);
|
|
2788
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(9, 8, "localization.translation.value"));
|
|
2789
|
+
i0.ɵɵadvance(3);
|
|
2790
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 10, "localization.translation.verified"));
|
|
2791
|
+
} }
|
|
2792
|
+
function TranslationListPage_Conditional_32_ng_template_3_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
2793
|
+
i0.ɵɵelementStart(0, "small", 19);
|
|
2794
|
+
i0.ɵɵtext(1);
|
|
2795
|
+
i0.ɵɵelementEnd();
|
|
2796
|
+
} if (rf & 2) {
|
|
2797
|
+
const row_r2 = i0.ɵɵnextContext().$implicit;
|
|
2798
|
+
i0.ɵɵadvance();
|
|
2799
|
+
i0.ɵɵtextInterpolate(row_r2.translationKey.description);
|
|
2800
|
+
} }
|
|
2801
|
+
function TranslationListPage_Conditional_32_ng_template_3_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
2802
|
+
i0.ɵɵelementStart(0, "span", 32);
|
|
2803
|
+
i0.ɵɵtext(1);
|
|
2804
|
+
i0.ɵɵelementEnd();
|
|
2805
|
+
} if (rf & 2) {
|
|
2806
|
+
const v_r3 = ctx.$implicit;
|
|
2807
|
+
const ctx_r3 = i0.ɵɵnextContext(4);
|
|
2808
|
+
i0.ɵɵadvance();
|
|
2809
|
+
i0.ɵɵtextInterpolate(ctx_r3.formatVariable(v_r3));
|
|
2810
|
+
} }
|
|
2811
|
+
function TranslationListPage_Conditional_32_ng_template_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
2812
|
+
i0.ɵɵelementStart(0, "div", 27);
|
|
2813
|
+
i0.ɵɵrepeaterCreate(1, TranslationListPage_Conditional_32_ng_template_3_Conditional_5_For_2_Template, 2, 1, "span", 32, i0.ɵɵrepeaterTrackByIdentity);
|
|
2814
|
+
i0.ɵɵelementEnd();
|
|
2815
|
+
} if (rf & 2) {
|
|
2816
|
+
const row_r2 = i0.ɵɵnextContext().$implicit;
|
|
2817
|
+
i0.ɵɵadvance();
|
|
2818
|
+
i0.ɵɵrepeater(row_r2.translationKey.variables);
|
|
2819
|
+
} }
|
|
2820
|
+
function TranslationListPage_Conditional_32_ng_template_3_Template(rf, ctx) { if (rf & 1) {
|
|
2821
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
2822
|
+
i0.ɵɵelementStart(0, "tr")(1, "td")(2, "div", 26);
|
|
2823
|
+
i0.ɵɵtext(3);
|
|
2824
|
+
i0.ɵɵelementEnd();
|
|
2825
|
+
i0.ɵɵconditionalCreate(4, TranslationListPage_Conditional_32_ng_template_3_Conditional_4_Template, 2, 1, "small", 19);
|
|
2826
|
+
i0.ɵɵconditionalCreate(5, TranslationListPage_Conditional_32_ng_template_3_Conditional_5_Template, 3, 0, "div", 27);
|
|
2827
|
+
i0.ɵɵelementEnd();
|
|
2828
|
+
i0.ɵɵelementStart(6, "td")(7, "span", 28);
|
|
2829
|
+
i0.ɵɵtext(8);
|
|
2830
|
+
i0.ɵɵelementEnd()();
|
|
2831
|
+
i0.ɵɵelementStart(9, "td")(10, "textarea", 29);
|
|
2832
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TranslationListPage_Conditional_32_ng_template_3_Template_textarea_ngModelChange_10_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; i0.ɵɵtwoWayBindingSet(row_r2.editValue, $event) || (row_r2.editValue = $event); return i0.ɵɵresetView($event); });
|
|
2833
|
+
i0.ɵɵlistener("input", function TranslationListPage_Conditional_32_ng_template_3_Template_textarea_input_10_listener() { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onValueChange(row_r2)); });
|
|
2834
|
+
i0.ɵɵelementEnd()();
|
|
2835
|
+
i0.ɵɵelementStart(11, "td", 30)(12, "p-checkbox", 31);
|
|
2836
|
+
i0.ɵɵtwoWayListener("ngModelChange", function TranslationListPage_Conditional_32_ng_template_3_Template_p_checkbox_ngModelChange_12_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; i0.ɵɵtwoWayBindingSet(row_r2.isVerified, $event) || (row_r2.isVerified = $event); return i0.ɵɵresetView($event); });
|
|
2837
|
+
i0.ɵɵlistener("onChange", function TranslationListPage_Conditional_32_ng_template_3_Template_p_checkbox_onChange_12_listener() { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onVerifiedChange(row_r2)); });
|
|
2838
|
+
i0.ɵɵelementEnd()()();
|
|
2839
|
+
} if (rf & 2) {
|
|
2840
|
+
const row_r2 = ctx.$implicit;
|
|
2841
|
+
i0.ɵɵclassProp("bg-yellow-50", row_r2.isDirty);
|
|
2842
|
+
i0.ɵɵadvance(3);
|
|
2843
|
+
i0.ɵɵtextInterpolate(row_r2.translationKey.key);
|
|
2844
|
+
i0.ɵɵadvance();
|
|
2845
|
+
i0.ɵɵconditional(row_r2.translationKey.description ? 4 : -1);
|
|
2846
|
+
i0.ɵɵadvance();
|
|
2847
|
+
i0.ɵɵconditional((row_r2.translationKey.variables == null ? null : row_r2.translationKey.variables.length) ? 5 : -1);
|
|
2848
|
+
i0.ɵɵadvance(3);
|
|
2849
|
+
i0.ɵɵtextInterpolate(row_r2.translationKey.defaultMessage);
|
|
2850
|
+
i0.ɵɵadvance(2);
|
|
2851
|
+
i0.ɵɵtwoWayProperty("ngModel", row_r2.editValue);
|
|
2852
|
+
i0.ɵɵproperty("ngModelOptions", i0.ɵɵpureFunction0(13, _c0))("rows", 2)("placeholder", row_r2.translationKey.defaultMessage);
|
|
2853
|
+
i0.ɵɵadvance(2);
|
|
2854
|
+
i0.ɵɵtwoWayProperty("ngModel", row_r2.isVerified);
|
|
2855
|
+
i0.ɵɵproperty("ngModelOptions", i0.ɵɵpureFunction0(14, _c0))("binary", true);
|
|
2856
|
+
} }
|
|
2857
|
+
function TranslationListPage_Conditional_32_ng_template_5_Template(rf, ctx) { if (rf & 1) {
|
|
2858
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 33);
|
|
2859
|
+
i0.ɵɵtext(2);
|
|
2860
|
+
i0.ɵɵpipe(3, "translate");
|
|
2861
|
+
i0.ɵɵelementEnd()();
|
|
2862
|
+
} if (rf & 2) {
|
|
2863
|
+
i0.ɵɵadvance(2);
|
|
2864
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(3, 1, "shared.no.results"), " ");
|
|
2865
|
+
} }
|
|
2866
|
+
function TranslationListPage_Conditional_32_Template(rf, ctx) { if (rf & 1) {
|
|
2867
|
+
i0.ɵɵelementStart(0, "p-table", 17);
|
|
2868
|
+
i0.ɵɵtemplate(1, TranslationListPage_Conditional_32_ng_template_1_Template, 13, 12, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(3, TranslationListPage_Conditional_32_ng_template_3_Template, 13, 15, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor)(5, TranslationListPage_Conditional_32_ng_template_5_Template, 4, 3, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
|
|
2869
|
+
i0.ɵɵelementEnd();
|
|
2870
|
+
} if (rf & 2) {
|
|
2871
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
2872
|
+
i0.ɵɵproperty("value", ctx_r3.filteredRows())("paginator", true)("rows", 20)("rowsPerPageOptions", i0.ɵɵpureFunction0(6, _c1))("showCurrentPageReport", true)("currentPageReportTemplate", ctx_r3.paginationTemplate());
|
|
2873
|
+
} }
|
|
2874
|
+
function TranslationListPage_Conditional_35_Template(rf, ctx) { if (rf & 1) {
|
|
2875
|
+
i0.ɵɵelementStart(0, "span", 20);
|
|
2876
|
+
i0.ɵɵelement(1, "i", 34);
|
|
2877
|
+
i0.ɵɵtext(2);
|
|
2878
|
+
i0.ɵɵpipe(3, "translate");
|
|
2879
|
+
i0.ɵɵelementEnd();
|
|
2880
|
+
} if (rf & 2) {
|
|
2881
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
2882
|
+
i0.ɵɵadvance(2);
|
|
2883
|
+
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(3, 1, "localization.translation.unsaved.changes", i0.ɵɵpureFunction1(4, _c2, ctx_r3.changedCount())), " ");
|
|
2884
|
+
} }
|
|
2885
|
+
class TranslationListPage {
|
|
2886
|
+
languageService = inject(LanguageApiService);
|
|
2887
|
+
translationKeyService = inject(TranslationKeyApiService);
|
|
2888
|
+
translationService = inject(TranslationApiService);
|
|
2889
|
+
messageService = inject(MessageService);
|
|
2890
|
+
translateService = inject(TranslateService);
|
|
2891
|
+
destroyRef = inject(DestroyRef);
|
|
2892
|
+
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
2893
|
+
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
2894
|
+
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
2895
|
+
modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
|
|
2896
|
+
translationRows = signal([], ...(ngDevMode ? [{ debugName: "translationRows" }] : []));
|
|
2897
|
+
selectedModule = signal(null, ...(ngDevMode ? [{ debugName: "selectedModule" }] : []));
|
|
2898
|
+
selectedLanguageId = signal(null, ...(ngDevMode ? [{ debugName: "selectedLanguageId" }] : []));
|
|
2899
|
+
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
2900
|
+
moduleOptions = computed(() => [
|
|
2901
|
+
{ label: this.translateService.instant('localization.translation.all.modules'), value: null },
|
|
2902
|
+
...this.modules().map((m) => ({ label: m, value: m })),
|
|
2903
|
+
], ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
2904
|
+
paginationTemplate = computed(() => this.translateService.instant('localization.translation.pagination'), ...(ngDevMode ? [{ debugName: "paginationTemplate" }] : []));
|
|
2905
|
+
languageOptions = computed(() => this.languages().map((l) => ({
|
|
2906
|
+
label: `${l.name} (${l.code})`,
|
|
2907
|
+
value: l.id,
|
|
2908
|
+
})), ...(ngDevMode ? [{ debugName: "languageOptions" }] : []));
|
|
2909
|
+
filteredRows = computed(() => {
|
|
2910
|
+
const rows = this.translationRows();
|
|
2911
|
+
const search = this.searchTerm().toLowerCase().trim();
|
|
2912
|
+
if (!search)
|
|
2913
|
+
return rows;
|
|
2914
|
+
return rows.filter((r) => r.translationKey.key.toLowerCase().includes(search) ||
|
|
2915
|
+
r.translationKey.defaultMessage.toLowerCase().includes(search) ||
|
|
2916
|
+
r.editValue.toLowerCase().includes(search));
|
|
2917
|
+
}, ...(ngDevMode ? [{ debugName: "filteredRows" }] : []));
|
|
2918
|
+
hasChanges = computed(() => this.translationRows().some((r) => r.isDirty), ...(ngDevMode ? [{ debugName: "hasChanges" }] : []));
|
|
2919
|
+
changedCount = computed(() => this.translationRows().filter((r) => r.isDirty).length, ...(ngDevMode ? [{ debugName: "changedCount" }] : []));
|
|
2920
|
+
formatVariable(v) {
|
|
2921
|
+
return `{{${v}}}`;
|
|
2922
|
+
}
|
|
2923
|
+
ngOnInit() {
|
|
2924
|
+
this.loadInitialData();
|
|
2925
|
+
}
|
|
2926
|
+
loadInitialData() {
|
|
2927
|
+
this.isLoading.set(true);
|
|
2928
|
+
forkJoin({
|
|
2929
|
+
languages: this.languageService.getAll(),
|
|
2930
|
+
modules: this.translationKeyService.getModules(),
|
|
2931
|
+
})
|
|
2932
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2933
|
+
.subscribe({
|
|
2934
|
+
next: ({ languages, modules }) => {
|
|
2935
|
+
if (languages.success && languages.data) {
|
|
2936
|
+
this.languages.set(languages.data.filter((l) => l.isActive));
|
|
2937
|
+
const defaultLang = languages.data.find((l) => l.isDefault);
|
|
2938
|
+
if (defaultLang) {
|
|
2939
|
+
this.selectedLanguageId.set(defaultLang.id);
|
|
2940
|
+
}
|
|
2941
|
+
else if (languages.data.length > 0) {
|
|
2942
|
+
this.selectedLanguageId.set(languages.data[0].id);
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
if (modules.success && modules.data) {
|
|
2946
|
+
this.modules.set(modules.data);
|
|
2947
|
+
}
|
|
2948
|
+
this.isLoading.set(false);
|
|
2949
|
+
},
|
|
2950
|
+
error: () => {
|
|
2951
|
+
this.isLoading.set(false);
|
|
2952
|
+
},
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
onModuleChange(value) {
|
|
2956
|
+
this.selectedModule.set(value);
|
|
2957
|
+
this.loadTranslations();
|
|
2958
|
+
}
|
|
2959
|
+
onLanguageChange(value) {
|
|
2960
|
+
this.selectedLanguageId.set(value);
|
|
2961
|
+
this.loadTranslations();
|
|
2962
|
+
}
|
|
2963
|
+
loadTranslations() {
|
|
2964
|
+
const languageId = this.selectedLanguageId();
|
|
2965
|
+
if (!languageId) {
|
|
2966
|
+
this.translationRows.set([]);
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
this.isLoading.set(true);
|
|
2970
|
+
const module = this.selectedModule();
|
|
2971
|
+
const keysRequest = module
|
|
2972
|
+
? this.translationKeyService.getByModule(module)
|
|
2973
|
+
: this.translationKeyService.getAll();
|
|
2974
|
+
const translationsRequest = module
|
|
2975
|
+
? this.translationService.getByModuleAndLanguageId(module, languageId)
|
|
2976
|
+
: this.translationService.getByLanguageId(languageId);
|
|
2977
|
+
forkJoin({
|
|
2978
|
+
keys: keysRequest,
|
|
2979
|
+
translations: translationsRequest,
|
|
2980
|
+
})
|
|
2981
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2982
|
+
.subscribe({
|
|
2983
|
+
next: ({ keys, translations }) => {
|
|
2984
|
+
const translationMap = new Map();
|
|
2985
|
+
if (translations.success && translations.data) {
|
|
2986
|
+
translations.data.forEach((t) => {
|
|
2987
|
+
translationMap.set(t.translationKeyId, t);
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2990
|
+
const rows = [];
|
|
2991
|
+
if (keys.success && keys.data) {
|
|
2992
|
+
keys.data.forEach((key) => {
|
|
2993
|
+
const translation = translationMap.get(key.id) ?? null;
|
|
2994
|
+
rows.push({
|
|
2995
|
+
translationKey: key,
|
|
2996
|
+
translation,
|
|
2997
|
+
editValue: translation?.value ?? '',
|
|
2998
|
+
isVerified: translation?.isVerified ?? false,
|
|
2999
|
+
isDirty: false,
|
|
3000
|
+
});
|
|
3001
|
+
});
|
|
3002
|
+
}
|
|
3003
|
+
this.translationRows.set(rows);
|
|
3004
|
+
this.isLoading.set(false);
|
|
3005
|
+
},
|
|
3006
|
+
error: () => {
|
|
3007
|
+
this.isLoading.set(false);
|
|
3008
|
+
},
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
onValueChange(row) {
|
|
3012
|
+
const originalValue = row.translation?.value ?? '';
|
|
3013
|
+
const originalVerified = row.translation?.isVerified ?? false;
|
|
3014
|
+
row.isDirty = row.editValue !== originalValue || row.isVerified !== originalVerified;
|
|
3015
|
+
this.translationRows.update((rows) => [...rows]);
|
|
3016
|
+
}
|
|
3017
|
+
onVerifiedChange(row) {
|
|
3018
|
+
this.onValueChange(row);
|
|
3019
|
+
}
|
|
3020
|
+
saveChanges() {
|
|
3021
|
+
const changedRows = this.translationRows().filter((r) => r.isDirty);
|
|
3022
|
+
const languageId = this.selectedLanguageId();
|
|
3023
|
+
if (changedRows.length === 0 || !languageId)
|
|
3024
|
+
return;
|
|
3025
|
+
this.isSaving.set(true);
|
|
3026
|
+
const items = changedRows.map((row) => ({
|
|
3027
|
+
id: row.translation?.id,
|
|
3028
|
+
languageId,
|
|
3029
|
+
translationKeyId: row.translationKey.id,
|
|
3030
|
+
value: row.editValue,
|
|
3031
|
+
isVerified: row.isVerified,
|
|
3032
|
+
}));
|
|
3033
|
+
this.translationService
|
|
3034
|
+
.bulkUpdate(items)
|
|
3035
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3036
|
+
.subscribe({
|
|
3037
|
+
next: (response) => {
|
|
3038
|
+
if (response.success) {
|
|
3039
|
+
this.messageService.add({
|
|
3040
|
+
severity: 'success',
|
|
3041
|
+
summary: this.translateService.instant('localization.translation.save.success'),
|
|
3042
|
+
detail: this.translateService.instant('localization.translation.save.success.detail'),
|
|
3043
|
+
});
|
|
3044
|
+
this.loadTranslations();
|
|
3045
|
+
}
|
|
3046
|
+
this.isSaving.set(false);
|
|
3047
|
+
},
|
|
3048
|
+
error: () => {
|
|
3049
|
+
this.isSaving.set(false);
|
|
3050
|
+
},
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
3053
|
+
static ɵfac = function TranslationListPage_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationListPage)(); };
|
|
3054
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TranslationListPage, selectors: [["lib-translation-list-page"]], features: [i0.ɵɵProvidersFeature([MessageService])], decls: 39, vars: 44, consts: [["header", ""], ["body", ""], ["emptymessage", ""], [1, "card"], [1, "flex", "flex-col", "sm:flex-row", "justify-between", "items-start", "sm:items-center", "gap-4", "mb-4"], [1, "text-xl", "font-semibold", "m-0"], [1, "flex", "gap-2"], ["icon", "pi pi-save", 3, "onClick", "label", "disabled", "loading"], [1, "flex", "flex-col", "md:flex-row", "gap-4", "mb-4"], [1, "flex-1"], [1, "block", "font-medium", "mb-2"], ["optionLabel", "label", "optionValue", "value", 1, "w-full", 3, "ngModelChange", "options", "ngModel", "ngModelOptions", "placeholder"], [1, "w-full"], [1, "pi", "pi-search"], ["pInputText", "", 1, "w-full", 3, "ngModelChange", "ngModel", "ngModelOptions", "placeholder"], [1, "flex", "justify-center", "py-8"], [1, "text-center", "py-8", "text-muted-color"], ["styleClass", "p-datatable-sm", 3, "value", "paginator", "rows", "rowsPerPageOptions", "showCurrentPageReport", "currentPageReportTemplate"], [1, "flex", "justify-between", "items-center", "mt-4"], [1, "text-muted-color"], [1, "text-orange-500"], ["strokeWidth", "4"], [2, "width", "30%"], [2, "width", "25%"], [2, "width", "35%"], [2, "width", "10%"], [1, "font-medium", "text-sm"], [1, "mt-1"], [1, "text-sm"], ["pInputTextarea", "", 1, "w-full", 3, "ngModelChange", "input", "ngModel", "ngModelOptions", "rows", "placeholder"], [1, "text-center"], [3, "ngModelChange", "onChange", "ngModel", "ngModelOptions", "binary"], [1, "text-xs", "bg-surface-100", "px-2", "py-1", "rounded", "mr-1"], ["colspan", "4", 1, "text-center", "py-4", "text-muted-color"], [1, "pi", "pi-exclamation-circle", "mr-1"]], template: function TranslationListPage_Template(rf, ctx) { if (rf & 1) {
|
|
3055
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "h2", 5);
|
|
3056
|
+
i0.ɵɵtext(3);
|
|
3057
|
+
i0.ɵɵpipe(4, "translate");
|
|
3058
|
+
i0.ɵɵelementEnd();
|
|
3059
|
+
i0.ɵɵelementStart(5, "div", 6)(6, "p-button", 7);
|
|
3060
|
+
i0.ɵɵpipe(7, "translate");
|
|
3061
|
+
i0.ɵɵlistener("onClick", function TranslationListPage_Template_p_button_onClick_6_listener() { return ctx.saveChanges(); });
|
|
3062
|
+
i0.ɵɵelementEnd()()();
|
|
3063
|
+
i0.ɵɵelementStart(8, "div", 8)(9, "div", 9)(10, "label", 10);
|
|
3064
|
+
i0.ɵɵtext(11);
|
|
3065
|
+
i0.ɵɵpipe(12, "translate");
|
|
3066
|
+
i0.ɵɵelementEnd();
|
|
3067
|
+
i0.ɵɵelementStart(13, "p-select", 11);
|
|
3068
|
+
i0.ɵɵpipe(14, "translate");
|
|
3069
|
+
i0.ɵɵlistener("ngModelChange", function TranslationListPage_Template_p_select_ngModelChange_13_listener($event) { return ctx.onModuleChange($event); });
|
|
3070
|
+
i0.ɵɵelementEnd()();
|
|
3071
|
+
i0.ɵɵelementStart(15, "div", 9)(16, "label", 10);
|
|
3072
|
+
i0.ɵɵtext(17);
|
|
3073
|
+
i0.ɵɵpipe(18, "translate");
|
|
3074
|
+
i0.ɵɵelementEnd();
|
|
3075
|
+
i0.ɵɵelementStart(19, "p-select", 11);
|
|
3076
|
+
i0.ɵɵpipe(20, "translate");
|
|
3077
|
+
i0.ɵɵlistener("ngModelChange", function TranslationListPage_Template_p_select_ngModelChange_19_listener($event) { return ctx.onLanguageChange($event); });
|
|
3078
|
+
i0.ɵɵelementEnd()();
|
|
3079
|
+
i0.ɵɵelementStart(21, "div", 9)(22, "label", 10);
|
|
3080
|
+
i0.ɵɵtext(23);
|
|
3081
|
+
i0.ɵɵpipe(24, "translate");
|
|
3082
|
+
i0.ɵɵelementEnd();
|
|
3083
|
+
i0.ɵɵelementStart(25, "p-iconfield", 12);
|
|
3084
|
+
i0.ɵɵelement(26, "p-inputicon", 13);
|
|
3085
|
+
i0.ɵɵelementStart(27, "input", 14);
|
|
3086
|
+
i0.ɵɵpipe(28, "translate");
|
|
3087
|
+
i0.ɵɵlistener("ngModelChange", function TranslationListPage_Template_input_ngModelChange_27_listener($event) { return ctx.searchTerm.set($event); });
|
|
3088
|
+
i0.ɵɵelementEnd()()()();
|
|
3089
|
+
i0.ɵɵconditionalCreate(29, TranslationListPage_Conditional_29_Template, 2, 0, "div", 15)(30, TranslationListPage_Conditional_30_Template, 4, 3, "div", 16)(31, TranslationListPage_Conditional_31_Template, 4, 3, "div", 16)(32, TranslationListPage_Conditional_32_Template, 7, 7, "p-table", 17);
|
|
3090
|
+
i0.ɵɵelementStart(33, "div", 18)(34, "div", 19);
|
|
3091
|
+
i0.ɵɵconditionalCreate(35, TranslationListPage_Conditional_35_Template, 4, 6, "span", 20);
|
|
3092
|
+
i0.ɵɵelementEnd();
|
|
3093
|
+
i0.ɵɵelementStart(36, "p-button", 7);
|
|
3094
|
+
i0.ɵɵpipe(37, "translate");
|
|
3095
|
+
i0.ɵɵlistener("onClick", function TranslationListPage_Template_p_button_onClick_36_listener() { return ctx.saveChanges(); });
|
|
3096
|
+
i0.ɵɵelementEnd()()();
|
|
3097
|
+
i0.ɵɵelement(38, "p-toast");
|
|
3098
|
+
} if (rf & 2) {
|
|
3099
|
+
i0.ɵɵadvance(3);
|
|
3100
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(4, 23, "localization.translation.title"));
|
|
3101
|
+
i0.ɵɵadvance(3);
|
|
3102
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(7, 25, "shared.save"))("disabled", !ctx.hasChanges())("loading", ctx.isSaving());
|
|
3103
|
+
i0.ɵɵadvance(5);
|
|
3104
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(12, 27, "localization.translation.module"));
|
|
3105
|
+
i0.ɵɵadvance(2);
|
|
3106
|
+
i0.ɵɵproperty("options", ctx.moduleOptions())("ngModel", ctx.selectedModule())("ngModelOptions", i0.ɵɵpureFunction0(41, _c0))("placeholder", i0.ɵɵpipeBind1(14, 29, "localization.translation.select.module"));
|
|
3107
|
+
i0.ɵɵadvance(4);
|
|
3108
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(18, 31, "localization.translation.language"));
|
|
3109
|
+
i0.ɵɵadvance(2);
|
|
3110
|
+
i0.ɵɵproperty("options", ctx.languageOptions())("ngModel", ctx.selectedLanguageId())("ngModelOptions", i0.ɵɵpureFunction0(42, _c0))("placeholder", i0.ɵɵpipeBind1(20, 33, "localization.translation.select.language"));
|
|
3111
|
+
i0.ɵɵadvance(4);
|
|
3112
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(24, 35, "shared.search"));
|
|
3113
|
+
i0.ɵɵadvance(4);
|
|
3114
|
+
i0.ɵɵproperty("ngModel", ctx.searchTerm())("ngModelOptions", i0.ɵɵpureFunction0(43, _c0))("placeholder", i0.ɵɵpipeBind1(28, 37, "localization.translation.search.keys"));
|
|
3115
|
+
i0.ɵɵadvance(2);
|
|
3116
|
+
i0.ɵɵconditional(ctx.isLoading() ? 29 : !ctx.selectedLanguageId() ? 30 : ctx.filteredRows().length === 0 ? 31 : 32);
|
|
3117
|
+
i0.ɵɵadvance(6);
|
|
3118
|
+
i0.ɵɵconditional(ctx.hasChanges() ? 35 : -1);
|
|
3119
|
+
i0.ɵɵadvance();
|
|
3120
|
+
i0.ɵɵproperty("label", i0.ɵɵpipeBind1(37, 39, "shared.save"))("disabled", !ctx.hasChanges())("loading", ctx.isSaving());
|
|
3121
|
+
} }, dependencies: [AngularModule, i1$1.DefaultValueAccessor, i1$1.NgControlStatus, i1$1.NgModel, PrimeModule, i2.Button, i3$1.Checkbox, i4$2.IconField, i5$1.InputIcon, i4$1.InputText, i5.Select, i8.Table, i7.Textarea, i10.Toast, i9.ProgressSpinner, FormsModule, TranslatePipe], encapsulation: 2 });
|
|
3122
|
+
}
|
|
3123
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationListPage, [{
|
|
3124
|
+
type: Component,
|
|
3125
|
+
args: [{
|
|
3126
|
+
selector: 'lib-translation-list-page',
|
|
3127
|
+
imports: [AngularModule, PrimeModule, FormsModule, TranslatePipe],
|
|
3128
|
+
providers: [MessageService],
|
|
3129
|
+
template: `
|
|
3130
|
+
<div class="card">
|
|
3131
|
+
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
|
|
3132
|
+
<h2 class="text-xl font-semibold m-0">{{ 'localization.translation.title' | translate }}</h2>
|
|
3133
|
+
<div class="flex gap-2">
|
|
3134
|
+
<p-button
|
|
3135
|
+
[label]="'shared.save' | translate"
|
|
3136
|
+
icon="pi pi-save"
|
|
3137
|
+
[disabled]="!hasChanges()"
|
|
3138
|
+
[loading]="isSaving()"
|
|
3139
|
+
(onClick)="saveChanges()"
|
|
3140
|
+
/>
|
|
3141
|
+
</div>
|
|
3142
|
+
</div>
|
|
3143
|
+
|
|
3144
|
+
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
3145
|
+
<div class="flex-1">
|
|
3146
|
+
<label class="block font-medium mb-2">{{ 'localization.translation.module' | translate }}</label>
|
|
3147
|
+
<p-select
|
|
3148
|
+
[options]="moduleOptions()"
|
|
3149
|
+
[ngModel]="selectedModule()"
|
|
3150
|
+
(ngModelChange)="onModuleChange($event)"
|
|
3151
|
+
[ngModelOptions]="{standalone: true}"
|
|
3152
|
+
optionLabel="label"
|
|
3153
|
+
optionValue="value"
|
|
3154
|
+
[placeholder]="'localization.translation.select.module' | translate"
|
|
3155
|
+
class="w-full"
|
|
3156
|
+
/>
|
|
3157
|
+
</div>
|
|
3158
|
+
<div class="flex-1">
|
|
3159
|
+
<label class="block font-medium mb-2">{{ 'localization.translation.language' | translate }}</label>
|
|
3160
|
+
<p-select
|
|
3161
|
+
[options]="languageOptions()"
|
|
3162
|
+
[ngModel]="selectedLanguageId()"
|
|
3163
|
+
(ngModelChange)="onLanguageChange($event)"
|
|
3164
|
+
[ngModelOptions]="{standalone: true}"
|
|
3165
|
+
optionLabel="label"
|
|
3166
|
+
optionValue="value"
|
|
3167
|
+
[placeholder]="'localization.translation.select.language' | translate"
|
|
3168
|
+
class="w-full"
|
|
3169
|
+
/>
|
|
3170
|
+
</div>
|
|
3171
|
+
<div class="flex-1">
|
|
3172
|
+
<label class="block font-medium mb-2">{{ 'shared.search' | translate }}</label>
|
|
3173
|
+
<p-iconfield class="w-full">
|
|
3174
|
+
<p-inputicon class="pi pi-search" />
|
|
3175
|
+
<input
|
|
3176
|
+
pInputText
|
|
3177
|
+
[ngModel]="searchTerm()"
|
|
3178
|
+
(ngModelChange)="searchTerm.set($event)"
|
|
3179
|
+
[ngModelOptions]="{standalone: true}"
|
|
3180
|
+
[placeholder]="'localization.translation.search.keys' | translate"
|
|
3181
|
+
class="w-full"
|
|
3182
|
+
/>
|
|
3183
|
+
</p-iconfield>
|
|
3184
|
+
</div>
|
|
3185
|
+
</div>
|
|
3186
|
+
|
|
3187
|
+
@if (isLoading()) {
|
|
3188
|
+
<div class="flex justify-center py-8">
|
|
3189
|
+
<p-progressSpinner strokeWidth="4" />
|
|
3190
|
+
</div>
|
|
3191
|
+
} @else if (!selectedLanguageId()) {
|
|
3192
|
+
<div class="text-center py-8 text-muted-color">
|
|
3193
|
+
<p>{{ 'localization.translation.select.language.hint' | translate }}</p>
|
|
3194
|
+
</div>
|
|
3195
|
+
} @else if (filteredRows().length === 0) {
|
|
3196
|
+
<div class="text-center py-8 text-muted-color">
|
|
3197
|
+
<p>{{ 'localization.translation.no.keys' | translate }}</p>
|
|
3198
|
+
</div>
|
|
3199
|
+
} @else {
|
|
3200
|
+
<p-table
|
|
3201
|
+
[value]="filteredRows()"
|
|
3202
|
+
[paginator]="true"
|
|
3203
|
+
[rows]="20"
|
|
3204
|
+
[rowsPerPageOptions]="[10, 20, 50, 100]"
|
|
3205
|
+
[showCurrentPageReport]="true"
|
|
3206
|
+
[currentPageReportTemplate]="paginationTemplate()"
|
|
3207
|
+
styleClass="p-datatable-sm"
|
|
3208
|
+
>
|
|
3209
|
+
<ng-template #header>
|
|
3210
|
+
<tr>
|
|
3211
|
+
<th style="width: 30%">{{ 'localization.translation.key' | translate }}</th>
|
|
3212
|
+
<th style="width: 25%">{{ 'localization.translation.default.message' | translate }}</th>
|
|
3213
|
+
<th style="width: 35%">{{ 'localization.translation.value' | translate }}</th>
|
|
3214
|
+
<th style="width: 10%">{{ 'localization.translation.verified' | translate }}</th>
|
|
3215
|
+
</tr>
|
|
3216
|
+
</ng-template>
|
|
3217
|
+
<ng-template #body let-row>
|
|
3218
|
+
<tr [class.bg-yellow-50]="row.isDirty">
|
|
3219
|
+
<td>
|
|
3220
|
+
<div class="font-medium text-sm">{{ row.translationKey.key }}</div>
|
|
3221
|
+
@if (row.translationKey.description) {
|
|
3222
|
+
<small class="text-muted-color">{{ row.translationKey.description }}</small>
|
|
3223
|
+
}
|
|
3224
|
+
@if (row.translationKey.variables?.length) {
|
|
3225
|
+
<div class="mt-1">
|
|
3226
|
+
@for (v of row.translationKey.variables; track v) {
|
|
3227
|
+
<span class="text-xs bg-surface-100 px-2 py-1 rounded mr-1">{{ formatVariable(v) }}</span>
|
|
3228
|
+
}
|
|
3229
|
+
</div>
|
|
3230
|
+
}
|
|
3231
|
+
</td>
|
|
3232
|
+
<td>
|
|
3233
|
+
<span class="text-sm">{{ row.translationKey.defaultMessage }}</span>
|
|
3234
|
+
</td>
|
|
3235
|
+
<td>
|
|
3236
|
+
<textarea
|
|
3237
|
+
pInputTextarea
|
|
3238
|
+
[(ngModel)]="row.editValue"
|
|
3239
|
+
[ngModelOptions]="{standalone: true}"
|
|
3240
|
+
[rows]="2"
|
|
3241
|
+
class="w-full"
|
|
3242
|
+
[placeholder]="row.translationKey.defaultMessage"
|
|
3243
|
+
(input)="onValueChange(row)"
|
|
3244
|
+
></textarea>
|
|
3245
|
+
</td>
|
|
3246
|
+
<td class="text-center">
|
|
3247
|
+
<p-checkbox
|
|
3248
|
+
[(ngModel)]="row.isVerified"
|
|
3249
|
+
[ngModelOptions]="{standalone: true}"
|
|
3250
|
+
[binary]="true"
|
|
3251
|
+
(onChange)="onVerifiedChange(row)"
|
|
3252
|
+
/>
|
|
3253
|
+
</td>
|
|
3254
|
+
</tr>
|
|
3255
|
+
</ng-template>
|
|
3256
|
+
<ng-template #emptymessage>
|
|
3257
|
+
<tr>
|
|
3258
|
+
<td colspan="4" class="text-center py-4 text-muted-color">
|
|
3259
|
+
{{ 'shared.no.results' | translate }}
|
|
3260
|
+
</td>
|
|
3261
|
+
</tr>
|
|
3262
|
+
</ng-template>
|
|
3263
|
+
</p-table>
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
<div class="flex justify-between items-center mt-4">
|
|
3267
|
+
<div class="text-muted-color">
|
|
3268
|
+
@if (hasChanges()) {
|
|
3269
|
+
<span class="text-orange-500">
|
|
3270
|
+
<i class="pi pi-exclamation-circle mr-1"></i>
|
|
3271
|
+
{{ 'localization.translation.unsaved.changes' | translate: { count: changedCount() } }}
|
|
3272
|
+
</span>
|
|
3273
|
+
}
|
|
3274
|
+
</div>
|
|
3275
|
+
<p-button
|
|
3276
|
+
[label]="'shared.save' | translate"
|
|
3277
|
+
icon="pi pi-save"
|
|
3278
|
+
[disabled]="!hasChanges()"
|
|
3279
|
+
[loading]="isSaving()"
|
|
3280
|
+
(onClick)="saveChanges()"
|
|
3281
|
+
/>
|
|
3282
|
+
</div>
|
|
3283
|
+
</div>
|
|
3284
|
+
|
|
3285
|
+
<p-toast />
|
|
3286
|
+
`,
|
|
3287
|
+
}]
|
|
3288
|
+
}], null, null); })();
|
|
3289
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TranslationListPage, { className: "TranslationListPage", filePath: "pages/translation-list/translation-list.page.ts", lineNumber: 193 }); })();
|
|
3290
|
+
|
|
3291
|
+
var translationList_page = /*#__PURE__*/Object.freeze({
|
|
3292
|
+
__proto__: null,
|
|
3293
|
+
TranslationListPage: TranslationListPage
|
|
3294
|
+
});
|
|
3295
|
+
|
|
3296
|
+
// Interfaces
|
|
3297
|
+
|
|
3298
|
+
/**
|
|
3299
|
+
* Generated bundle index. Do not edit.
|
|
3300
|
+
*/
|
|
3301
|
+
|
|
3302
|
+
export { LOCALIZATION_CONFIG, LOCALIZATION_MESSAGES, LOCALIZATION_ROUTES, LanguageApiService, LanguageFormPage, LanguageListPage, LanguageSelectorComponent, LocalizationApiService, LocalizationContainerPage, LocalizationInitializerService, LocalizationStateService, STORAGE_KEYS, TranslateService, TranslationApiService, TranslationKeyApiService, TranslationKeyFormPage, TranslationKeyListPage, TranslationListPage, TranslationLoaderService, getLocalizationConfig, provideLocalization };
|
|
3303
|
+
//# sourceMappingURL=flusys-ng-localization.mjs.map
|