@flusys/ng-localization 4.1.0 → 5.0.0

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.
@@ -5,31 +5,30 @@ import { PrimeNG } from 'primeng/config';
5
5
  import { HttpClient } from '@angular/common/http';
6
6
  import { APP_CONFIG, TRANSLATE_ADAPTER } from '@flusys/ng-core';
7
7
  import { firstValueFrom, from, fromEvent, finalize, forkJoin } from 'rxjs';
8
+ import { ApiResourceService, resolveTranslationModule, SHARED_MESSAGES, PermissionValidatorService, LANGUAGE_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TranslatePipe, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
8
9
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
9
10
  import * as i1 from 'primeng/styleclass';
10
11
  import { StyleClassModule } from 'primeng/styleclass';
11
12
  import { filter } from 'rxjs/operators';
12
13
  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
14
  import { RouterOutlet, RouterLink, RouterLinkActive, Router, ActivatedRoute } from '@angular/router';
15
15
  import { ConfirmationService, MessageService } from 'primeng/api';
16
16
  import * as i2 from 'primeng/button';
17
17
  import * as i2$1 from 'primeng/confirmdialog';
18
- import * as i8 from 'primeng/table';
18
+ import * as i3 from 'primeng/table';
19
19
  import * as i4 from 'primeng/tag';
20
- import * as i10 from 'primeng/toast';
20
+ import * as i5 from 'primeng/toast';
21
21
  import * as i6 from 'primeng/tooltip';
22
22
  import * as i1$1 from '@angular/forms';
23
23
  import { FormsModule } from '@angular/forms';
24
24
  import { form, required, maxLength, FormField } from '@angular/forms/signals';
25
- import * as i3 from 'primeng/card';
25
+ import * as i3$1 from 'primeng/card';
26
26
  import * as i4$1 from 'primeng/inputtext';
27
- import * as i5 from 'primeng/select';
27
+ import * as i5$1 from 'primeng/select';
28
28
  import * as i4$2 from 'primeng/iconfield';
29
- import * as i5$1 from 'primeng/inputicon';
29
+ import * as i5$2 from 'primeng/inputicon';
30
30
  import * as i7 from 'primeng/textarea';
31
31
  import * as i9 from 'primeng/progressspinner';
32
- import * as i3$1 from 'primeng/checkbox';
33
32
 
34
33
  const LOCALIZATION_CONFIG = new InjectionToken('LOCALIZATION_CONFIG');
35
34
  /** Get localization config with sensible defaults applied */
@@ -52,106 +51,17 @@ const STORAGE_KEYS = {
52
51
  };
53
52
 
54
53
  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
54
  // Language CRUD (API keys)
146
55
  'language.create.success': 'Language created successfully',
147
56
  'language.create.many.success': '{{count}} languages created successfully',
148
57
  'language.get.success': 'Language retrieved successfully',
58
+ 'language.get.by.ids.success': 'Languages retrieved successfully by Ids',
59
+ 'language.get.by.filter.success': 'Languages retrieved successfully by filter',
149
60
  'language.get.all.success': 'Languages retrieved successfully',
150
61
  'language.update.success': 'Language updated successfully',
151
62
  'language.update.many.success': '{{count}} languages updated successfully',
152
63
  'language.delete.success': 'Language deleted successfully',
153
64
  'language.restore.success': 'Language restored successfully',
154
- 'language.not.found': 'Language not found',
155
65
  'language.active.success': 'Active languages retrieved successfully',
156
66
  'language.set.default.success': 'Default language updated successfully',
157
67
  'language.get.default.success': 'Default language retrieved successfully',
@@ -159,55 +69,90 @@ const LOCALIZATION_MESSAGES = {
159
69
  'translation.key.create.success': 'Translation key created successfully',
160
70
  'translation.key.create.many.success': '{{count}} translation keys created successfully',
161
71
  'translation.key.get.success': 'Translation key retrieved successfully',
72
+ 'translation.key.get.by.ids.success': 'Translation keys retrieved successfully by Ids',
73
+ 'translation.key.get.by.filter.success': 'Translation keys retrieved successfully by filter',
162
74
  'translation.key.get.all.success': 'Translation keys retrieved successfully',
163
75
  'translation.key.update.success': 'Translation key updated successfully',
164
76
  'translation.key.update.many.success': '{{count}} translation keys updated successfully',
165
77
  'translation.key.delete.success': 'Translation key deleted successfully',
166
78
  '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',
79
+ 'translation.key.modules.success': 'Modules retrieved successfully',
170
80
  'translation.key.readonly.delete.forbidden': 'Cannot delete readonly translation keys: {{keys}}',
171
81
  'translation.key.readonly.update.forbidden': 'Cannot modify key or module of system translation keys',
172
82
  'translation.key.duplicate.key.in.module': 'Translation key "{{key}}" already exists in module "{{module}}"',
173
- 'translation.key.modules.success': 'Modules retrieved successfully',
174
83
  // Translation CRUD (API keys)
175
84
  'translation.create.success': 'Translation created successfully',
176
85
  'translation.create.many.success': '{{count}} translations created successfully',
177
86
  'translation.get.success': 'Translation retrieved successfully',
87
+ 'translation.get.by.ids.success': 'Translations retrieved successfully by Ids',
88
+ 'translation.get.by.filter.success': 'Translations retrieved successfully by filter',
178
89
  'translation.get.all.success': 'Translations retrieved successfully',
179
90
  'translation.update.success': 'Translation updated successfully',
180
91
  'translation.update.many.success': '{{count}} translations updated successfully',
181
92
  'translation.delete.success': 'Translation deleted successfully',
182
93
  'translation.restore.success': 'Translation restored successfully',
183
- 'translation.not.found': 'Translation not found',
184
94
  '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
95
+ // pages/localization-container/localization-container.page.ts
96
+ 'localization.title': 'Localization',
97
+ 'localization.subtitle': 'Manage languages and translations',
98
+ 'localization.tabs.languages': 'Languages',
99
+ 'localization.tabs.keys': 'Keys',
100
+ // pages/language-list/language-list.page.ts
101
+ 'localization.language.title': 'Languages',
102
+ 'localization.language.subtitle': 'Manage available languages for your application',
103
+ 'localization.language.new': 'Add Language',
104
+ 'localization.language.code': 'Language Code',
105
+ 'localization.language.name': 'Language Name',
106
+ 'localization.language.native.name': 'Native Name',
107
+ 'localization.language.direction': 'Text Direction',
108
+ 'localization.language.rtl': 'RTL',
109
+ 'localization.language.ltr': 'LTR',
110
+ 'localization.language.default': 'Default',
111
+ 'localization.language.set.default': 'Set as Default',
112
+ 'localization.language.empty': 'No languages configured. Add a language to get started.',
113
+ 'localization.language.confirm.set.default': 'Set "{{name}}" as the default language?',
114
+ 'localization.language.delete.title': 'Delete Language',
115
+ // pages/language-form/language-form.page.ts
116
+ 'localization.language.edit': 'Edit Language',
117
+ 'localization.placeholder.code': 'en',
118
+ 'localization.language.iso.code.hint': 'ISO 639-1 language code (e.g., en, ar, fr)',
119
+ 'localization.placeholder.name': 'English',
120
+ 'localization.placeholder.native.name': 'English',
121
+ 'localization.language.native.name.hint': 'Name in the native language (e.g., العربية for Arabic)',
122
+ 'localization.language.display.order': 'Display Order',
123
+ 'localization.language.direction.ltr': 'Left to Right (LTR)',
124
+ 'localization.language.direction.rtl': 'Right to Left (RTL)',
190
125
  'localization.validation.code.required': 'Language code is required',
191
126
  'localization.validation.code.max.length': 'Language code must be at most 10 characters',
192
127
  'localization.validation.name.required': 'Language name is required',
193
128
  'localization.validation.name.max.length': 'Language name must be at most 100 characters',
129
+ // pages/translation-key-list/translation-key-list.page.ts
130
+ 'localization.key.title': 'Translation Keys',
131
+ 'localization.key.subtitle': 'Manage translation keys for your application',
132
+ 'localization.key.new': 'Add Key',
133
+ 'localization.key.filter.module': 'Filter by module',
134
+ 'localization.key.module': 'Module',
135
+ 'localization.key.name': 'Key Name',
136
+ 'localization.key.default.message': 'Default Message',
137
+ 'localization.key.translations': 'Translations',
138
+ 'localization.key.empty': 'No translation keys found',
139
+ 'localization.key.delete.title': 'Delete Translation Key',
140
+ // pages/translation-key-form/translation-key-form.page.ts
141
+ 'localization.key.edit': 'Edit Key',
142
+ 'localization.key.about': 'Key Information',
143
+ 'localization.placeholder.key.name': 'button.submit',
144
+ 'localization.key.select.module': 'Select or enter module',
145
+ 'localization.placeholder.default.message': 'Enter default value (English)',
146
+ 'localization.key.description': 'Description',
147
+ 'localization.placeholder.key.description': 'Optional description for translators',
148
+ 'localization.key.variables': 'Variables',
149
+ 'localization.key.variables.placeholder': 'e.g., name, count, date',
150
+ 'localization.key.variables.hint': 'Enter variable names used in this translation',
151
+ 'localization.key.translations.section': 'Translations',
152
+ 'localization.key.no.languages': 'No active languages configured',
153
+ 'localization.key.enter.translation': 'Enter translation',
194
154
  'localization.validation.key.required': 'Translation key is required',
195
- 'localization.validation.module.required': 'Module is required',
196
155
  '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
156
  };
212
157
 
213
158
  class LocalizationStateService {
@@ -255,8 +200,16 @@ class LocalizationStateService {
255
200
  dotToCamel(str) {
256
201
  return str.replace(/\.([a-z])/g, (_, c) => c.toUpperCase());
257
202
  }
203
+ PRIMENG_NUMERIC_KEYS = new Set(['firstDayOfWeek']);
204
+ PRIMENG_ARRAY_DEFAULTS = {
205
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
206
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
207
+ dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
208
+ monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
209
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
210
+ };
258
211
  syncPrimeNGTranslations(translations, fallbacks) {
259
- const primeNGTranslations = {};
212
+ const primeNGTranslations = { ...this.PRIMENG_ARRAY_DEFAULTS };
260
213
  const ariaTranslations = {};
261
214
  const prefix = 'primeng.';
262
215
  const ariaPrefix = 'primeng.aria.';
@@ -268,15 +221,13 @@ class LocalizationStateService {
268
221
  }
269
222
  else if (key.startsWith(prefix)) {
270
223
  const primeKey = this.dotToCamel(key.substring(prefix.length));
271
- primeNGTranslations[primeKey] = value;
224
+ primeNGTranslations[primeKey] = this.PRIMENG_NUMERIC_KEYS.has(primeKey) ? parseInt(value, 10) : value;
272
225
  }
273
226
  }
274
227
  if (Object.keys(ariaTranslations).length > 0) {
275
228
  primeNGTranslations['aria'] = ariaTranslations;
276
229
  }
277
- if (Object.keys(primeNGTranslations).length > 0) {
278
- this.primeNG.setTranslation(primeNGTranslations);
279
- }
230
+ this.primeNG.setTranslation(primeNGTranslations);
280
231
  }
281
232
  setCurrentLanguage(language) {
282
233
  this._currentLanguage.set(language);
@@ -320,13 +271,13 @@ class LocalizationStateService {
320
271
  hasModuleFallbacks(module) {
321
272
  return this._moduleFallbacks.has(module);
322
273
  }
323
- static ɵfac = function LocalizationStateService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationStateService)(); };
324
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationStateService, factory: LocalizationStateService.ɵfac, providedIn: 'root' });
274
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
275
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationStateService, providedIn: 'root' });
325
276
  }
326
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationStateService, [{
327
- type: Injectable,
328
- args: [{ providedIn: 'root' }]
329
- }], () => [], null); })();
277
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationStateService, decorators: [{
278
+ type: Injectable,
279
+ args: [{ providedIn: 'root' }]
280
+ }], ctorParameters: () => [] });
330
281
 
