turbogui-angular 17.0.0 → 18.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.
- package/fesm2022/turbogui-angular.mjs +264 -86
- package/fesm2022/turbogui-angular.mjs.map +1 -1
- package/main/controller/dialog.service.d.ts +10 -8
- package/main/controller/dialog.service.d.ts.map +1 -1
- package/main/controller/locales.service.d.ts +16 -3
- package/main/controller/locales.service.d.ts.map +1 -1
- package/main/controller/router-base.service.d.ts +93 -0
- package/main/controller/router-base.service.d.ts.map +1 -0
- package/main/model/classes/View.d.ts +19 -8
- package/main/model/classes/View.d.ts.map +1 -1
- package/main/view/components/button-container/button-container.component.d.ts +1 -0
- package/main/view/components/button-container/button-container.component.d.ts.map +1 -1
- package/package.json +6 -6
- package/public_api.d.ts +1 -0
- package/public_api.d.ts.map +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { EventEmitter, Output, Directive, HostListener, NgModule, inject, Injectable, Component, Inject, HostBinding, Input } from '@angular/core';
|
|
3
|
-
import { Subject } from 'rxjs';
|
|
3
|
+
import { Subject, BehaviorSubject } from 'rxjs';
|
|
4
4
|
import { ArrayUtils, NumericUtils, HTTPManager, StringUtils, HTTPManagerGetRequest, HTTPManagerPostRequest, BrowserManager, ConversionUtils } from 'turbocommons-ts';
|
|
5
5
|
import * as i1 from '@angular/material/dialog';
|
|
6
6
|
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
@@ -14,6 +14,10 @@ import * as i2$1 from '@angular/material/datepicker';
|
|
|
14
14
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
15
15
|
import { MatNativeDateModule } from '@angular/material/core';
|
|
16
16
|
import * as i1$1 from '@angular/material/snack-bar';
|
|
17
|
+
import * as i1$2 from '@angular/router';
|
|
18
|
+
import { NavigationEnd } from '@angular/router';
|
|
19
|
+
import { filter } from 'rxjs/operators';
|
|
20
|
+
import * as i2$2 from '@angular/platform-browser';
|
|
17
21
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
18
22
|
import * as i4 from '@angular/material/input';
|
|
19
23
|
import { MatInputModule } from '@angular/material/input';
|
|
@@ -450,7 +454,7 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
450
454
|
return value;
|
|
451
455
|
}
|
|
452
456
|
/**
|
|
453
|
-
* Defines the behaviour for
|
|
457
|
+
* Defines the behaviour for t(), tStartCase(), etc... methods when a key is not found on
|
|
454
458
|
* a bundle or the bundle does not exist
|
|
455
459
|
*
|
|
456
460
|
* If missingKeyFormat is an empty string, all missing keys will return an empty value (not recommended)
|
|
@@ -476,6 +480,43 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
476
480
|
getMissingKeyFormat() {
|
|
477
481
|
return this._missingKeyFormat;
|
|
478
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Initializes the translation system by loading and parsing bundle files from the specified JSON object.
|
|
485
|
+
* After the method finishes, the class will contain all the translation data and will be ready to translate any provided key.
|
|
486
|
+
*
|
|
487
|
+
* @param translations A JSON object containing the translation data. The structure must be as follows:
|
|
488
|
+
* { library_name: { bundle_name: { locale_code: { key1: "translation1", key2: "translation2" } } } ... }
|
|
489
|
+
*
|
|
490
|
+
* @param locales An array of locale codes (e.g., ['en_US', 'es_ES', 'fr_FR']) to load into this class. The order of this array
|
|
491
|
+
* will determine the translation priority
|
|
492
|
+
*
|
|
493
|
+
* @return True if the translations get correctly loaded. Any unsuccessful initialization will throw an exception
|
|
494
|
+
*/
|
|
495
|
+
initializeFromJson(translations, locales) {
|
|
496
|
+
this._isInitialized = false;
|
|
497
|
+
// Validate received locales are correct
|
|
498
|
+
for (const locale of locales) {
|
|
499
|
+
this._validateLocaleString(locale);
|
|
500
|
+
}
|
|
501
|
+
// Validate the translations object follows the right structure
|
|
502
|
+
let isTranslationsValid = false;
|
|
503
|
+
for (const library in translations) {
|
|
504
|
+
for (const bundle in translations[library]) {
|
|
505
|
+
for (const locale in translations[library][bundle]) {
|
|
506
|
+
this._validateLocaleString(locale);
|
|
507
|
+
isTranslationsValid = true;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (!isTranslationsValid) {
|
|
512
|
+
throw new Error('translations must be a non empty object with the structure: { library: { bundle: { xx_XX: { key: translation } } } }');
|
|
513
|
+
}
|
|
514
|
+
this._loadedTranslations = translations;
|
|
515
|
+
this._locales = locales;
|
|
516
|
+
this._languages = locales.map((l) => l.substring(0, 2));
|
|
517
|
+
this._cacheHashBaseString = this._wildCardsFormat + this._missingKeyFormat + this._locales[0];
|
|
518
|
+
return this._isInitialized = true;
|
|
519
|
+
}
|
|
479
520
|
/**
|
|
480
521
|
* Initializes the translation system by loading and parsing bundle files from the specified translations path.
|
|
481
522
|
* After the promise finishes, the class will contain all the translation data and will be ready to translate any
|
|
@@ -489,14 +530,9 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
489
530
|
*
|
|
490
531
|
* @return A promise that will resolve if the translations get correctly loaded, or reject with an error if load fails
|
|
491
532
|
*/
|
|
492
|
-
|
|
533
|
+
initializeFromUrl(translationsPath, locales, parameters) {
|
|
493
534
|
this._isInitialized = false;
|
|
494
|
-
|
|
495
|
-
// Validate received locales are correct
|
|
496
|
-
for (const locale of locales) {
|
|
497
|
-
this._validateLocaleString(locale);
|
|
498
|
-
}
|
|
499
|
-
let translationsFullPath = translationsPath + '/' + locales.join('-') + '/' + parameters.join('/');
|
|
535
|
+
const translationsFullPath = translationsPath + '/' + locales.join('-') + '/' + parameters.join('/');
|
|
500
536
|
return new Promise((resolve, reject) => {
|
|
501
537
|
fetch(translationsFullPath).then(response => {
|
|
502
538
|
if (!response.ok) {
|
|
@@ -504,11 +540,7 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
504
540
|
}
|
|
505
541
|
return response.json();
|
|
506
542
|
}).then(data => {
|
|
507
|
-
this.
|
|
508
|
-
this._isInitialized = true;
|
|
509
|
-
this._locales = locales;
|
|
510
|
-
this._languages = locales.map((l) => l.substring(0, 2));
|
|
511
|
-
this._cacheHashBaseString = this._wildCardsFormat + this._missingKeyFormat + this._locales[0];
|
|
543
|
+
this.initializeFromJson(data, locales);
|
|
512
544
|
resolve(undefined);
|
|
513
545
|
}).catch(error => {
|
|
514
546
|
reject(new Error(`ERROR LOADING LOCALES FROM: ${translationsFullPath}\n` + error));
|
|
@@ -526,7 +558,7 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
526
558
|
*/
|
|
527
559
|
_validateInitialized() {
|
|
528
560
|
if (!this._isInitialized) {
|
|
529
|
-
throw new Error('
|
|
561
|
+
throw new Error('Translation service not initialized');
|
|
530
562
|
}
|
|
531
563
|
}
|
|
532
564
|
/**
|
|
@@ -609,7 +641,7 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
609
641
|
}
|
|
610
642
|
// Check if an exception needs to be thrown if the specified key is not found on this bundle
|
|
611
643
|
if (this._missingKeyFormat.includes('$exception')) {
|
|
612
|
-
throw new Error(`key <${key}> not found on
|
|
644
|
+
throw new Error(`Translation key <${key}> not found on <${bundlePath}>`);
|
|
613
645
|
}
|
|
614
646
|
this._keyValuesCache[cacheKey] = this._replace(this._missingKeyFormat, '$key', key);
|
|
615
647
|
}
|
|
@@ -667,7 +699,7 @@ class LocalesService extends SingletoneStrictClass {
|
|
|
667
699
|
* list for a translated text. If missing, the next one will be used, and so. This list is constructed after initialize
|
|
668
700
|
* methods is called.
|
|
669
701
|
*
|
|
670
|
-
* @example: After loading the following list of locales ['en_US', 'es_ES', 'fr_FR'] if we call
|
|
702
|
+
* @example: After loading the following list of locales ['en_US', 'es_ES', 'fr_FR'] if we call t('HELLO', 'lib1/greetings')
|
|
671
703
|
* the localization manager will try to locate the en_US value for the HELLO tag on the greetings bundle for the library lib1.
|
|
672
704
|
* If the tag is not found for the specified locale and bundle, the same search will be performed for the es_ES locale, and so, till a
|
|
673
705
|
* value is found or no more locales are defined.
|
|
@@ -1228,22 +1260,29 @@ class DialogService extends SingletoneStrictClass {
|
|
|
1228
1260
|
* @param action If not empty, the text to place on the snackbar confirmation button
|
|
1229
1261
|
* @param actionCallback A method to execute once the user clicks into the action button.
|
|
1230
1262
|
*
|
|
1231
|
-
* @return
|
|
1263
|
+
* @return A promise that will be resolved once the snackbar is closed.
|
|
1232
1264
|
*/
|
|
1233
|
-
addSnackBar(config, message, action = ''
|
|
1265
|
+
addSnackBar(config, message, action = '') {
|
|
1234
1266
|
if (!this._isEnabled) {
|
|
1235
|
-
return;
|
|
1267
|
+
return Promise.reject(new Error('Dialog service is disabled'));
|
|
1236
1268
|
}
|
|
1237
1269
|
if (this._isShowingSnackBar) {
|
|
1238
1270
|
throw new Error('Trying to show a snackbar while another one is still visible');
|
|
1239
1271
|
}
|
|
1240
1272
|
this._isShowingSnackBar = true;
|
|
1241
|
-
|
|
1242
|
-
|
|
1273
|
+
return new Promise((resolve) => {
|
|
1274
|
+
const snackBarRef = this.matSnackBar.open(message, action === '' ? undefined : action, config);
|
|
1275
|
+
// Handle action button click
|
|
1243
1276
|
snackBarRef.onAction().subscribe(() => {
|
|
1244
|
-
|
|
1277
|
+
this._isShowingSnackBar = false;
|
|
1278
|
+
resolve(true);
|
|
1245
1279
|
});
|
|
1246
|
-
|
|
1280
|
+
// Handle dismiss
|
|
1281
|
+
snackBarRef.afterDismissed().subscribe(() => {
|
|
1282
|
+
this._isShowingSnackBar = false;
|
|
1283
|
+
resolve(false);
|
|
1284
|
+
});
|
|
1285
|
+
});
|
|
1247
1286
|
}
|
|
1248
1287
|
/**
|
|
1249
1288
|
* Tells if the application is currently showing a snackbar or not
|
|
@@ -1286,60 +1325,61 @@ class DialogService extends SingletoneStrictClass {
|
|
|
1286
1325
|
* - viewContainerRef: This is important if we want to propagate providers from a parent component to this dialog. We must specify
|
|
1287
1326
|
* this reference to make sure the same services injected on the parent are available too at the child dialog
|
|
1288
1327
|
*
|
|
1289
|
-
* @
|
|
1290
|
-
*
|
|
1328
|
+
* @return A promise that will be resolved once the dialog is closed.
|
|
1329
|
+
* The promise will receive a selection object with two properties which will correspond to the index and value from the options
|
|
1330
|
+
* array that's selected by the user. If no option selected, index will be -1 and value null
|
|
1291
1331
|
*/
|
|
1292
|
-
addDialog(dialogComponentClass, properties
|
|
1332
|
+
addDialog(dialogComponentClass, properties) {
|
|
1293
1333
|
if (!this._isEnabled) {
|
|
1294
|
-
return;
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
const dialogRef = this.matDialog.open(dialogComponentClass, {
|
|
1314
|
-
width: properties.width ?? "50%",
|
|
1315
|
-
maxWidth: properties.maxWidth ?? "96vw",
|
|
1316
|
-
disableClose: properties.modal,
|
|
1317
|
-
autoFocus: false,
|
|
1318
|
-
closeOnNavigation: !properties.modal,
|
|
1319
|
-
viewContainerRef: properties.viewContainerRef,
|
|
1320
|
-
data: { texts: properties.texts, options: properties.options, data: properties.data }
|
|
1321
|
-
});
|
|
1322
|
-
// Assign the dialog ID only if specifically set on properties
|
|
1323
|
-
if (properties.id && properties.id !== undefined) {
|
|
1324
|
-
dialogRef.id = properties.id;
|
|
1325
|
-
}
|
|
1326
|
-
this._activeDialogs.push(dialogHash);
|
|
1327
|
-
this._activeDialogInstances.push(dialogRef);
|
|
1328
|
-
dialogRef.beforeClosed().subscribe((selection) => {
|
|
1329
|
-
this._activeDialogs = ArrayUtils.removeElement(this._activeDialogs, dialogHash);
|
|
1330
|
-
this._activeDialogInstances = ArrayUtils.removeElement(this._activeDialogInstances, dialogRef);
|
|
1331
|
-
if (!properties.modal && selection === undefined) {
|
|
1332
|
-
selection = { index: -1 };
|
|
1334
|
+
return Promise.reject(new Error('Dialog service is disabled'));
|
|
1335
|
+
}
|
|
1336
|
+
return new Promise((resolve) => {
|
|
1337
|
+
// Set the default values for non specified properties
|
|
1338
|
+
properties.modal = properties.modal ?? true;
|
|
1339
|
+
properties.texts = properties.texts ?? [];
|
|
1340
|
+
properties.options = properties.options ?? [];
|
|
1341
|
+
properties.data = properties.data ?? {};
|
|
1342
|
+
// Generate a string to uniquely identify this dialog on the list of active dialogs
|
|
1343
|
+
// A dialog is considered as unique if the dialog id and texts are exactly the same. We do not take options into consideration
|
|
1344
|
+
// as there may be dialogs with a big amount of options available.
|
|
1345
|
+
let className = dialogComponentClass.DIALOG_CLASS_NAME;
|
|
1346
|
+
if (className === '') {
|
|
1347
|
+
throw new Error(`The static property DIALOG_CLASS_NAME is not defined or is empty for this dialog component (${dialogComponentClass})`);
|
|
1348
|
+
}
|
|
1349
|
+
const dialogHash = className + properties.texts.join('');
|
|
1350
|
+
// identical dialogs won't be allowed at the same time
|
|
1351
|
+
if (this._activeDialogs.includes(dialogHash)) {
|
|
1352
|
+
return resolve({ index: -1 });
|
|
1333
1353
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1354
|
+
const dialogRef = this.matDialog.open(dialogComponentClass, {
|
|
1355
|
+
width: properties.width ?? "50%",
|
|
1356
|
+
maxWidth: properties.maxWidth ?? "96vw",
|
|
1357
|
+
disableClose: properties.modal,
|
|
1358
|
+
autoFocus: false,
|
|
1359
|
+
closeOnNavigation: !properties.modal,
|
|
1360
|
+
viewContainerRef: properties.viewContainerRef,
|
|
1361
|
+
data: { texts: properties.texts, options: properties.options, data: properties.data }
|
|
1362
|
+
});
|
|
1363
|
+
// Assign the dialog ID only if specifically set on properties
|
|
1364
|
+
if (properties.id && properties.id !== undefined) {
|
|
1365
|
+
dialogRef.id = properties.id;
|
|
1336
1366
|
}
|
|
1337
|
-
|
|
1367
|
+
this._activeDialogs.push(dialogHash);
|
|
1368
|
+
this._activeDialogInstances.push(dialogRef);
|
|
1369
|
+
dialogRef.beforeClosed().subscribe((selection) => {
|
|
1370
|
+
this._activeDialogs = ArrayUtils.removeElement(this._activeDialogs, dialogHash);
|
|
1371
|
+
this._activeDialogInstances = ArrayUtils.removeElement(this._activeDialogInstances, dialogRef);
|
|
1372
|
+
if (!properties.modal && selection === undefined) {
|
|
1373
|
+
selection = { index: -1 };
|
|
1374
|
+
}
|
|
1375
|
+
else if (!NumericUtils.isInteger(selection.index)) {
|
|
1376
|
+
throw new Error(`closeDialog() expects index to be an integer`);
|
|
1377
|
+
}
|
|
1338
1378
|
if (selection.index >= 0 && selection.value === null) {
|
|
1339
1379
|
selection.value = properties.options[selection.index];
|
|
1340
1380
|
}
|
|
1341
|
-
|
|
1342
|
-
}
|
|
1381
|
+
resolve(selection);
|
|
1382
|
+
});
|
|
1343
1383
|
});
|
|
1344
1384
|
}
|
|
1345
1385
|
/**
|
|
@@ -1359,13 +1399,14 @@ class DialogService extends SingletoneStrictClass {
|
|
|
1359
1399
|
* - title: An optional dialog title
|
|
1360
1400
|
* - viewContainerRef: This is important to propagate providers from a parent component to this dialog. We must specify
|
|
1361
1401
|
* this reference to make sure the same services injected on the parent are available too at the child dialog
|
|
1362
|
-
*
|
|
1402
|
+
*
|
|
1403
|
+
* @returns A Promise that resolves to a Date() object selected by the user or null if no selection was made
|
|
1363
1404
|
*/
|
|
1364
|
-
addDateSelectionDialog(properties
|
|
1405
|
+
async addDateSelectionDialog(properties) {
|
|
1365
1406
|
if (!this._isEnabled) {
|
|
1366
|
-
return;
|
|
1407
|
+
return null;
|
|
1367
1408
|
}
|
|
1368
|
-
this.addDialog(DialogDateSelectionComponent, {
|
|
1409
|
+
const selection = await this.addDialog(DialogDateSelectionComponent, {
|
|
1369
1410
|
id: properties.id ?? undefined,
|
|
1370
1411
|
width: properties.width ?? "50%",
|
|
1371
1412
|
maxWidth: properties.maxWidth ?? "96vw",
|
|
@@ -1374,9 +1415,8 @@ class DialogService extends SingletoneStrictClass {
|
|
|
1374
1415
|
modal: properties.modal ?? false,
|
|
1375
1416
|
texts: [properties.title ?? ''],
|
|
1376
1417
|
viewContainerRef: properties.viewContainerRef
|
|
1377
|
-
}, (selection) => {
|
|
1378
|
-
callback(selection.index === -1 ? null : selection.value);
|
|
1379
1418
|
});
|
|
1419
|
+
return selection.index === -1 ? null : selection.value;
|
|
1380
1420
|
}
|
|
1381
1421
|
/**
|
|
1382
1422
|
* Force the removal of all the dialogs that are currently visible.
|
|
@@ -2025,6 +2065,132 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImpor
|
|
|
2025
2065
|
}]
|
|
2026
2066
|
}], ctorParameters: () => [{ type: DialogService }, { type: BrowserService }] });
|
|
2027
2067
|
|
|
2068
|
+
/**
|
|
2069
|
+
* TurboGUI is A library that helps with the most common and generic UI elements and functionalities
|
|
2070
|
+
*
|
|
2071
|
+
* Website : -> http://www.turbogui.org
|
|
2072
|
+
* License : -> Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License.
|
|
2073
|
+
* License Url : -> http://www.apache.org/licenses/LICENSE-2.0
|
|
2074
|
+
* CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com
|
|
2075
|
+
*/
|
|
2076
|
+
/**
|
|
2077
|
+
* Global service that helps with application routing and related functionalities.
|
|
2078
|
+
* It is defined as an abstract class so it must be extended in our application to be used.
|
|
2079
|
+
* We must declare a static array of routes that will be used to define the routes of the application.
|
|
2080
|
+
*/
|
|
2081
|
+
class RouterBaseService {
|
|
2082
|
+
constructor(router, titleService, ls) {
|
|
2083
|
+
this.router = router;
|
|
2084
|
+
this.titleService = titleService;
|
|
2085
|
+
this.ls = ls;
|
|
2086
|
+
/**
|
|
2087
|
+
* Indicates whether the title manager has been initialized.
|
|
2088
|
+
* This should only be done once, typically at application startup.
|
|
2089
|
+
*/
|
|
2090
|
+
this._isTitleManagerInitialized = false;
|
|
2091
|
+
/**
|
|
2092
|
+
* BehaviorSubject that holds the current route URL.
|
|
2093
|
+
* This allows components to reactively subscribe to route changes.
|
|
2094
|
+
*/
|
|
2095
|
+
this._currentRoute = new BehaviorSubject(this.router.url);
|
|
2096
|
+
// Initial update in case the service loads after the first NavigationEnd
|
|
2097
|
+
this._updateCurrentRoute();
|
|
2098
|
+
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Updates the current route URL in the BehaviorSubject.
|
|
2101
|
+
* This is called internally after each navigation event.
|
|
2102
|
+
*/
|
|
2103
|
+
_updateCurrentRoute() {
|
|
2104
|
+
this._currentRoute.next(this.router.url);
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Checks if the current route matches the specified route.
|
|
2108
|
+
*
|
|
2109
|
+
* @param route The route to check against the current route.
|
|
2110
|
+
*
|
|
2111
|
+
* @returns True if we are actually at the specified route, false otherwise.
|
|
2112
|
+
*/
|
|
2113
|
+
isRouteCurrent(route) {
|
|
2114
|
+
return this.getCurrentRoute() === '/' + route;
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* Gets the current value of the route URL synchronously.
|
|
2118
|
+
*/
|
|
2119
|
+
getCurrentRoute() {
|
|
2120
|
+
return this._currentRoute.getValue();
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Initializes the title management feature to automatically refresh the browser title based on the current
|
|
2124
|
+
* URL route. It Must be called once, typically at application startup
|
|
2125
|
+
*
|
|
2126
|
+
* To correctly translate the route title, We expect the route definitions to have the following properties:
|
|
2127
|
+
*
|
|
2128
|
+
* - titleKey: The key to be used to get the title from the translation bundle.
|
|
2129
|
+
* - titleBundle: The bundle to be used to get the title from the translation bundle.
|
|
2130
|
+
*
|
|
2131
|
+
* (Translations will be done using the LocalesService from this same library).
|
|
2132
|
+
*
|
|
2133
|
+
* Example of a Route using this feature:
|
|
2134
|
+
* // Home route
|
|
2135
|
+
* { path: '', component: HomePageComponent,
|
|
2136
|
+
* data: { titleKey: 'HOME', titleBundle: 'turbodepot/user-interface'} },
|
|
2137
|
+
*
|
|
2138
|
+
* @param prefix A text to be added before the computed title.
|
|
2139
|
+
* @param sufix A text to be added after the computed title.
|
|
2140
|
+
*/
|
|
2141
|
+
initializeAutoTranslateTitleByRoute(prefix = '', sufix = '') {
|
|
2142
|
+
if (this._isTitleManagerInitialized) {
|
|
2143
|
+
throw new Error('Title refresh from routes has already been initialized. Can only be done once.');
|
|
2144
|
+
}
|
|
2145
|
+
// Set initial title based on current route data immediately
|
|
2146
|
+
this.updateTitleFromCurrentRoute(prefix, sufix);
|
|
2147
|
+
// Subscribe to future navigation events
|
|
2148
|
+
this._routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
|
|
2149
|
+
this._updateCurrentRoute();
|
|
2150
|
+
this.updateTitleFromCurrentRoute(prefix, sufix);
|
|
2151
|
+
});
|
|
2152
|
+
this._isTitleManagerInitialized = true;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Aux method: Updates the browser title based on the current route's data properties.
|
|
2156
|
+
* This is called after each navigation event to ensure the title is always up-to-date.
|
|
2157
|
+
*
|
|
2158
|
+
* @param prefix A text to be added before the computed title.
|
|
2159
|
+
* @param sufix A text to be added after the computed title.
|
|
2160
|
+
*/
|
|
2161
|
+
updateTitleFromCurrentRoute(prefix, sufix) {
|
|
2162
|
+
let currentRoute = this.router.routerState.snapshot.root;
|
|
2163
|
+
while (currentRoute.firstChild) {
|
|
2164
|
+
currentRoute = currentRoute.firstChild;
|
|
2165
|
+
}
|
|
2166
|
+
const data = currentRoute.data;
|
|
2167
|
+
if (data['titleKey'] && data['titleBundle']) {
|
|
2168
|
+
this.titleService.setTitle(prefix + this.ls.t(data['titleKey'], data['titleBundle']) + sufix);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
/**
|
|
2172
|
+
* Navigates to the specified route.
|
|
2173
|
+
*
|
|
2174
|
+
* @param route The route to navigate to.
|
|
2175
|
+
*/
|
|
2176
|
+
navigateTo(route) {
|
|
2177
|
+
this.router.navigate(['/' + route]);
|
|
2178
|
+
}
|
|
2179
|
+
ngOnDestroy() {
|
|
2180
|
+
this._routerSubscription?.unsubscribe();
|
|
2181
|
+
// Clean up BehaviorSubject
|
|
2182
|
+
this._currentRoute.complete();
|
|
2183
|
+
}
|
|
2184
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: RouterBaseService, deps: [{ token: i1$2.Router }, { token: i2$2.Title }, { token: LocalesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2185
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: RouterBaseService, providedIn: 'root' }); }
|
|
2186
|
+
}
|
|
2187
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: RouterBaseService, decorators: [{
|
|
2188
|
+
type: Injectable,
|
|
2189
|
+
args: [{
|
|
2190
|
+
providedIn: 'root',
|
|
2191
|
+
}]
|
|
2192
|
+
}], ctorParameters: () => [{ type: i1$2.Router }, { type: i2$2.Title }, { type: LocalesService }] });
|
|
2193
|
+
|
|
2028
2194
|
/**
|
|
2029
2195
|
* TurboGUI is A library that helps with the most common and generic UI elements and functionalities
|
|
2030
2196
|
*
|
|
@@ -2557,6 +2723,7 @@ class ButtonContainerComponent extends ButtonBaseComponent {
|
|
|
2557
2723
|
super(...arguments);
|
|
2558
2724
|
/**
|
|
2559
2725
|
* This is used to attach the fade animation directly to this component so it fades in and out when created and removed from the app
|
|
2726
|
+
* TODO: THIS IS NOT A GOOD IDEA
|
|
2560
2727
|
*/
|
|
2561
2728
|
this.buttonFade = true;
|
|
2562
2729
|
}
|
|
@@ -2612,18 +2779,29 @@ class GUINotification {
|
|
|
2612
2779
|
* CopyRight : -> Copyright 2018 Edertone Advanded Solutions. https://www.edertone.com
|
|
2613
2780
|
*/
|
|
2614
2781
|
/**
|
|
2615
|
-
*
|
|
2616
|
-
*
|
|
2617
|
-
*
|
|
2782
|
+
* This is a base class that helps managing our application pages.
|
|
2783
|
+
* We should extend this class to create our application pages, as it forces us to set the viewContainerRef and the viewService,
|
|
2784
|
+
* which are both used when working with pages.
|
|
2785
|
+
*
|
|
2786
|
+
* IMPORTANT!!! View services are created and destroyed when the page is created and destroyed. It is vital to specify the view service
|
|
2787
|
+
* as a provider for the page to ensure that it will be created and destroyed when the view is created and destroyed.
|
|
2618
2788
|
*
|
|
2619
|
-
*
|
|
2620
|
-
*
|
|
2789
|
+
* Example:
|
|
2790
|
+
*
|
|
2791
|
+
* @Component({
|
|
2792
|
+
* ...
|
|
2793
|
+
* selector: 'app-my-view-page',
|
|
2794
|
+
* providers: [MyViewService]
|
|
2795
|
+
* ...
|
|
2796
|
+
*})
|
|
2621
2797
|
*/
|
|
2622
2798
|
class View {
|
|
2623
2799
|
/**
|
|
2624
|
-
* This constructor is specifically designed to force the
|
|
2625
|
-
*
|
|
2626
|
-
*
|
|
2800
|
+
* This constructor is specifically designed to force the following:
|
|
2801
|
+
*
|
|
2802
|
+
* - Set the viewContainerRef which will be automatically assigned to the respective view service.
|
|
2803
|
+
*
|
|
2804
|
+
* - If the view has no service, we can set it to null, but it is recommended to always use a service with a view, to store the view state and global methods
|
|
2627
2805
|
*/
|
|
2628
2806
|
constructor(viewContainerRef, viewService) {
|
|
2629
2807
|
this.viewContainerRef = viewContainerRef;
|
|
@@ -2764,5 +2942,5 @@ class ValidatorsPlus extends Validators {
|
|
|
2764
2942
|
* Generated bundle index. Do not edit.
|
|
2765
2943
|
*/
|
|
2766
2944
|
|
|
2767
|
-
export { AutoFocusOnDisplayDirective, AutoSelectTextOnFocusDirective, BrowserService, BusyStateBaseComponent, ButtonContainerComponent, ButtonImageComponent, DelayedMethodCallManager, DialogBaseComponent, DialogDateSelectionComponent, DialogErrorComponent, DialogMultipleOptionComponent, DialogService, DialogSingleInputComponent, DialogSingleOptionComponent, DialogSingleSelectionListComponent, DialogTwoOptionComponent, ElementCreatedDirective, ElementDestroyedDirective, FadeAnimationClass, GUINotification, GlobalErrorService, HTTPService, HTTPServiceGetRequest, HTTPServicePostRequest, LocalesService, NotificationService, SingletoneStrictClass, TurboApiCallerService, TurboGuiAngularModule, ValidatorsPlus, View, ViewService };
|
|
2945
|
+
export { AutoFocusOnDisplayDirective, AutoSelectTextOnFocusDirective, BrowserService, BusyStateBaseComponent, ButtonContainerComponent, ButtonImageComponent, DelayedMethodCallManager, DialogBaseComponent, DialogDateSelectionComponent, DialogErrorComponent, DialogMultipleOptionComponent, DialogService, DialogSingleInputComponent, DialogSingleOptionComponent, DialogSingleSelectionListComponent, DialogTwoOptionComponent, ElementCreatedDirective, ElementDestroyedDirective, FadeAnimationClass, GUINotification, GlobalErrorService, HTTPService, HTTPServiceGetRequest, HTTPServicePostRequest, LocalesService, NotificationService, RouterBaseService, SingletoneStrictClass, TurboApiCallerService, TurboGuiAngularModule, ValidatorsPlus, View, ViewService };
|
|
2768
2946
|
//# sourceMappingURL=turbogui-angular.mjs.map
|