331
282
  class LocalizationApiService {
332
283
  http = inject(HttpClient);
@@ -340,13 +291,13 @@ class LocalizationApiService {
340
291
  getTranslationsByLanguage(languageCode, modules) {
341
292
  return this.http.post(`${this.baseUrl}/translation/get-by-language`, { languageCode, ...(modules?.length ? { modules } : {}) });
342
293
  }
343
- static ɵfac = function LocalizationApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationApiService)(); };
344
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationApiService, factory: LocalizationApiService.ɵfac, providedIn: 'root' });
294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
295
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationApiService, providedIn: 'root' });
345
296
  }
346
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationApiService, [{
347
- type: Injectable,
348
- args: [{ providedIn: 'root' }]
349
- }], null, null); })();
297
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationApiService, decorators: [{
298
+ type: Injectable,
299
+ args: [{ providedIn: 'root' }]
300
+ }] });
350
301
 
351
302
  class LocalizationInitializerService {
352
303
  config = inject(LOCALIZATION_CONFIG, { optional: true });
@@ -383,17 +334,19 @@ class LocalizationInitializerService {
383
334
  this.stateService.setInitialized(true);
384
335
  }
385
336
  }
386
- static ɵfac = function LocalizationInitializerService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LocalizationInitializerService)(); };
387
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LocalizationInitializerService, factory: LocalizationInitializerService.ɵfac, providedIn: 'root' });
337
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationInitializerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
338
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationInitializerService, providedIn: 'root' });
388
339
  }
389
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationInitializerService, [{
390
- type: Injectable,
391
- args: [{ providedIn: 'root' }]
392
- }], null, null); })();
340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationInitializerService, decorators: [{
341
+ type: Injectable,
342
+ args: [{ providedIn: 'root' }]
343
+ }] });
393
344
 
394
345
  class TranslateService {
395
346
  localizationState = inject(LocalizationStateService);
396
- localizationConfig = inject(LOCALIZATION_CONFIG, { optional: true });
347
+ localizationConfig = inject(LOCALIZATION_CONFIG, {
348
+ optional: true,
349
+ });
397
350
  languageCode = this.localizationState.currentLanguageCode;
398
351
  translate(key, params) {
399
352
  if (!this.localizationConfig) {
@@ -412,9 +365,6 @@ class TranslateService {
412
365
  return this.translate(key, params);
413
366
  });
414
367
  }
415
- instant(key, params) {
416
- return this.translate(key, params);
417
- }
418
368
  interpolate(template, params) {
419
369
  if (!params || !template)
420
370
  return template;
@@ -428,13 +378,13 @@ class TranslateService {
428
378
  const value = fallbacks[key] ?? key;
429
379
  return this.interpolate(value, params);
430
380
  }
431
- static ɵfac = function TranslateService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslateService)(); };
432
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslateService, factory: TranslateService.ɵfac, providedIn: 'root' });
381
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
382
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslateService, providedIn: 'root' });
433
383
  }
434
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslateService, [{
435
- type: Injectable,
436
- args: [{ providedIn: 'root' }]
437
- }], null, null); })();
384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslateService, decorators: [{
385
+ type: Injectable,
386
+ args: [{ providedIn: 'root' }]
387
+ }] });
438
388
 
439
389
  class TranslationLoaderService {
440
390
  DEFAULT_INITIAL_MODULES = ['shared', 'layout'];
@@ -499,99 +449,47 @@ class TranslationLoaderService {
499
449
  loadTranslationsAsync(languageCode, clearModules = false) {
500
450
  return from(this.loadTranslations(languageCode, clearModules));
501
451
  }
502
- static ɵfac = function TranslationLoaderService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationLoaderService)(); };
503
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslationLoaderService, factory: TranslationLoaderService.ɵfac, providedIn: 'root' });
452
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
453
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationLoaderService, providedIn: 'root' });
504
454
  }
505
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationLoaderService, [{
506
- type: Injectable,
507
- args: [{ providedIn: 'root' }]
508
- }], null, null); })();
455
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationLoaderService, decorators: [{
456
+ type: Injectable,
457
+ args: [{ providedIn: 'root' }]
458
+ }] });
509
459
 
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' });
460
+ class LanguageApiService extends ApiResourceService {
461
+ constructor() {
462
+ super('language', inject(HttpClient), 'localization');
534
463
  }
535
464
  setDefault(id) {
536
465
  return this.http.post(`${this.baseUrl}/set-default`, { id });
537
466
  }
538
- static ɵfac = function LanguageApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || LanguageApiService)(); };
539
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: LanguageApiService, factory: LanguageApiService.ɵfac, providedIn: 'root' });
467
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
468
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageApiService, providedIn: 'root' });
540
469
  }
541
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LanguageApiService, [{
542
- type: Injectable,
543
- args: [{ providedIn: 'root' }]
544
- }], null, null); })();
470
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageApiService, decorators: [{
471
+ type: Injectable,
472
+ args: [{ providedIn: 'root' }]
473
+ }], ctorParameters: () => [] });
545
474
 
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
- });
475
+ class TranslationKeyApiService extends ApiResourceService {
476
+ constructor() {
477
+ super('translation-key', inject(HttpClient), 'localization');
563
478
  }
564
479
  getModules() {
565
480
  return this.http.post(`${this.baseUrl}/get-modules`, {});
566
481
  }
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' });
482
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
483
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, providedIn: 'root' });
584
484
  }
585
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TranslationKeyApiService, [{
586
- type: Injectable,
587
- args: [{ providedIn: 'root' }]
588
- }], null, null); })();
485
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, decorators: [{
486
+ type: Injectable,
487
+ args: [{ providedIn: 'root' }]
488
+ }], ctorParameters: () => [] });
589
489
 
590
- class TranslationApiService {
591
- http = inject(HttpClient);
592
- appConfig = inject(APP_CONFIG);
593
- get baseUrl() {
594
- return `${this.appConfig.apiBaseUrl}/localization/translation`;
490
+ class TranslationApiService extends ApiResourceService {
491
+ constructor() {
492
+ super('translation', inject(HttpClient), 'localization');
595
493
  }
596
494
  getByLanguageId(languageId) {
597
495
  return this.http.post(`${this.baseUrl}/get-all`, {
@@ -607,21 +505,6 @@ class TranslationApiService {
607
505
  sort: {},
608
506
  });
609
507
  }
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
508
  getByKeyId(translationKeyId) {
626
509
  return this.http.post(`${this.baseUrl}/get-all`, {
627
510
  pagination: { currentPage: 0, pageSize: 1000 },
@@ -632,41 +515,17 @@ class TranslationApiService {
632
515
  getCounts() {
633
516
  return this.http.post(`${this.baseUrl}/get-counts`, {});
634
517
  }
635
- static ɵfac = function TranslationApiService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TranslationApiService)(); };
636
- static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TranslationApiService, factory: TranslationApiService.ɵfac, providedIn: 'root' });
518
+ bulkUpdate(translations) {
519
+ return this.http.post(`${this.baseUrl}/update-many-values`, { translations });
520
+ }
521
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
522
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, providedIn: 'root' });
637
523
  }
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
- } }
524
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, decorators: [{
525
+ type: Injectable,
526
+ args: [{ providedIn: 'root' }]
527
+ }], ctorParameters: () => [] });
528
+
670
529
  class LanguageSelectorComponent {
671
530
  localizationState = inject(LocalizationStateService);
672
531
  translationLoader = inject(TranslationLoaderService);
@@ -702,34 +561,51 @@ class LanguageSelectorComponent {
702
561
  .subscribe();
703
562
  }
704
563
  }
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 });
564
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
565
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LanguageSelectorComponent, isStandalone: true, selector: "lib-language-selector", host: { classAttribute: "relative" }, ngImport: i0, template: `
566
+ <button
567
+ type="button"
568
+ class="layout-topbar-action"
569
+ [class.layout-topbar-action-highlight]="isActive()"
570
+ pStyleClass="@next"
571
+ enterFromClass="hidden"
572
+ enterActiveClass="animate-scalein"
573
+ leaveToClass="hidden"
574
+ leaveActiveClass="animate-fadeout"
575
+ [hideOnOutsideClick]="true"
576
+ (click)="togglePanel()">
577
+ <i class="pi pi-globe"></i>
578
+ <span class="font-semibold">{{ selectedLanguage()?.nativeName || selectedLanguage()?.name || selectedLanguageCode() }}</span>
579
+ </button>
580
+ <div
581
+ 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]"
582
+ style="background-color: var(--surface-overlay); inset-inline-end: 0;">
583
+ <div class="flex flex-col">
584
+ @for (lang of languages(); track lang.id) {
585
+ <button
586
+ type="button"
587
+ 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"
588
+ [class.bg-primary-50]="lang.code === selectedLanguageCode()"
589
+ [class.text-primary]="lang.code === selectedLanguageCode()"
590
+ (click)="onLanguageSelect(lang.code)">
591
+ <span class="font-medium flex-1">{{ lang.nativeName || lang.name }}</span>
592
+ <span class="text-xs text-muted-color uppercase">({{ lang.code }})</span>
593
+ @if (lang.code === selectedLanguageCode()) {
594
+ <i class="pi pi-check text-primary text-sm"></i>
595
+ }
596
+ </button>
597
+ }
598
+ </div>
599
+ </div>
600
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }] });
725
601
  }
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: `
602
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageSelectorComponent, decorators: [{
603
+ type: Component,
604
+ args: [{
605
+ selector: 'lib-language-selector',
606
+ imports: [StyleClassModule],
607
+ host: { class: 'relative' },
608
+ template: `
733
609
  <button
734
610
  type="button"
735
611
  class="layout-topbar-action"
@@ -765,37 +641,9 @@ class LanguageSelectorComponent {
765
641
  </div>
766
642
  </div>
767
643
  `,
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
- } }
644
+ }]
645
+ }], ctorParameters: () => [] });
646
+
799
647
  class LanguageSelectorPanelComponent {
800
648
  localizationState = inject(LocalizationStateService);
801
649
  translationLoader = inject(TranslationLoaderService);
@@ -822,26 +670,36 @@ class LanguageSelectorPanelComponent {
822
670
  .subscribe();
823
671
  }
824
672
  }
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 });
673
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageSelectorPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
674
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LanguageSelectorPanelComponent, isStandalone: true, selector: "lib-language-selector-panel", host: { styleAttribute: "background-color: var(--surface-overlay); inset-inline-end: 0;", classAttribute: "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]" }, ngImport: i0, template: `
675
+ <div class="flex flex-col">
676
+ @for (lang of languages(); track lang.id) {
677
+ <button
678
+ type="button"
679
+ 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"
680
+ [class.bg-primary-50]="lang.code === selectedLanguageCode()"
681
+ [class.text-primary]="lang.code === selectedLanguageCode()"
682
+ (click)="onLanguageSelect(lang.code)">
683
+ <span class="font-medium flex-1">{{ lang.nativeName || lang.name }}</span>
684
+ <span class="text-xs text-muted-color uppercase">({{ lang.code }})</span>
685
+ @if (lang.code === selectedLanguageCode()) {
686
+ <i class="pi pi-check text-primary text-sm"></i>
687
+ }
688
+ </button>
689
+ }
690
+ </div>
691
+ `, isInline: true });
834
692
  }
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: `
693
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageSelectorPanelComponent, decorators: [{
694
+ type: Component,
695
+ args: [{
696
+ selector: 'lib-language-selector-panel',
697
+ imports: [],
698
+ host: {
699
+ 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]',
700
+ style: 'background-color: var(--surface-overlay); inset-inline-end: 0;',
701
+ },
702
+ template: `
845
703
  <div class="flex flex-col">
846
704
  @for (lang of languages(); track lang.id) {
847
705
  <button
@@ -859,9 +717,8 @@ class LanguageSelectorPanelComponent {
859
717
  }
860
718
  </div>
861
719
  `,
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 }); })();
720
+ }]
721
+ }], ctorParameters: () => [] });
865
722
 
866
723
  function provideLocalization(config) {
867
724
  const providers = [
@@ -914,10 +771,6 @@ const LOCALIZATION_ROUTES = [
914
771
  path: 'keys/:id',
915
772
  loadComponent: () => Promise.resolve().then(function () { return translationKeyForm_page; }).then((m) => m.TranslationKeyFormPage),
916
773
  },
917
- {
918
- path: 'translations',
919
- loadComponent: () => Promise.resolve().then(function () { return translationList_page; }).then((m) => m.TranslationListPage),
920
- },
921
774
  {
922
775
  path: '',
923
776
  redirectTo: 'languages',
@@ -927,22 +780,6 @@ const LOCALIZATION_ROUTES = [
927
780
  },
928
781
  ];
929
782
 
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
783
  class LocalizationContainerPage {
947
784
  permissionValidator = inject(PermissionValidatorService);
948
785
  allTabs = [
@@ -960,13 +797,6 @@ class LocalizationContainerPage {
960
797
  route: 'keys',
961
798
  permission: TRANSLATION_KEY_PERMISSIONS.READ,
962
799
  },
963
- {
964
- id: 'translations',
965
- labelKey: 'localization.tabs.translations',
966
- icon: 'pi pi-language',
967
- route: 'translations',
968
- permission: TRANSLATION_PERMISSIONS.READ,
969
- },
970
800
  ];
971
801
  visibleTabs = computed(() => {
972
802
  // Explicitly track permissions signal for reactivity
@@ -975,33 +805,34 @@ class LocalizationContainerPage {
975
805
  return [];
976
806
  return this.allTabs.filter((tab) => this.permissionValidator.hasPermission(tab.permission));
977
807
  }, ...(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}"] });
808
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationContainerPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
809
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LocalizationContainerPage, isStandalone: true, selector: "lib-localization-container", ngImport: i0, template: `
810
+ <div class="p-2 sm:p-4">
811
+ <div class="mb-4">
812
+ <h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'localization.title' | translate }}</h1>
813
+ <p class="text-muted-color mt-1 text-sm sm:text-base">{{ 'localization.subtitle' | translate }}</p>
814
+ </div>
815
+
816
+ <div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
817
+ @for (tab of visibleTabs(); track tab.id) {
818
+ <a
819
+ [routerLink]="tab.route"
820
+ routerLinkActive="tab-active"
821
+ 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"
822
+ >
823
+ <i [class]="tab.icon"></i>
824
+ <span>{{ tab.labelKey | translate }}</span>
825
+ </a>
826
+ }
827
+ </div>
828
+
829
+ <router-outlet />
830
+ </div>
831
+ `, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1001
832
  }
1002
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LocalizationContainerPage, [{
1003
- type: Component,
1004
- args: [{ selector: 'lib-localization-container', imports: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], template: `
833
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LocalizationContainerPage, decorators: [{
834
+ type: Component,
835
+ args: [{ selector: 'lib-localization-container', imports: [RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], template: `
1005
836
  <div class="p-2 sm:p-4">
1006
837
  <div class="mb-4">
1007
838
  <h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'localization.title' | translate }}</h1>
@@ -1024,160 +855,13 @@ class LocalizationContainerPage {
1024
855
  <router-outlet />
1025
856
  </div>
1026
857
  `, 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 }); })();
858
+ }] });
1029
859
 
1030
860
  var localizationContainer_page = /*#__PURE__*/Object.freeze({
1031
861
  __proto__: null,
1032
862
  LocalizationContainerPage: LocalizationContainerPage
1033
863
  });
1034
864
 
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
865
  class LanguageListPage {
1182
866
  LANGUAGE_PERMISSIONS = LANGUAGE_PERMISSIONS;
1183
867
  router = inject(Router);
@@ -1186,10 +870,12 @@ class LanguageListPage {
1186
870
  messageService = inject(MessageService);
1187
871
  translateService = inject(TranslateService);
1188
872
  destroyRef = inject(DestroyRef);
1189
- isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
1190
- languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
1191
873
  ngOnInit() {
1192
- this.loadLanguages();
874
+ this.languageService.fetchList('', {
875
+ pagination: { currentPage: 0, pageSize: 100 },
876
+ filter: {},
877
+ sort: { serial: 'ASC', name: 'ASC' },
878
+ });
1193
879
  }
1194
880
  onCreate() {
1195
881
  this.router.navigate(['/localization/languages/new']);
@@ -1197,29 +883,14 @@ class LanguageListPage {
1197
883
  onEdit(id) {
1198
884
  this.router.navigate(['/localization/languages', id]);
1199
885
  }
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
886
  onSetDefault(lang) {
1217
887
  this.confirmationService.confirm({
1218
888
  message: this.translateService.translate('localization.language.confirm.set.default', { name: lang.name }),
1219
889
  header: this.translateService.translate('localization.language.set.default'),
1220
890
  icon: 'pi pi-star',
1221
891
  accept: () => {
1222
- this.languageService.setDefault(lang.id)
892
+ this.languageService
893
+ .setDefault(lang.id)
1223
894
  .pipe(takeUntilDestroyed(this.destroyRef))
1224
895
  .subscribe({
1225
896
  next: (response) => {
@@ -1227,9 +898,11 @@ class LanguageListPage {
1227
898
  this.messageService.add({
1228
899
  severity: 'success',
1229
900
  summary: this.translateService.translate('shared.success'),
1230
- detail: this.translateService.translate('localization.language.set.default.success', { name: lang.name }),
901
+ detail: response.messageKey
902
+ ? this.translateService.translate(response.messageKey, response.messageVariables)
903
+ : (response.message ?? ''),
1231
904
  });
1232
- this.loadLanguages();
905
+ this.languageService.reload();
1233
906
  }
1234
907
  },
1235
908
  });
@@ -1243,7 +916,7 @@ class LanguageListPage {
1243
916
  icon: 'pi pi-exclamation-triangle',
1244
917
  acceptButtonStyleClass: 'p-button-danger',
1245
918
  accept: () => {
1246
- this.languageService.delete(lang.id)
919
+ from(this.languageService.delete({ id: lang.id, type: 'delete' }))
1247
920
  .pipe(takeUntilDestroyed(this.destroyRef))
1248
921
  .subscribe({
1249
922
  next: (response) => {
@@ -1251,60 +924,34 @@ class LanguageListPage {
1251
924
  this.messageService.add({
1252
925
  severity: 'success',
1253
926
  summary: this.translateService.translate('shared.success'),
1254
- detail: this.translateService.translate('localization.language.delete.success'),
927
+ detail: response.messageKey
928
+ ? this.translateService.translate(response.messageKey, response.messageVariables)
929
+ : (response.message ?? ''),
1255
930
  });
1256
- this.loadLanguages();
931
+ this.languageService.reload();
1257
932
  }
1258
933
  },
1259
934
  });
1260
935
  },
1261
936
  });
1262
937
  }
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: `
938
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageListPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
939
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LanguageListPage, isStandalone: true, selector: "lib-language-list-page", providers: [ConfirmationService, MessageService], ngImport: i0, template: `
1297
940
  <div class="card">
1298
- <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
941
+ <div
942
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
943
+ >
1299
944
  <div>
1300
- <h3 class="text-lg sm:text-xl font-semibold m-0">{{ 'localization.language.title' | translate }}</h3>
945
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
946
+ {{ 'localization.language.title' | translate }}
947
+ </h3>
1301
948
  <p class="text-sm text-muted-color mt-1">
1302
949
  {{ 'localization.language.subtitle' | translate }}
1303
950
  </p>
1304
951
  </div>
1305
952
  <p-button
1306
953
  *hasPermission="LANGUAGE_PERMISSIONS.CREATE"
1307
- [label]="'localization.language.create' | translate"
954
+ [label]="'localization.language.new' | translate"
1308
955
  icon="pi pi-plus"
1309
956
  (onClick)="onCreate()"
1310
957
  styleClass="w-full sm:w-auto"
@@ -1313,8 +960,8 @@ class LanguageListPage {
1313
960
 
1314
961
  <div class="overflow-x-auto -mx-4 sm:mx-0">
1315
962
  <p-table
1316
- [value]="languages()"
1317
- [loading]="isLoading()"
963
+ [value]="languageService.data()"
964
+ [loading]="languageService.isLoading()"
1318
965
  styleClass="p-datatable-sm"
1319
966
  [tableStyle]="{ 'min-width': '40rem' }"
1320
967
  >
@@ -1338,18 +985,29 @@ class LanguageListPage {
1338
985
  <td>{{ lang.nativeName || ('shared.na' | translate) }}</td>
1339
986
  <td>
1340
987
  <p-tag
1341
- [value]="lang.direction === 'rtl' ? ('localization.language.rtl' | translate) : ('localization.language.ltr' | translate)"
988
+ [value]="
989
+ lang.direction === 'rtl'
990
+ ? ('localization.language.rtl' | translate)
991
+ : ('localization.language.ltr' | translate)
992
+ "
1342
993
  [severity]="lang.direction === 'rtl' ? 'warn' : 'info'"
1343
994
  />
1344
995
  </td>
1345
996
  <td>
1346
997
  <div class="flex gap-1 items-center">
1347
998
  <p-tag
1348
- [value]="lang.isActive ? ('shared.active' | translate) : ('shared.inactive' | translate)"
999
+ [value]="
1000
+ lang.isActive
1001
+ ? ('shared.active' | translate)
1002
+ : ('shared.inactive' | translate)
1003
+ "
1349
1004
  [severity]="lang.isActive ? 'success' : 'secondary'"
1350
1005
  />
1351
1006
  @if (lang.isDefault) {
1352
- <p-tag [value]="'localization.language.default' | translate" severity="contrast" />
1007
+ <p-tag
1008
+ [value]="'localization.language.default' | translate"
1009
+ severity="contrast"
1010
+ />
1353
1011
  }
1354
1012
  </div>
1355
1013
  </td>
@@ -1361,7 +1019,9 @@ class LanguageListPage {
1361
1019
  icon="pi pi-star"
1362
1020
  [text]="true"
1363
1021
  size="small"
1364
- [pTooltip]="'localization.language.set.default' | translate"
1022
+ [pTooltip]="
1023
+ 'localization.language.set.default' | translate
1024
+ "
1365
1025
  (onClick)="onSetDefault(lang)"
1366
1026
  />
1367
1027
  }
@@ -1402,46 +1062,175 @@ class LanguageListPage {
1402
1062
 
1403
1063
  <p-confirmDialog />
1404
1064
  <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);
1065
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1066
+ }
1067
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageListPage, decorators: [{
1068
+ type: Component,
1069
+ args: [{
1070
+ selector: 'lib-language-list-page',
1071
+ imports: [AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe],
1072
+ providers: [ConfirmationService, MessageService],
1073
+ template: `
1074
+ <div class="card">
1075
+ <div
1076
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
1077
+ >
1078
+ <div>
1079
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
1080
+ {{ 'localization.language.title' | translate }}
1081
+ </h3>
1082
+ <p class="text-sm text-muted-color mt-1">
1083
+ {{ 'localization.language.subtitle' | translate }}
1084
+ </p>
1085
+ </div>
1086
+ <p-button
1087
+ *hasPermission="LANGUAGE_PERMISSIONS.CREATE"
1088
+ [label]="'localization.language.new' | translate"
1089
+ icon="pi pi-plus"
1090
+ (onClick)="onCreate()"
1091
+ styleClass="w-full sm:w-auto"
1092
+ />
1093
+ </div>
1094
+
1095
+ <div class="overflow-x-auto -mx-4 sm:mx-0">
1096
+ <p-table
1097
+ [value]="languageService.data()"
1098
+ [loading]="languageService.isLoading()"
1099
+ styleClass="p-datatable-sm"
1100
+ [tableStyle]="{ 'min-width': '40rem' }"
1101
+ >
1102
+ <ng-template #header>
1103
+ <tr>
1104
+ <th>{{ 'localization.language.code' | translate }}</th>
1105
+ <th>{{ 'localization.language.name' | translate }}</th>
1106
+ <th>{{ 'localization.language.native.name' | translate }}</th>
1107
+ <th>{{ 'localization.language.direction' | translate }}</th>
1108
+ <th>{{ 'shared.status' | translate }}</th>
1109
+ <th class="w-[150px]">{{ 'shared.actions' | translate }}</th>
1110
+ </tr>
1111
+ </ng-template>
1112
+
1113
+ <ng-template #body let-lang>
1114
+ <tr>
1115
+ <td>
1116
+ <span class="uppercase font-semibold">{{ lang.code }}</span>
1117
+ </td>
1118
+ <td>{{ lang.name }}</td>
1119
+ <td>{{ lang.nativeName || ('shared.na' | translate) }}</td>
1120
+ <td>
1121
+ <p-tag
1122
+ [value]="
1123
+ lang.direction === 'rtl'
1124
+ ? ('localization.language.rtl' | translate)
1125
+ : ('localization.language.ltr' | translate)
1126
+ "
1127
+ [severity]="lang.direction === 'rtl' ? 'warn' : 'info'"
1128
+ />
1129
+ </td>
1130
+ <td>
1131
+ <div class="flex gap-1 items-center">
1132
+ <p-tag
1133
+ [value]="
1134
+ lang.isActive
1135
+ ? ('shared.active' | translate)
1136
+ : ('shared.inactive' | translate)
1137
+ "
1138
+ [severity]="lang.isActive ? 'success' : 'secondary'"
1139
+ />
1140
+ @if (lang.isDefault) {
1141
+ <p-tag
1142
+ [value]="'localization.language.default' | translate"
1143
+ severity="contrast"
1144
+ />
1145
+ }
1146
+ </div>
1147
+ </td>
1148
+ <td>
1149
+ <div class="flex gap-1">
1150
+ @if (!lang.isDefault) {
1151
+ <p-button
1152
+ *hasPermission="LANGUAGE_PERMISSIONS.UPDATE"
1153
+ icon="pi pi-star"
1154
+ [text]="true"
1155
+ size="small"
1156
+ [pTooltip]="
1157
+ 'localization.language.set.default' | translate
1158
+ "
1159
+ (onClick)="onSetDefault(lang)"
1160
+ />
1161
+ }
1162
+ <p-button
1163
+ *hasPermission="LANGUAGE_PERMISSIONS.UPDATE"
1164
+ icon="pi pi-pencil"
1165
+ [text]="true"
1166
+ severity="secondary"
1167
+ size="small"
1168
+ [pTooltip]="'shared.edit' | translate"
1169
+ (onClick)="onEdit(lang.id)"
1170
+ />
1171
+ <p-button
1172
+ *hasPermission="LANGUAGE_PERMISSIONS.DELETE"
1173
+ icon="pi pi-trash"
1174
+ [text]="true"
1175
+ severity="danger"
1176
+ size="small"
1177
+ [pTooltip]="'shared.delete' | translate"
1178
+ [disabled]="lang.isDefault"
1179
+ (onClick)="onDelete(lang)"
1180
+ />
1181
+ </div>
1182
+ </td>
1183
+ </tr>
1184
+ </ng-template>
1185
+
1186
+ <ng-template #emptymessage>
1187
+ <tr>
1188
+ <td colspan="6" class="text-center py-4 text-muted-color">
1189
+ {{ 'localization.language.empty' | translate }}
1190
+ </td>
1191
+ </tr>
1192
+ </ng-template>
1193
+ </p-table>
1194
+ </div>
1195
+ </div>
1196
+
1197
+ <p-confirmDialog />
1198
+ <p-toast />
1199
+ `,
1200
+ }]
1201
+ }] });
1202
+
1203
+ var languageList_page = /*#__PURE__*/Object.freeze({
1204
+ __proto__: null,
1205
+ LanguageListPage: LanguageListPage
1206
+ });
1207
+
1208
+ class LanguageFormPage {
1209
+ router = inject(Router);
1210
+ route = inject(ActivatedRoute);
1211
+ languageService = inject(LanguageApiService);
1431
1212
  messageService = inject(MessageService);
1432
- translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
1213
+ translateAdapter = inject(TRANSLATE_ADAPTER, {
1214
+ optional: true,
1215
+ });
1433
1216
  destroyRef = inject(DestroyRef);
1434
1217
  routeParams = toSignal(this.route.paramMap);
1435
1218
  loadTriggered = false;
1436
1219
  isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
1437
1220
  existingLanguage = signal(null, ...(ngDevMode ? [{ debugName: "existingLanguage" }] : []));
1438
1221
  isEditMode = computed(() => !!this.existingLanguage(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
1439
- translate(key) {
1440
- return this.translateAdapter?.translate(key) ?? key;
1222
+ translate(key, vars) {
1223
+ return this.translateAdapter?.translate(key, vars) ?? key;
1441
1224
  }
1442
1225
  directionOptions = computed(() => [
1443
- { label: this.translate('localization.language.direction.ltr'), value: 'ltr' },
1444
- { label: this.translate('localization.language.direction.rtl'), value: 'rtl' },
1226
+ {
1227
+ label: this.translate('localization.language.direction.ltr'),
1228
+ value: 'ltr',
1229
+ },
1230
+ {
1231
+ label: this.translate('localization.language.direction.rtl'),
1232
+ value: 'rtl',
1233
+ },
1445
1234
  ], ...(ngDevMode ? [{ debugName: "directionOptions" }] : []));
1446
1235
  formModel = signal({
1447
1236
  code: '',
@@ -1453,10 +1242,18 @@ class LanguageFormPage {
1453
1242
  isDefault: false,
1454
1243
  }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
1455
1244
  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') });
1245
+ required(f.code, {
1246
+ message: this.translate('localization.validation.code.required'),
1247
+ });
1248
+ maxLength(f.code, 10, {
1249
+ message: this.translate('localization.validation.code.max.length'),
1250
+ });
1251
+ required(f.name, {
1252
+ message: this.translate('localization.validation.name.required'),
1253
+ });
1254
+ maxLength(f.name, 100, {
1255
+ message: this.translate('localization.validation.name.max.length'),
1256
+ });
1460
1257
  });
1461
1258
  isFormValid = computed(() => {
1462
1259
  const model = this.formModel();
@@ -1479,7 +1276,7 @@ class LanguageFormPage {
1479
1276
  }
1480
1277
  loadLanguage(id) {
1481
1278
  this.isSaving.set(true);
1482
- this.languageService.getById(id)
1279
+ from(this.languageService.findById(id))
1483
1280
  .pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
1484
1281
  .subscribe({
1485
1282
  next: (response) => {
@@ -1517,8 +1314,11 @@ class LanguageFormPage {
1517
1314
  isDefault: model.isDefault,
1518
1315
  };
1519
1316
  const operation$ = this.isEditMode()
1520
- ? this.languageService.update({ id: this.existingLanguage().id, ...dto })
1521
- : this.languageService.create(dto);
1317
+ ? from(this.languageService.update({
1318
+ id: this.existingLanguage().id,
1319
+ ...dto,
1320
+ }))
1321
+ : from(this.languageService.insert(dto));
1522
1322
  operation$
1523
1323
  .pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
1524
1324
  .subscribe({
@@ -1527,7 +1327,9 @@ class LanguageFormPage {
1527
1327
  this.messageService.add({
1528
1328
  severity: 'success',
1529
1329
  summary: this.translate('shared.success'),
1530
- detail: this.translate(this.isEditMode() ? 'localization.language.update.success' : 'localization.language.create.success'),
1330
+ detail: response.messageKey
1331
+ ? this.translate(response.messageKey, response.messageVariables)
1332
+ : (response.message ?? ''),
1531
1333
  });
1532
1334
  this.router.navigate(['/localization/languages']);
1533
1335
  }
@@ -1537,197 +1339,239 @@ class LanguageFormPage {
1537
1339
  onCancel() {
1538
1340
  this.router.navigate(['/localization/languages']);
1539
1341
  }
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 });
1342
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageFormPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
1343
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: LanguageFormPage, isStandalone: true, selector: "lib-language-form-page", providers: [MessageService], ngImport: i0, template: `
1344
+ <p-card>
1345
+ <ng-template #header>
1346
+ <div class="flex justify-between items-center p-4">
1347
+ <h2 class="text-xl font-semibold m-0">
1348
+ {{
1349
+ isEditMode()
1350
+ ? ('localization.language.edit' | translate)
1351
+ : ('localization.language.new' | translate)
1352
+ }}
1353
+ </h2>
1354
+ </div>
1355
+ </ng-template>
1356
+
1357
+ <form
1358
+ (ngSubmit)="onSubmit()"
1359
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
1360
+ >
1361
+ <!-- Language Code -->
1362
+ <div class="flex flex-col gap-2">
1363
+ <label for="code" class="font-medium"
1364
+ >{{ 'localization.language.code' | translate }} *</label
1365
+ >
1366
+ <input
1367
+ pInputText
1368
+ id="code"
1369
+ [formField]="formTree.code"
1370
+ [placeholder]="'localization.placeholder.code' | translate"
1371
+ />
1372
+ <small class="text-muted-color">{{
1373
+ 'localization.language.iso.code.hint' | translate
1374
+ }}</small>
1375
+ </div>
1376
+
1377
+ <!-- Language Name -->
1378
+ <div class="flex flex-col gap-2">
1379
+ <label for="name" class="font-medium"
1380
+ >{{ 'localization.language.name' | translate }} *</label
1381
+ >
1382
+ <input
1383
+ pInputText
1384
+ id="name"
1385
+ [formField]="formTree.name"
1386
+ [placeholder]="'localization.placeholder.name' | translate"
1387
+ />
1388
+ </div>
1389
+
1390
+ <!-- Native Name -->
1391
+ <div class="flex flex-col gap-2">
1392
+ <label for="nativeName" class="font-medium">{{
1393
+ 'localization.language.native.name' | translate
1394
+ }}</label>
1395
+ <input
1396
+ pInputText
1397
+ id="nativeName"
1398
+ [formField]="formTree.nativeName"
1399
+ [placeholder]="'localization.placeholder.native.name' | translate"
1400
+ />
1401
+ <small class="text-muted-color">{{
1402
+ 'localization.language.native.name.hint' | translate
1403
+ }}</small>
1404
+ </div>
1405
+
1406
+ <!-- Text Direction -->
1407
+ <div class="flex flex-col gap-2">
1408
+ <label for="direction" class="font-medium"
1409
+ >{{ 'localization.language.direction' | translate }} *</label
1410
+ >
1411
+ <p-select
1412
+ id="direction"
1413
+ [ngModel]="formModel().direction"
1414
+ (ngModelChange)="updateDirection($event)"
1415
+ [ngModelOptions]="{ standalone: true }"
1416
+ [options]="directionOptions()"
1417
+ optionLabel="label"
1418
+ optionValue="value"
1419
+ class="w-full"
1420
+ />
1421
+ </div>
1422
+
1423
+ <!-- Display Order -->
1424
+ <div class="flex flex-col gap-2">
1425
+ <label for="serial" class="font-medium">{{
1426
+ 'localization.language.display.order' | translate
1427
+ }}</label>
1428
+ <input
1429
+ pInputText
1430
+ id="serial"
1431
+ type="number"
1432
+ [formField]="formTree.serial"
1433
+ [placeholder]="'shared.display.order.placeholder' | translate"
1434
+ />
1435
+ </div>
1436
+
1437
+ <!-- Empty cell for alignment -->
1438
+ <div class="hidden md:block"></div>
1439
+
1440
+ <!-- Checkboxes -->
1441
+ <div class="flex items-center gap-6 md:col-span-2 pt-4">
1442
+ <label class="p-checkbox-native">
1443
+ <input type="checkbox" [formField]="formTree.isActive" />
1444
+ <span>{{ 'shared.active' | translate }}</span>
1445
+ </label>
1446
+ <label class="p-checkbox-native">
1447
+ <input type="checkbox" [formField]="formTree.isDefault" />
1448
+ <span>{{ 'localization.language.default' | translate }}</span>
1449
+ </label>
1450
+ </div>
1451
+
1452
+ <!-- Actions -->
1453
+ <div class="flex justify-end gap-4 md:col-span-2 pt-4">
1454
+ <p-button
1455
+ [label]="'shared.cancel' | translate"
1456
+ severity="secondary"
1457
+ [outlined]="true"
1458
+ (onClick)="onCancel()"
1459
+ />
1460
+ <p-button
1461
+ [label]="
1462
+ isEditMode()
1463
+ ? ('shared.update' | translate)
1464
+ : ('shared.create' | translate)
1465
+ "
1466
+ type="submit"
1467
+ [loading]="isSaving()"
1468
+ [disabled]="!isFormValid() || isSaving()"
1469
+ />
1470
+ </div>
1471
+ </form>
1472
+ </p-card>
1473
+
1474
+ <p-toast />
1475
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1658
1476
  }
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: `
1477
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageFormPage, decorators: [{
1478
+ type: Component,
1479
+ args: [{
1480
+ selector: 'lib-language-form-page',
1481
+ imports: [AngularModule, PrimeModule, FormsModule, FormField, TranslatePipe],
1482
+ providers: [MessageService],
1483
+ template: `
1666
1484
  <p-card>
1667
1485
  <ng-template #header>
1668
1486
  <div class="flex justify-between items-center p-4">
1669
1487
  <h2 class="text-xl font-semibold m-0">
1670
- {{ isEditMode() ? ('localization.language.edit' | translate) : ('localization.language.create' | translate) }}
1488
+ {{
1489
+ isEditMode()
1490
+ ? ('localization.language.edit' | translate)
1491
+ : ('localization.language.new' | translate)
1492
+ }}
1671
1493
  </h2>
1672
1494
  </div>
1673
1495
  </ng-template>
1674
1496
 
1675
- <form (ngSubmit)="onSubmit()" class="grid grid-cols-1 md:grid-cols-2 gap-4">
1497
+ <form
1498
+ (ngSubmit)="onSubmit()"
1499
+ class="grid grid-cols-1 md:grid-cols-2 gap-4"
1500
+ >
1676
1501
  <!-- Language Code -->
1677
1502
  <div class="flex flex-col gap-2">
1678
- <label for="code" class="font-medium">{{ 'localization.language.code' | translate }} *</label>
1503
+ <label for="code" class="font-medium"
1504
+ >{{ 'localization.language.code' | translate }} *</label
1505
+ >
1679
1506
  <input
1680
1507
  pInputText
1681
1508
  id="code"
1682
1509
  [formField]="formTree.code"
1683
- [placeholder]="'localization.placeholder.code' | translate" />
1684
- <small class="text-muted-color">{{ 'localization.language.iso.code.hint' | translate }}</small>
1510
+ [placeholder]="'localization.placeholder.code' | translate"
1511
+ />
1512
+ <small class="text-muted-color">{{
1513
+ 'localization.language.iso.code.hint' | translate
1514
+ }}</small>
1685
1515
  </div>
1686
1516
 
1687
1517
  <!-- Language Name -->
1688
1518
  <div class="flex flex-col gap-2">
1689
- <label for="name" class="font-medium">{{ 'localization.language.name' | translate }} *</label>
1519
+ <label for="name" class="font-medium"
1520
+ >{{ 'localization.language.name' | translate }} *</label
1521
+ >
1690
1522
  <input
1691
1523
  pInputText
1692
1524
  id="name"
1693
1525
  [formField]="formTree.name"
1694
- [placeholder]="'localization.placeholder.name' | translate" />
1526
+ [placeholder]="'localization.placeholder.name' | translate"
1527
+ />
1695
1528
  </div>
1696
1529
 
1697
1530
  <!-- Native Name -->
1698
1531
  <div class="flex flex-col gap-2">
1699
- <label for="nativeName" class="font-medium">{{ 'localization.language.native.name' | translate }}</label>
1532
+ <label for="nativeName" class="font-medium">{{
1533
+ 'localization.language.native.name' | translate
1534
+ }}</label>
1700
1535
  <input
1701
1536
  pInputText
1702
1537
  id="nativeName"
1703
1538
  [formField]="formTree.nativeName"
1704
- [placeholder]="'localization.placeholder.native.name' | translate" />
1705
- <small class="text-muted-color">{{ 'localization.language.native.name.hint' | translate }}</small>
1539
+ [placeholder]="'localization.placeholder.native.name' | translate"
1540
+ />
1541
+ <small class="text-muted-color">{{
1542
+ 'localization.language.native.name.hint' | translate
1543
+ }}</small>
1706
1544
  </div>
1707
1545
 
1708
1546
  <!-- Text Direction -->
1709
1547
  <div class="flex flex-col gap-2">
1710
- <label for="direction" class="font-medium">{{ 'localization.language.direction' | translate }} *</label>
1548
+ <label for="direction" class="font-medium"
1549
+ >{{ 'localization.language.direction' | translate }} *</label
1550
+ >
1711
1551
  <p-select
1712
1552
  id="direction"
1713
1553
  [ngModel]="formModel().direction"
1714
1554
  (ngModelChange)="updateDirection($event)"
1715
- [ngModelOptions]="{standalone: true}"
1555
+ [ngModelOptions]="{ standalone: true }"
1716
1556
  [options]="directionOptions()"
1717
1557
  optionLabel="label"
1718
1558
  optionValue="value"
1719
- class="w-full" />
1559
+ class="w-full"
1560
+ />
1720
1561
  </div>
1721
1562
 
1722
1563
  <!-- Display Order -->
1723
1564
  <div class="flex flex-col gap-2">
1724
- <label for="serial" class="font-medium">{{ 'localization.language.display.order' | translate }}</label>
1565
+ <label for="serial" class="font-medium">{{
1566
+ 'localization.language.display.order' | translate
1567
+ }}</label>
1725
1568
  <input
1726
1569
  pInputText
1727
1570
  id="serial"
1728
1571
  type="number"
1729
1572
  [formField]="formTree.serial"
1730
- [placeholder]="'shared.display.order.placeholder' | translate" />
1573
+ [placeholder]="'shared.display.order.placeholder' | translate"
1574
+ />
1731
1575
  </div>
1732
1576
 
1733
1577
  <!-- Empty cell for alignment -->
@@ -1751,145 +1595,32 @@ class LanguageFormPage {
1751
1595
  [label]="'shared.cancel' | translate"
1752
1596
  severity="secondary"
1753
1597
  [outlined]="true"
1754
- (onClick)="onCancel()" />
1598
+ (onClick)="onCancel()"
1599
+ />
1755
1600
  <p-button
1756
- [label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
1601
+ [label]="
1602
+ isEditMode()
1603
+ ? ('shared.update' | translate)
1604
+ : ('shared.create' | translate)
1605
+ "
1757
1606
  type="submit"
1758
1607
  [loading]="isSaving()"
1759
- [disabled]="!isFormValid() || isSaving()" />
1608
+ [disabled]="!isFormValid() || isSaving()"
1609
+ />
1760
1610
  </div>
1761
1611
  </form>
1762
1612
  </p-card>
1763
1613
 
1764
1614
  <p-toast />
1765
1615
  `,
1766
- }]
1767
- }], () => [], null); })();
1768
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(LanguageFormPage, { className: "LanguageFormPage", filePath: "pages/language-form/language-form.page.ts", lineNumber: 136 }); })();
1616
+ }]
1617
+ }], ctorParameters: () => [] });
1769
1618
 
1770
1619
  var languageForm_page = /*#__PURE__*/Object.freeze({
1771
1620
  __proto__: null,
1772
1621
  LanguageFormPage: LanguageFormPage
1773
1622
  });
1774
1623
 
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
1624
  class TranslationKeyListPage {
1894
1625
  TRANSLATION_KEY_PERMISSIONS = TRANSLATION_KEY_PERMISSIONS;
1895
1626
  router = inject(Router);
@@ -1908,7 +1639,7 @@ class TranslationKeyListPage {
1908
1639
  selectedModule = signal(null, ...(ngDevMode ? [{ debugName: "selectedModule" }] : []));
1909
1640
  searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1910
1641
  moduleOptions = computed(() => [
1911
- { label: this.translateService.instant('shared.all'), value: null },
1642
+ { label: this.translateService.translate('shared.all'), value: null },
1912
1643
  ...this.modules().map((m) => ({ label: m, value: m })),
1913
1644
  ], ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
1914
1645
  filteredKeys = computed(() => {
@@ -1931,9 +1662,17 @@ class TranslationKeyListPage {
1931
1662
  loadData() {
1932
1663
  this.isLoading.set(true);
1933
1664
  forkJoin({
1934
- languages: this.languageService.getAll(),
1665
+ languages: from(this.languageService.getAll({
1666
+ pagination: { currentPage: 0, pageSize: 100 },
1667
+ filter: {},
1668
+ sort: { serial: 'ASC', name: 'ASC' },
1669
+ })),
1935
1670
  modules: this.translationKeyService.getModules(),
1936
- keys: this.translationKeyService.getAll(),
1671
+ keys: from(this.translationKeyService.getAll({
1672
+ pagination: { currentPage: 0, pageSize: 1000 },
1673
+ filter: {},
1674
+ sort: { module: 'ASC', key: 'ASC' },
1675
+ })),
1937
1676
  })
1938
1677
  .pipe(takeUntilDestroyed(this.destroyRef))
1939
1678
  .subscribe({
@@ -1956,7 +1695,8 @@ class TranslationKeyListPage {
1956
1695
  });
1957
1696
  }
1958
1697
  loadTranslationCounts() {
1959
- this.translationService.getCounts()
1698
+ this.translationService
1699
+ .getCounts()
1960
1700
  .pipe(takeUntilDestroyed(this.destroyRef))
1961
1701
  .subscribe({
1962
1702
  next: (response) => {
@@ -1985,15 +1725,17 @@ class TranslationKeyListPage {
1985
1725
  icon: 'pi pi-exclamation-triangle',
1986
1726
  acceptButtonStyleClass: 'p-button-danger',
1987
1727
  accept: () => {
1988
- this.translationKeyService.delete(key.id)
1728
+ from(this.translationKeyService.delete({ id: key.id, type: 'delete' }))
1989
1729
  .pipe(takeUntilDestroyed(this.destroyRef))
1990
1730
  .subscribe({
1991
1731
  next: (response) => {
1992
1732
  if (response.success) {
1993
1733
  this.messageService.add({
1994
1734
  severity: 'success',
1995
- summary: this.translateService.instant('shared.success'),
1996
- detail: this.translateService.instant('localization.translation.key.delete.success'),
1735
+ summary: this.translateService.translate('shared.success'),
1736
+ detail: response.messageKey
1737
+ ? this.translateService.translate(response.messageKey, response.messageVariables)
1738
+ : (response.message ?? ''),
1997
1739
  });
1998
1740
  this.loadData();
1999
1741
  }
@@ -2002,80 +1744,37 @@ class TranslationKeyListPage {
2002
1744
  },
2003
1745
  });
2004
1746
  }
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: `
1747
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyListPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
1748
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: TranslationKeyListPage, isStandalone: true, selector: "lib-translation-key-list-page", providers: [ConfirmationService, MessageService], ngImport: i0, template: `
2055
1749
  <div class="card">
2056
- <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4">
1750
+ <div
1751
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
1752
+ >
2057
1753
  <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>
1754
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
1755
+ {{ 'localization.key.title' | translate }}
1756
+ </h3>
1757
+ <p class="text-sm text-muted-color mt-1">
1758
+ {{ 'localization.key.subtitle' | translate }}
1759
+ </p>
2060
1760
  </div>
2061
1761
  <div class="flex gap-2">
2062
1762
  <p-button
2063
1763
  *hasPermission="TRANSLATION_KEY_PERMISSIONS.CREATE"
2064
- [label]="'localization.key.create' | translate"
1764
+ [label]="'localization.key.new' | translate"
2065
1765
  icon="pi pi-plus"
2066
1766
  (onClick)="onCreate()"
2067
1767
  />
2068
1768
  </div>
2069
1769
  </div>
2070
1770
 
2071
- <!-- Filters -->
2072
1771
  <div class="flex flex-col md:flex-row gap-4 mb-4">
2073
1772
  <div class="flex-1">
2074
1773
  <p-select
2075
1774
  [options]="moduleOptions()"
2076
1775
  [ngModel]="selectedModule()"
2077
1776
  (ngModelChange)="onModuleChange($event)"
2078
- [ngModelOptions]="{standalone: true}"
1777
+ [ngModelOptions]="{ standalone: true }"
2079
1778
  optionLabel="label"
2080
1779
  optionValue="value"
2081
1780
  [placeholder]="'localization.key.filter.module' | translate"
@@ -2090,7 +1789,7 @@ class TranslationKeyListPage {
2090
1789
  pInputText
2091
1790
  [ngModel]="searchTerm()"
2092
1791
  (ngModelChange)="searchTerm.set($event)"
2093
- [ngModelOptions]="{standalone: true}"
1792
+ [ngModelOptions]="{ standalone: true }"
2094
1793
  [placeholder]="'shared.search' | translate"
2095
1794
  class="w-full"
2096
1795
  />
@@ -2105,18 +1804,28 @@ class TranslationKeyListPage {
2105
1804
  [paginator]="true"
2106
1805
  [rows]="15"
2107
1806
  [rowsPerPageOptions]="[10, 15, 25, 50]"
2108
- styleClass="p-datatable-sm"
1807
+ class="p-datatable-sm"
2109
1808
  >
2110
1809
  <ng-template #header>
2111
1810
  <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>
1811
+ <th style="width: 15%">
1812
+ {{ 'localization.key.module' | translate }}
1813
+ </th>
1814
+ <th style="width: 25%">
1815
+ {{ 'localization.key.name' | translate }}
1816
+ </th>
1817
+ <th style="width: 35%">
1818
+ {{ 'localization.key.default.message' | translate }}
1819
+ </th>
1820
+ <th style="width: 10%">
1821
+ {{ 'localization.key.translations' | translate }}
1822
+ </th>
2116
1823
  <th style="width: 15%">{{ 'shared.actions' | translate }}</th>
2117
1824
  </tr>
2118
1825
  </ng-template>
2119
1826
  <ng-template #body let-key>
1827
+ @let translationCount = getTranslationCount(key.id);
1828
+ @let languageCount = languages().length;
2120
1829
  <tr>
2121
1830
  <td>
2122
1831
  <p-tag [value]="key.module" severity="secondary" />
@@ -2129,8 +1838,13 @@ class TranslationKeyListPage {
2129
1838
  </td>
2130
1839
  <td>{{ key.defaultMessage }}</td>
2131
1840
  <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 }}
1841
+ <span
1842
+ class="text-sm"
1843
+ [class.text-green-500]="translationCount === languageCount"
1844
+ [class.text-orange-500]="translationCount < languageCount && translationCount > 0"
1845
+ [class.text-muted-color]="translationCount === 0"
1846
+ >
1847
+ {{ translationCount }}/{{ languageCount }}
2134
1848
  </span>
2135
1849
  </td>
2136
1850
  <td>
@@ -2169,93 +1883,177 @@ class TranslationKeyListPage {
2169
1883
 
2170
1884
  <p-confirmDialog />
2171
1885
  <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
- });
1886
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: i4$2.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i5$2.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1887
+ }
1888
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyListPage, decorators: [{
1889
+ type: Component,
1890
+ args: [{
1891
+ selector: 'lib-translation-key-list-page',
1892
+ imports: [
1893
+ AngularModule,
1894
+ PrimeModule,
1895
+ FormsModule,
1896
+ HasPermissionDirective,
1897
+ TranslatePipe,
1898
+ ],
1899
+ providers: [ConfirmationService, MessageService],
1900
+ template: `
1901
+ <div class="card">
1902
+ <div
1903
+ class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
1904
+ >
1905
+ <div>
1906
+ <h3 class="text-lg sm:text-xl font-semibold m-0">
1907
+ {{ 'localization.key.title' | translate }}
1908
+ </h3>
1909
+ <p class="text-sm text-muted-color mt-1">
1910
+ {{ 'localization.key.subtitle' | translate }}
1911
+ </p>
1912
+ </div>
1913
+ <div class="flex gap-2">
1914
+ <p-button
1915
+ *hasPermission="TRANSLATION_KEY_PERMISSIONS.CREATE"
1916
+ [label]="'localization.key.new' | translate"
1917
+ icon="pi pi-plus"
1918
+ (onClick)="onCreate()"
1919
+ />
1920
+ </div>
1921
+ </div>
2181
1922
 
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);
1923
+ <div class="flex flex-col md:flex-row gap-4 mb-4">
1924
+ <div class="flex-1">
1925
+ <p-select
1926
+ [options]="moduleOptions()"
1927
+ [ngModel]="selectedModule()"
1928
+ (ngModelChange)="onModuleChange($event)"
1929
+ [ngModelOptions]="{ standalone: true }"
1930
+ optionLabel="label"
1931
+ optionValue="value"
1932
+ [placeholder]="'localization.key.filter.module' | translate"
1933
+ [showClear]="true"
1934
+ class="w-full"
1935
+ />
1936
+ </div>
1937
+ <div class="flex-1">
1938
+ <p-iconfield class="w-full">
1939
+ <p-inputicon class="pi pi-search" />
1940
+ <input
1941
+ pInputText
1942
+ [ngModel]="searchTerm()"
1943
+ (ngModelChange)="searchTerm.set($event)"
1944
+ [ngModelOptions]="{ standalone: true }"
1945
+ [placeholder]="'shared.search' | translate"
1946
+ class="w-full"
1947
+ />
1948
+ </p-iconfield>
1949
+ </div>
1950
+ </div>
1951
+
1952
+ <!-- Table -->
1953
+ <p-table
1954
+ [value]="filteredKeys()"
1955
+ [loading]="isLoading()"
1956
+ [paginator]="true"
1957
+ [rows]="15"
1958
+ [rowsPerPageOptions]="[10, 15, 25, 50]"
1959
+ class="p-datatable-sm"
1960
+ >
1961
+ <ng-template #header>
1962
+ <tr>
1963
+ <th style="width: 15%">
1964
+ {{ 'localization.key.module' | translate }}
1965
+ </th>
1966
+ <th style="width: 25%">
1967
+ {{ 'localization.key.name' | translate }}
1968
+ </th>
1969
+ <th style="width: 35%">
1970
+ {{ 'localization.key.default.message' | translate }}
1971
+ </th>
1972
+ <th style="width: 10%">
1973
+ {{ 'localization.key.translations' | translate }}
1974
+ </th>
1975
+ <th style="width: 15%">{{ 'shared.actions' | translate }}</th>
1976
+ </tr>
1977
+ </ng-template>
1978
+ <ng-template #body let-key>
1979
+ @let translationCount = getTranslationCount(key.id);
1980
+ @let languageCount = languages().length;
1981
+ <tr>
1982
+ <td>
1983
+ <p-tag [value]="key.module" severity="secondary" />
1984
+ </td>
1985
+ <td>
1986
+ <div class="font-medium">{{ key.key }}</div>
1987
+ @if (key.description) {
1988
+ <small class="text-muted-color">{{ key.description }}</small>
1989
+ }
1990
+ </td>
1991
+ <td>{{ key.defaultMessage }}</td>
1992
+ <td class="text-center">
1993
+ <span
1994
+ class="text-sm"
1995
+ [class.text-green-500]="translationCount === languageCount"
1996
+ [class.text-orange-500]="translationCount < languageCount && translationCount > 0"
1997
+ [class.text-muted-color]="translationCount === 0"
1998
+ >
1999
+ {{ translationCount }}/{{ languageCount }}
2000
+ </span>
2001
+ </td>
2002
+ <td>
2003
+ <div class="flex gap-1">
2004
+ <p-button
2005
+ *hasPermission="TRANSLATION_KEY_PERMISSIONS.UPDATE"
2006
+ icon="pi pi-pencil"
2007
+ [text]="true"
2008
+ severity="secondary"
2009
+ size="small"
2010
+ [pTooltip]="'shared.edit' | translate"
2011
+ (onClick)="onEdit(key)"
2012
+ />
2013
+ <p-button
2014
+ *hasPermission="TRANSLATION_KEY_PERMISSIONS.DELETE"
2015
+ icon="pi pi-trash"
2016
+ [text]="true"
2017
+ severity="danger"
2018
+ size="small"
2019
+ [pTooltip]="'shared.delete' | translate"
2020
+ (onClick)="onDelete(key)"
2021
+ />
2022
+ </div>
2023
+ </td>
2024
+ </tr>
2025
+ </ng-template>
2026
+ <ng-template #emptymessage>
2027
+ <tr>
2028
+ <td colspan="5" class="text-center py-4 text-muted-color">
2029
+ {{ 'localization.key.empty' | translate }}
2030
+ </td>
2031
+ </tr>
2032
+ </ng-template>
2033
+ </p-table>
2034
+ </div>
2035
+
2036
+ <p-confirmDialog />
2037
+ <p-toast />
2038
+ `,
2039
+ }]
2040
+ }] });
2041
+
2042
+ var translationKeyList_page = /*#__PURE__*/Object.freeze({
2043
+ __proto__: null,
2044
+ TranslationKeyListPage: TranslationKeyListPage
2045
+ });
2046
+
2047
+ class TranslationKeyFormPage {
2048
+ router = inject(Router);
2253
2049
  route = inject(ActivatedRoute);
2254
2050
  languageService = inject(LanguageApiService);
2255
2051
  translationKeyService = inject(TranslationKeyApiService);
2256
2052
  translationService = inject(TranslationApiService);
2257
2053
  messageService = inject(MessageService);
2258
- translateAdapter = inject(TRANSLATE_ADAPTER, { optional: true });
2054
+ translateAdapter = inject(TRANSLATE_ADAPTER, {
2055
+ optional: true,
2056
+ });
2259
2057
  destroyRef = inject(DestroyRef);
2260
2058
  routeParams = toSignal(this.route.paramMap);
2261
2059
  loadTriggered = false;
@@ -2266,8 +2064,8 @@ class TranslationKeyFormPage {
2266
2064
  languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
2267
2065
  modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
2268
2066
  translations = signal([], ...(ngDevMode ? [{ debugName: "translations" }] : []));
2269
- translate(key) {
2270
- return this.translateAdapter?.translate(key) ?? key;
2067
+ translate(key, vars) {
2068
+ return this.translateAdapter?.translate(key, vars) ?? key;
2271
2069
  }
2272
2070
  moduleOptions = computed(() => this.modules().map((m) => ({ label: m, value: m })), ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
2273
2071
  formModel = signal({
@@ -2278,12 +2076,18 @@ class TranslationKeyFormPage {
2278
2076
  variables: '',
2279
2077
  }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
2280
2078
  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') });
2079
+ required(f.key, {
2080
+ message: this.translate('localization.validation.key.required'),
2081
+ });
2082
+ required(f.defaultMessage, {
2083
+ message: this.translate('localization.validation.default.message.required'),
2084
+ });
2283
2085
  });
2284
2086
  isFormValid = computed(() => {
2285
2087
  const model = this.formModel();
2286
- return model.key.trim().length > 0 && model.module.trim().length > 0 && model.defaultMessage.trim().length > 0;
2088
+ return (model.key.trim().length > 0 &&
2089
+ model.module.trim().length > 0 &&
2090
+ model.defaultMessage.trim().length > 0);
2287
2091
  }, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
2288
2092
  constructor() {
2289
2093
  effect(() => {
@@ -2303,7 +2107,11 @@ class TranslationKeyFormPage {
2303
2107
  loadInitialData() {
2304
2108
  this.isLoadingLanguages.set(true);
2305
2109
  forkJoin({
2306
- languages: this.languageService.getAll(),
2110
+ languages: from(this.languageService.getAll({
2111
+ pagination: { currentPage: 0, pageSize: 100 },
2112
+ filter: {},
2113
+ sort: { serial: 'ASC', name: 'ASC' },
2114
+ })),
2307
2115
  modules: this.translationKeyService.getModules(),
2308
2116
  })
2309
2117
  .pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isLoadingLanguages.set(false)))
@@ -2330,20 +2138,20 @@ class TranslationKeyFormPage {
2330
2138
  this.formModel.update((m) => ({ ...m, module: value ?? '' }));
2331
2139
  }
2332
2140
  getTranslationValue(languageId) {
2333
- return this.translations().find((t) => t.languageId === languageId)?.value ?? '';
2141
+ return (this.translations().find((t) => t.languageId === languageId)?.value ?? '');
2334
2142
  }
2335
2143
  setTranslationValue(languageId, value) {
2336
2144
  this.translations.update((list) => {
2337
2145
  const existing = list.find((t) => t.languageId === languageId);
2338
2146
  if (existing) {
2339
- return list.map((t) => (t.languageId === languageId ? { ...t, value } : t));
2147
+ return list.map((t) => t.languageId === languageId ? { ...t, value } : t);
2340
2148
  }
2341
2149
  return [...list, { languageId, value }];
2342
2150
  });
2343
2151
  }
2344
2152
  loadTranslationKey(id) {
2345
2153
  this.isSaving.set(true);
2346
- this.translationKeyService.getById(id)
2154
+ from(this.translationKeyService.findById(id))
2347
2155
  .pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
2348
2156
  .subscribe({
2349
2157
  next: (response) => {
@@ -2357,7 +2165,8 @@ class TranslationKeyFormPage {
2357
2165
  });
2358
2166
  }
2359
2167
  loadExistingTranslations(keyId) {
2360
- this.translationService.getByKeyId(keyId)
2168
+ this.translationService
2169
+ .getByKeyId(keyId)
2361
2170
  .pipe(takeUntilDestroyed(this.destroyRef))
2362
2171
  .subscribe({
2363
2172
  next: (response) => {
@@ -2371,7 +2180,11 @@ class TranslationKeyFormPage {
2371
2180
  existing.translationId = t.id;
2372
2181
  }
2373
2182
  else {
2374
- updated.push({ languageId: t.languageId, value: t.value, translationId: t.id });
2183
+ updated.push({
2184
+ languageId: t.languageId,
2185
+ value: t.value,
2186
+ translationId: t.id,
2187
+ });
2375
2188
  }
2376
2189
  });
2377
2190
  return updated;
@@ -2413,12 +2226,12 @@ class TranslationKeyFormPage {
2413
2226
  description: model.description || undefined,
2414
2227
  variables: variables.length > 0 ? variables : undefined,
2415
2228
  };
2416
- this.translationKeyService.create(createDto)
2229
+ from(this.translationKeyService.insert(createDto))
2417
2230
  .pipe(takeUntilDestroyed(this.destroyRef))
2418
2231
  .subscribe({
2419
2232
  next: (response) => {
2420
2233
  if (response.success && response.data) {
2421
- this.saveTranslations(response.data.id);
2234
+ this.saveTranslations(response.data.id, response.messageKey, response.messageVariables);
2422
2235
  }
2423
2236
  else {
2424
2237
  this.isSaving.set(false);
@@ -2436,12 +2249,12 @@ class TranslationKeyFormPage {
2436
2249
  description: model.description || undefined,
2437
2250
  variables: variables.length > 0 ? variables : undefined,
2438
2251
  };
2439
- this.translationKeyService.update(updateDto)
2252
+ from(this.translationKeyService.update(updateDto))
2440
2253
  .pipe(takeUntilDestroyed(this.destroyRef))
2441
2254
  .subscribe({
2442
2255
  next: (response) => {
2443
2256
  if (response.success) {
2444
- this.saveTranslations(this.existingKey().id);
2257
+ this.saveTranslations(this.existingKey().id, response.messageKey, response.messageVariables);
2445
2258
  }
2446
2259
  else {
2447
2260
  this.isSaving.set(false);
@@ -2450,7 +2263,7 @@ class TranslationKeyFormPage {
2450
2263
  error: () => this.isSaving.set(false),
2451
2264
  });
2452
2265
  }
2453
- saveTranslations(keyId) {
2266
+ saveTranslations(keyId, messageKey, messageVariables) {
2454
2267
  const translationsToSave = this.translations()
2455
2268
  .filter((t) => t.value?.trim())
2456
2269
  .map((t) => ({
@@ -2461,21 +2274,22 @@ class TranslationKeyFormPage {
2461
2274
  isVerified: false,
2462
2275
  }));
2463
2276
  if (translationsToSave.length === 0) {
2464
- this.onSaveSuccess();
2277
+ this.onSaveSuccess(messageKey, messageVariables);
2465
2278
  return;
2466
2279
  }
2467
- this.translationService.bulkUpdate(translationsToSave)
2280
+ this.translationService
2281
+ .bulkUpdate(translationsToSave)
2468
2282
  .pipe(takeUntilDestroyed(this.destroyRef))
2469
2283
  .subscribe({
2470
- next: () => this.onSaveSuccess(),
2471
- error: () => this.onSaveSuccess(),
2284
+ next: () => this.onSaveSuccess(messageKey, messageVariables),
2285
+ error: () => this.onSaveSuccess(messageKey, messageVariables),
2472
2286
  });
2473
2287
  }
2474
- onSaveSuccess() {
2288
+ onSaveSuccess(messageKey, messageVariables) {
2475
2289
  this.messageService.add({
2476
2290
  severity: 'success',
2477
2291
  summary: this.translate('shared.success'),
2478
- detail: this.translate(this.isEditMode() ? 'localization.translation.key.update.success' : 'localization.translation.key.create.success'),
2292
+ detail: messageKey ? this.translate(messageKey, messageVariables) : '',
2479
2293
  });
2480
2294
  this.isSaving.set(false);
2481
2295
  this.router.navigate(['/localization/keys']);
@@ -2483,126 +2297,17 @@ class TranslationKeyFormPage {
2483
2297
  onCancel() {
2484
2298
  this.router.navigate(['/localization/keys']);
2485
2299
  }
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: `
2300
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyFormPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
2301
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: TranslationKeyFormPage, isStandalone: true, selector: "lib-translation-key-form-page", providers: [MessageService], ngImport: i0, template: `
2601
2302
  <p-card>
2602
2303
  <ng-template #header>
2603
2304
  <div class="flex justify-between items-center p-4">
2604
2305
  <h2 class="text-xl font-semibold m-0">
2605
- {{ isEditMode() ? ('localization.key.edit' | translate) : ('localization.key.create' | translate) }}
2306
+ {{
2307
+ isEditMode()
2308
+ ? ('localization.key.edit' | translate)
2309
+ : ('localization.key.new' | translate)
2310
+ }}
2606
2311
  </h2>
2607
2312
  </div>
2608
2313
  </ng-template>
@@ -2610,71 +2315,98 @@ class TranslationKeyFormPage {
2610
2315
  <form (ngSubmit)="onSubmit()" class="flex flex-col gap-6">
2611
2316
  <!-- Key Info Section -->
2612
2317
  <div class="p-4 surface-ground rounded-lg">
2613
- <h4 class="font-semibold mt-0 mb-4">{{ 'localization.key.about' | translate }}</h4>
2318
+ <h4 class="font-semibold mt-0 mb-4">
2319
+ {{ 'localization.key.about' | translate }}
2320
+ </h4>
2614
2321
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2615
2322
  <!-- Key Name -->
2616
2323
  <div class="flex flex-col gap-2">
2617
- <label for="key" class="font-medium">{{ 'localization.key.name' | translate }} *</label>
2324
+ <label for="key" class="font-medium"
2325
+ >{{ 'localization.key.name' | translate }} *</label
2326
+ >
2618
2327
  <input
2619
2328
  pInputText
2620
2329
  id="key"
2621
2330
  [formField]="formTree.key"
2622
- [placeholder]="'localization.placeholder.key.name' | translate" />
2331
+ [placeholder]="'localization.placeholder.key.name' | translate"
2332
+ />
2623
2333
  </div>
2624
2334
 
2625
2335
  <!-- Module -->
2626
2336
  <div class="flex flex-col gap-2">
2627
- <label for="module" class="font-medium">{{ 'localization.key.module' | translate }} *</label>
2337
+ <label for="module" class="font-medium"
2338
+ >{{ 'localization.key.module' | translate }} *</label
2339
+ >
2628
2340
  <p-select
2629
2341
  id="module"
2630
2342
  [ngModel]="formModel().module"
2631
2343
  (ngModelChange)="updateModule($event)"
2632
- [ngModelOptions]="{standalone: true}"
2344
+ [ngModelOptions]="{ standalone: true }"
2633
2345
  [options]="moduleOptions()"
2634
2346
  optionLabel="label"
2635
2347
  optionValue="value"
2636
2348
  [editable]="true"
2637
2349
  [placeholder]="'localization.key.select.module' | translate"
2638
- class="w-full" />
2350
+ class="w-full"
2351
+ />
2639
2352
  </div>
2640
2353
 
2641
2354
  <!-- Default Message -->
2642
2355
  <div class="flex flex-col gap-2 md:col-span-2">
2643
- <label for="defaultMessage" class="font-medium">{{ 'localization.key.default.message' | translate }} *</label>
2356
+ <label for="defaultMessage" class="font-medium"
2357
+ >{{ 'localization.key.default.message' | translate }} *</label
2358
+ >
2644
2359
  <textarea
2645
2360
  pInputTextarea
2646
2361
  id="defaultMessage"
2647
2362
  [formField]="formTree.defaultMessage"
2648
2363
  [rows]="2"
2649
- [placeholder]="'localization.placeholder.default.message' | translate"></textarea>
2364
+ [placeholder]="
2365
+ 'localization.placeholder.default.message' | translate
2366
+ "
2367
+ ></textarea>
2650
2368
  </div>
2651
2369
 
2652
2370
  <!-- Description -->
2653
2371
  <div class="flex flex-col gap-2 md:col-span-2">
2654
- <label for="description" class="font-medium">{{ 'localization.key.description' | translate }}</label>
2372
+ <label for="description" class="font-medium">{{
2373
+ 'localization.key.description' | translate
2374
+ }}</label>
2655
2375
  <input
2656
2376
  pInputText
2657
2377
  id="description"
2658
2378
  [formField]="formTree.description"
2659
- [placeholder]="'localization.placeholder.key.description' | translate" />
2379
+ [placeholder]="
2380
+ 'localization.placeholder.key.description' | translate
2381
+ "
2382
+ />
2660
2383
  </div>
2661
2384
 
2662
2385
  <!-- Variables -->
2663
2386
  <div class="flex flex-col gap-2 md:col-span-2">
2664
- <label for="variables" class="font-medium">{{ 'localization.key.variables' | translate }}</label>
2387
+ <label for="variables" class="font-medium">{{
2388
+ 'localization.key.variables' | translate
2389
+ }}</label>
2665
2390
  <input
2666
2391
  pInputText
2667
2392
  id="variables"
2668
2393
  [formField]="formTree.variables"
2669
- [placeholder]="'localization.key.variables.placeholder' | translate" />
2670
- <small class="text-muted-color">{{ 'localization.key.variables.hint' | translate }}</small>
2394
+ [placeholder]="
2395
+ 'localization.key.variables.placeholder' | translate
2396
+ "
2397
+ />
2398
+ <small class="text-muted-color">{{
2399
+ 'localization.key.variables.hint' | translate
2400
+ }}</small>
2671
2401
  </div>
2672
2402
  </div>
2673
2403
  </div>
2674
2404
 
2675
2405
  <!-- Translations Section -->
2676
2406
  <div class="p-4 surface-ground rounded-lg">
2677
- <h4 class="font-semibold mt-0 mb-4">{{ 'localization.key.translations.section' | translate }}</h4>
2407
+ <h4 class="font-semibold mt-0 mb-4">
2408
+ {{ 'localization.key.translations.section' | translate }}
2409
+ </h4>
2678
2410
  @if (isLoadingLanguages()) {
2679
2411
  <div class="flex justify-center py-4">
2680
2412
  <p-progressSpinner strokeWidth="4" />
@@ -2691,18 +2423,28 @@ class TranslationKeyFormPage {
2691
2423
  <label class="font-medium">
2692
2424
  {{ lang.name }}
2693
2425
  @if (lang.nativeName && lang.nativeName !== lang.name) {
2694
- <span class="text-muted-color">({{ lang.nativeName }})</span>
2426
+ <span class="text-muted-color"
2427
+ >({{ lang.nativeName }})</span
2428
+ >
2695
2429
  }
2696
2430
  </label>
2697
- <p-tag [value]="lang.code" severity="secondary" class="uppercase" />
2431
+ <p-tag
2432
+ [value]="lang.code"
2433
+ severity="secondary"
2434
+ class="uppercase"
2435
+ />
2698
2436
  </div>
2699
2437
  <textarea
2700
2438
  pInputTextarea
2701
2439
  [ngModel]="getTranslationValue(lang.id)"
2702
2440
  (ngModelChange)="setTranslationValue(lang.id, $event)"
2703
- [ngModelOptions]="{standalone: true}"
2441
+ [ngModelOptions]="{ standalone: true }"
2704
2442
  [rows]="2"
2705
- [placeholder]="formModel().defaultMessage || ('localization.key.enter.translation' | translate)"></textarea>
2443
+ [placeholder]="
2444
+ formModel().defaultMessage ||
2445
+ ('localization.key.enter.translation' | translate)
2446
+ "
2447
+ ></textarea>
2706
2448
  </div>
2707
2449
  }
2708
2450
  </div>
@@ -2715,582 +2457,214 @@ class TranslationKeyFormPage {
2715
2457
  [label]="'shared.cancel' | translate"
2716
2458
  severity="secondary"
2717
2459
  [outlined]="true"
2718
- (onClick)="onCancel()" />
2460
+ (onClick)="onCancel()"
2461
+ />
2719
2462
  <p-button
2720
- [label]="isEditMode() ? ('shared.update' | translate) : ('shared.create' | translate)"
2463
+ [label]="
2464
+ isEditMode()
2465
+ ? ('shared.update' | translate)
2466
+ : ('shared.create' | translate)
2467
+ "
2721
2468
  type="submit"
2722
2469
  [loading]="isSaving()"
2723
- [disabled]="!isFormValid() || isSaving()" />
2470
+ [disabled]="!isFormValid() || isSaving()"
2471
+ />
2724
2472
  </div>
2725
2473
  </form>
2726
2474
  </p-card>
2727
2475
 
2728
2476
  <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 });
2477
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: i7.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i9.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3122
2478
  }
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
- />
2479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyFormPage, decorators: [{
2480
+ type: Component,
2481
+ args: [{
2482
+ selector: 'lib-translation-key-form-page',
2483
+ imports: [AngularModule, PrimeModule, FormsModule, FormField, TranslatePipe],
2484
+ providers: [MessageService],
2485
+ template: `
2486
+ <p-card>
2487
+ <ng-template #header>
2488
+ <div class="flex justify-between items-center p-4">
2489
+ <h2 class="text-xl font-semibold m-0">
2490
+ {{
2491
+ isEditMode()
2492
+ ? ('localization.key.edit' | translate)
2493
+ : ('localization.key.new' | translate)
2494
+ }}
2495
+ </h2>
3141
2496
  </div>
3142
- </div>
2497
+ </ng-template>
3143
2498
 
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>
2499
+ <form (ngSubmit)="onSubmit()" class="flex flex-col gap-6">
2500
+ <!-- Key Info Section -->
2501
+ <div class="p-4 surface-ground rounded-lg">
2502
+ <h4 class="font-semibold mt-0 mb-4">
2503
+ {{ 'localization.key.about' | translate }}
2504
+ </h4>
2505
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2506
+ <!-- Key Name -->
2507
+ <div class="flex flex-col gap-2">
2508
+ <label for="key" class="font-medium"
2509
+ >{{ 'localization.key.name' | translate }} *</label
2510
+ >
2511
+ <input
2512
+ pInputText
2513
+ id="key"
2514
+ [formField]="formTree.key"
2515
+ [placeholder]="'localization.placeholder.key.name' | translate"
2516
+ />
2517
+ </div>
3186
2518
 
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>
2519
+ <!-- Module -->
2520
+ <div class="flex flex-col gap-2">
2521
+ <label for="module" class="font-medium"
2522
+ >{{ 'localization.key.module' | translate }} *</label
2523
+ >
2524
+ <p-select
2525
+ id="module"
2526
+ [ngModel]="formModel().module"
2527
+ (ngModelChange)="updateModule($event)"
2528
+ [ngModelOptions]="{ standalone: true }"
2529
+ [options]="moduleOptions()"
2530
+ optionLabel="label"
2531
+ optionValue="value"
2532
+ [editable]="true"
2533
+ [placeholder]="'localization.key.select.module' | translate"
2534
+ class="w-full"
2535
+ />
2536
+ </div>
2537
+
2538
+ <!-- Default Message -->
2539
+ <div class="flex flex-col gap-2 md:col-span-2">
2540
+ <label for="defaultMessage" class="font-medium"
2541
+ >{{ 'localization.key.default.message' | translate }} *</label
2542
+ >
2543
+ <textarea
2544
+ pInputTextarea
2545
+ id="defaultMessage"
2546
+ [formField]="formTree.defaultMessage"
2547
+ [rows]="2"
2548
+ [placeholder]="
2549
+ 'localization.placeholder.default.message' | translate
2550
+ "
2551
+ ></textarea>
2552
+ </div>
2553
+
2554
+ <!-- Description -->
2555
+ <div class="flex flex-col gap-2 md:col-span-2">
2556
+ <label for="description" class="font-medium">{{
2557
+ 'localization.key.description' | translate
2558
+ }}</label>
2559
+ <input
2560
+ pInputText
2561
+ id="description"
2562
+ [formField]="formTree.description"
2563
+ [placeholder]="
2564
+ 'localization.placeholder.key.description' | translate
2565
+ "
2566
+ />
2567
+ </div>
2568
+
2569
+ <!-- Variables -->
2570
+ <div class="flex flex-col gap-2 md:col-span-2">
2571
+ <label for="variables" class="font-medium">{{
2572
+ 'localization.key.variables' | translate
2573
+ }}</label>
2574
+ <input
2575
+ pInputText
2576
+ id="variables"
2577
+ [formField]="formTree.variables"
2578
+ [placeholder]="
2579
+ 'localization.key.variables.placeholder' | translate
2580
+ "
2581
+ />
2582
+ <small class="text-muted-color">{{
2583
+ 'localization.key.variables.hint' | translate
2584
+ }}</small>
2585
+ </div>
2586
+ </div>
3198
2587
  </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
2588
 
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>
2589
+ <!-- Translations Section -->
2590
+ <div class="p-4 surface-ground rounded-lg">
2591
+ <h4 class="font-semibold mt-0 mb-4">
2592
+ {{ 'localization.key.translations.section' | translate }}
2593
+ </h4>
2594
+ @if (isLoadingLanguages()) {
2595
+ <div class="flex justify-center py-4">
2596
+ <p-progressSpinner strokeWidth="4" />
2597
+ </div>
2598
+ } @else if (languages().length === 0) {
2599
+ <p class="text-muted-color text-center py-4">
2600
+ {{ 'localization.key.no.languages' | translate }}
2601
+ </p>
2602
+ } @else {
2603
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
2604
+ @for (lang of languages(); track lang.id) {
2605
+ <div class="flex flex-col gap-2">
2606
+ <div class="flex justify-between items-center">
2607
+ <label class="font-medium">
2608
+ {{ lang.name }}
2609
+ @if (lang.nativeName && lang.nativeName !== lang.name) {
2610
+ <span class="text-muted-color"
2611
+ >({{ lang.nativeName }})</span
2612
+ >
2613
+ }
2614
+ </label>
2615
+ <p-tag
2616
+ [value]="lang.code"
2617
+ severity="secondary"
2618
+ class="uppercase"
2619
+ />
2620
+ </div>
2621
+ <textarea
2622
+ pInputTextarea
2623
+ [ngModel]="getTranslationValue(lang.id)"
2624
+ (ngModelChange)="setTranslationValue(lang.id, $event)"
2625
+ [ngModelOptions]="{ standalone: true }"
2626
+ [rows]="2"
2627
+ [placeholder]="
2628
+ formModel().defaultMessage ||
2629
+ ('localization.key.enter.translation' | translate)
2630
+ "
2631
+ ></textarea>
2632
+ </div>
2633
+ }
2634
+ </div>
3273
2635
  }
3274
2636
  </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>
2637
+
2638
+ <!-- Actions -->
2639
+ <div class="flex justify-end gap-4 pt-4">
2640
+ <p-button
2641
+ [label]="'shared.cancel' | translate"
2642
+ severity="secondary"
2643
+ [outlined]="true"
2644
+ (onClick)="onCancel()"
2645
+ />
2646
+ <p-button
2647
+ [label]="
2648
+ isEditMode()
2649
+ ? ('shared.update' | translate)
2650
+ : ('shared.create' | translate)
2651
+ "
2652
+ type="submit"
2653
+ [loading]="isSaving()"
2654
+ [disabled]="!isFormValid() || isSaving()"
2655
+ />
2656
+ </div>
2657
+ </form>
2658
+ </p-card>
3284
2659
 
3285
2660
  <p-toast />
3286
2661
  `,
3287
- }]
3288
- }], null, null); })();
3289
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TranslationListPage, { className: "TranslationListPage", filePath: "pages/translation-list/translation-list.page.ts", lineNumber: 193 }); })();
2662
+ }]
2663
+ }], ctorParameters: () => [] });
3290
2664
 
3291
- var translationList_page = /*#__PURE__*/Object.freeze({
2665
+ var translationKeyForm_page = /*#__PURE__*/Object.freeze({
3292
2666
  __proto__: null,
3293
- TranslationListPage: TranslationListPage
2667
+ TranslationKeyFormPage: TranslationKeyFormPage
3294
2668
  });
3295
2669
 
3296
2670
  // Interfaces
@@ -3299,5 +2673,5 @@ var translationList_page = /*#__PURE__*/Object.freeze({
3299
2673
  * Generated bundle index. Do not edit.
3300
2674
  */
3301
2675
 
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 };
2676
+ export { LOCALIZATION_CONFIG, LOCALIZATION_MESSAGES, LOCALIZATION_ROUTES, LanguageApiService, LanguageFormPage, LanguageListPage, LanguageSelectorComponent, LocalizationApiService, LocalizationContainerPage, LocalizationInitializerService, LocalizationStateService, STORAGE_KEYS, TranslateService, TranslationApiService, TranslationKeyApiService, TranslationKeyFormPage, TranslationKeyListPage, TranslationLoaderService, getLocalizationConfig, provideLocalization };
3303
2677
  //# sourceMappingURL=flusys-ng-localization.mjs.map