@elite.framework/ng.core 2.0.30 → 2.0.32
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/abstracts/index.d.ts +1 -9
- package/fesm2022/elite.framework-ng.core-abstracts.mjs +1 -18
- package/fesm2022/elite.framework-ng.core-abstracts.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.core-interceptors.mjs +5 -5
- package/fesm2022/elite.framework-ng.core-interceptors.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.core-services.mjs +1118 -1118
- package/fesm2022/elite.framework-ng.core-services.mjs.map +1 -1
- package/package.json +1 -1
- package/services/index.d.ts +167 -167
|
@@ -4,15 +4,14 @@ import { throwError, catchError, map as map$1, Subject, BehaviorSubject, combine
|
|
|
4
4
|
import * as i1 from '@angular/common/http';
|
|
5
5
|
import { HttpParams, HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
6
6
|
import { CORE_OPTIONS, INCUDE_LOCALIZATION_RESOURCES_TOKEN, localizations$, DISABLE_PROJECT_NAME, OTHERS_GROUP, TENANT_KEY, TENANT_NOT_FOUND_BY_NAME, CHECK_AUTHENTICATION_STATE_FN_KEY, APP_INIT_ERROR_HANDLERS } from '@elite.framework/ng.core/tokens';
|
|
7
|
-
import { InternalStore,
|
|
7
|
+
import { InternalStore, createLocalizer, createLocalizerWithFallback, interpolate, isFunction, transformStringToArray, isPlainObject, createTreeFromList, BaseTreeNode, createGroupMap, pushValueTo, noop, getPathName, deepMerge, createTokenParser } from '@elite.framework/ng.core/utils';
|
|
8
8
|
import { map, switchMap, tap, take, filter, mapTo, takeUntil, catchError as catchError$1 } from 'rxjs/operators';
|
|
9
9
|
import { isPlatformBrowser, DOCUMENT, registerLocaleData } from '@angular/common';
|
|
10
|
-
import * as i1$1 from '@ngx-translate/core';
|
|
11
10
|
import Swal from 'sweetalert2';
|
|
11
|
+
import compare from 'just-compare';
|
|
12
12
|
import * as i2 from '@angular/router';
|
|
13
13
|
import { RouterStateSnapshot, TitleStrategy, NavigationStart, NavigationError, NavigationEnd, NavigationCancel, Router, PRIMARY_OUTLET } from '@angular/router';
|
|
14
14
|
import { DEFAULT_REDIRECT_KEY, NavItem, UserMenu } from '@elite.framework/ng.core/models';
|
|
15
|
-
import compare from 'just-compare';
|
|
16
15
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
17
16
|
import { Title } from '@angular/platform-browser';
|
|
18
17
|
import clone from 'just-clone';
|
|
@@ -494,95 +493,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
|
|
|
494
493
|
args: [REQUEST]
|
|
495
494
|
}] }] });
|
|
496
495
|
|
|
497
|
-
class SwalService {
|
|
498
|
-
translate;
|
|
499
|
-
defaultClass = {
|
|
500
|
-
container: 'swal2-container'
|
|
501
|
-
};
|
|
502
|
-
constructor(translate) {
|
|
503
|
-
this.translate = translate;
|
|
504
|
-
}
|
|
505
|
-
t(key) {
|
|
506
|
-
return this.translate.instant(key);
|
|
507
|
-
}
|
|
508
|
-
/** رسالة تأكيد */
|
|
509
|
-
confirm(title = this.t('Confirm.Title'), text = this.t('Confirm.Text'), confirmButtonText = this.t('Confirm.Yes'), cancelButtonText = this.t('Confirm.Cancel')) {
|
|
510
|
-
return Swal.fire({
|
|
511
|
-
icon: 'warning',
|
|
512
|
-
title,
|
|
513
|
-
text,
|
|
514
|
-
showCancelButton: true,
|
|
515
|
-
confirmButtonText,
|
|
516
|
-
cancelButtonText,
|
|
517
|
-
customClass: this.defaultClass
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
/** رسالة نجاح */
|
|
521
|
-
success(title, text, timer = 2000) {
|
|
522
|
-
return Swal.fire({
|
|
523
|
-
icon: 'success',
|
|
524
|
-
title: this.t(title),
|
|
525
|
-
text: text ? this.t(text) : undefined,
|
|
526
|
-
timer,
|
|
527
|
-
showConfirmButton: false,
|
|
528
|
-
customClass: this.defaultClass
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
/** رسالة خطأ */
|
|
532
|
-
error(title, text, footer) {
|
|
533
|
-
return Swal.fire({
|
|
534
|
-
icon: 'error',
|
|
535
|
-
title: this.t(title),
|
|
536
|
-
text: text ? this.t(text) : undefined,
|
|
537
|
-
footer: footer ? this.t(footer) : undefined,
|
|
538
|
-
customClass: this.defaultClass
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
/** رسالة معلومات */
|
|
542
|
-
info(title, text) {
|
|
543
|
-
return Swal.fire({
|
|
544
|
-
icon: 'info',
|
|
545
|
-
title: this.t(title),
|
|
546
|
-
text: text ? this.t(text) : undefined,
|
|
547
|
-
customClass: this.defaultClass
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
/** أي خيارات مخصصة */
|
|
551
|
-
alert(options) {
|
|
552
|
-
const translated = {
|
|
553
|
-
...options,
|
|
554
|
-
title: options.title ? this.t(options.title) : undefined,
|
|
555
|
-
text: options.text ? this.t(options.text) : undefined,
|
|
556
|
-
footer: options.footer ? this.t(options.footer) : undefined,
|
|
557
|
-
customClass: this.defaultClass
|
|
558
|
-
};
|
|
559
|
-
return Swal.fire(translated);
|
|
560
|
-
}
|
|
561
|
-
/** Toast */
|
|
562
|
-
toast(title, icon = 'info', position = 'top-end', timer = 3000) {
|
|
563
|
-
const Toast = Swal.mixin({
|
|
564
|
-
toast: true,
|
|
565
|
-
position,
|
|
566
|
-
timer,
|
|
567
|
-
showConfirmButton: false,
|
|
568
|
-
customClass: this.defaultClass
|
|
569
|
-
});
|
|
570
|
-
Toast.fire({ icon, title: this.t(title) });
|
|
571
|
-
}
|
|
572
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
573
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, providedIn: 'root' });
|
|
574
|
-
}
|
|
575
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, decorators: [{
|
|
576
|
-
type: Injectable,
|
|
577
|
-
args: [{ providedIn: 'root' }]
|
|
578
|
-
}], ctorParameters: () => [{ type: i1$1.TranslateService }] });
|
|
579
|
-
|
|
580
496
|
class ApplicationLocalizationService {
|
|
581
497
|
restService;
|
|
582
498
|
apiName = 'framework';
|
|
583
499
|
get = (input, config) => this.restService.request({
|
|
584
500
|
method: 'GET',
|
|
585
|
-
url: '/
|
|
501
|
+
url: '/asp-net-core/framework-application-localizations',
|
|
586
502
|
params: { cultureName: input.cultureName, onlyDynamics: input.onlyDynamics },
|
|
587
503
|
}, { apiName: this.apiName, ...config });
|
|
588
504
|
constructor(restService) {
|
|
@@ -605,7 +521,7 @@ class ApplicationConfigurationService {
|
|
|
605
521
|
get = (options, config) => this.restService.request({
|
|
606
522
|
method: 'GET',
|
|
607
523
|
// url: '/api/framework/application-configuration',
|
|
608
|
-
url: '/
|
|
524
|
+
url: '/asp-net-core/framework-application-configurations',
|
|
609
525
|
params: { includeLocalizationResources: options.includeLocalizationResources },
|
|
610
526
|
}, { apiName: this.apiName, ...config });
|
|
611
527
|
constructor(restService) {
|
|
@@ -811,1150 +727,1234 @@ function splitKeys(keys) {
|
|
|
811
727
|
return keys;
|
|
812
728
|
}
|
|
813
729
|
|
|
814
|
-
class
|
|
730
|
+
class SessionStateService {
|
|
815
731
|
configState;
|
|
816
|
-
|
|
732
|
+
localStorageService;
|
|
733
|
+
store = new InternalStore({});
|
|
734
|
+
document = inject(DOCUMENT);
|
|
735
|
+
updateLocalStorage = () => {
|
|
736
|
+
this.localStorageService.set('abpSession', JSON.stringify(this.store.state), { expires: new Date(new Date().getTime() + 365 * 86400000), path: '/' });
|
|
737
|
+
};
|
|
738
|
+
constructor(configState, localStorageService) {
|
|
817
739
|
this.configState = configState;
|
|
740
|
+
this.localStorageService = localStorageService;
|
|
741
|
+
this.init();
|
|
742
|
+
this.setInitialLanguage();
|
|
818
743
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
const andRegexp = /&&/g;
|
|
824
|
-
// TODO: Allow combination of ANDs & ORs
|
|
825
|
-
if (orRegexp.test(key)) {
|
|
826
|
-
const keys = key.split('||').filter(Boolean);
|
|
827
|
-
if (keys.length < 2)
|
|
828
|
-
return false;
|
|
829
|
-
return keys.some(k => this.getPolicy(k.trim(), grantedPolicies));
|
|
830
|
-
}
|
|
831
|
-
else if (andRegexp.test(key)) {
|
|
832
|
-
const keys = key.split('&&').filter(Boolean);
|
|
833
|
-
if (keys.length < 2)
|
|
834
|
-
return false;
|
|
835
|
-
return keys.every(k => this.getPolicy(k.trim(), grantedPolicies));
|
|
744
|
+
init() {
|
|
745
|
+
const session = this.localStorageService.get('abpSession');
|
|
746
|
+
if (session) {
|
|
747
|
+
this.store.set(JSON.parse(session));
|
|
836
748
|
}
|
|
837
|
-
|
|
749
|
+
this.store.sliceUpdate(state => state).subscribe(this.updateLocalStorage);
|
|
838
750
|
}
|
|
839
|
-
|
|
840
|
-
|
|
751
|
+
setInitialLanguage() {
|
|
752
|
+
const appLanguage = this.getLanguage();
|
|
753
|
+
this.configState
|
|
754
|
+
.getDeep$('localization.currentCulture.cultureName')
|
|
755
|
+
.pipe(filter(cultureName => !!cultureName), take(1))
|
|
756
|
+
.subscribe(lang => {
|
|
757
|
+
if (lang.includes(';')) {
|
|
758
|
+
lang = lang.split(';')[0];
|
|
759
|
+
}
|
|
760
|
+
this.setLanguage(lang);
|
|
761
|
+
});
|
|
841
762
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
return true;
|
|
845
|
-
return this.getGrantedPolicy$(permissionName);
|
|
763
|
+
onLanguageChange$() {
|
|
764
|
+
return this.store.sliceUpdate(state => state.language);
|
|
846
765
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
return true;
|
|
850
|
-
return this.getGrantedPolicy(permissionName);
|
|
766
|
+
onTenantChange$() {
|
|
767
|
+
return this.store.sliceUpdate(state => state.tenant);
|
|
851
768
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
return this.isPolicyGranted(key, policies);
|
|
769
|
+
getLanguage() {
|
|
770
|
+
return this.store.state.language;
|
|
855
771
|
}
|
|
856
|
-
|
|
857
|
-
return this.
|
|
772
|
+
getLanguage$() {
|
|
773
|
+
return this.store.sliceState(state => state.language);
|
|
858
774
|
}
|
|
859
|
-
|
|
860
|
-
return this.
|
|
775
|
+
getTenant() {
|
|
776
|
+
return this.store.state.tenant;
|
|
861
777
|
}
|
|
862
|
-
|
|
863
|
-
return
|
|
778
|
+
getTenant$() {
|
|
779
|
+
return this.store.sliceState(state => state.tenant);
|
|
864
780
|
}
|
|
865
|
-
|
|
866
|
-
|
|
781
|
+
setTenant(tenant) {
|
|
782
|
+
if (compare(tenant, this.store.state.tenant))
|
|
783
|
+
return;
|
|
784
|
+
this.store.set({ ...this.store.state, tenant });
|
|
867
785
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
type: Injectable,
|
|
873
|
-
args: [{
|
|
874
|
-
providedIn: 'root'
|
|
875
|
-
}]
|
|
876
|
-
}], ctorParameters: () => [{ type: ConfigStateService }] });
|
|
877
|
-
|
|
878
|
-
const ngxPermissionsGuard = (route, state) => {
|
|
879
|
-
const guard = inject(NgxPermissionsGuard);
|
|
880
|
-
if (state instanceof RouterStateSnapshot) {
|
|
881
|
-
return guard.hasPermissions(route, state);
|
|
786
|
+
setState(session) {
|
|
787
|
+
if (compare(session, this.store.state))
|
|
788
|
+
return;
|
|
789
|
+
this.store.set({ ...this.store.state, ...session });
|
|
882
790
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
791
|
+
setLanguage(language) {
|
|
792
|
+
const currentLanguage = this.store.state.language;
|
|
793
|
+
if (language !== currentLanguage) {
|
|
794
|
+
this.store.patch({ language });
|
|
795
|
+
}
|
|
796
|
+
const currentAttribute = this.document.documentElement.getAttribute('lang');
|
|
797
|
+
if (language !== currentAttribute) {
|
|
798
|
+
this.document.documentElement.setAttribute('lang', language);
|
|
799
|
+
}
|
|
891
800
|
}
|
|
892
|
-
|
|
893
|
-
return this.
|
|
801
|
+
get application() {
|
|
802
|
+
return this.store.state.application;
|
|
894
803
|
}
|
|
895
|
-
|
|
896
|
-
return this.
|
|
804
|
+
get user() {
|
|
805
|
+
return this.store.state.user;
|
|
897
806
|
}
|
|
898
|
-
|
|
899
|
-
return this.
|
|
807
|
+
get userId() {
|
|
808
|
+
return this.user ? this.user.id : 0;
|
|
900
809
|
}
|
|
901
|
-
|
|
902
|
-
return this.
|
|
810
|
+
get tenant() {
|
|
811
|
+
return this.store.state.tenant;
|
|
903
812
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
813
|
+
get branch() {
|
|
814
|
+
return this.store.state.branch;
|
|
815
|
+
}
|
|
816
|
+
/* get branchName(): BranchLoginInfoDto {
|
|
817
|
+
return this._branch ? this.branch.Name : '';
|
|
818
|
+
|
|
819
|
+
} */
|
|
820
|
+
get tenancyName() {
|
|
821
|
+
return this.store.state.tenant ? this.tenant?.tenancyName : '';
|
|
822
|
+
}
|
|
823
|
+
get branchId() {
|
|
824
|
+
// return this.branch ? this.branch.id : this.configState.Session?.branchId ? this.configState.Session.branchId:null;
|
|
825
|
+
return this.branch ? this.branch.id : 0;
|
|
826
|
+
}
|
|
827
|
+
get tenantId() {
|
|
828
|
+
return this.tenant ? this.tenant.id : 0;
|
|
829
|
+
}
|
|
830
|
+
getShownLoginName() {
|
|
831
|
+
const userName = this.store.state.user?.userName ?? '';
|
|
832
|
+
if (!this.multiTenancySide) {
|
|
833
|
+
return userName;
|
|
916
834
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
else {
|
|
923
|
-
except.push(...transformStringToArray(data.except));
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
const permissions = {
|
|
927
|
-
only,
|
|
928
|
-
except,
|
|
929
|
-
redirectTo: data?.redirectTo
|
|
930
|
-
};
|
|
931
|
-
// --- rest of the guard logic ---
|
|
932
|
-
// EXCEPT check
|
|
933
|
-
if (permissions.except?.length) {
|
|
934
|
-
for (const perm of permissions.except) {
|
|
935
|
-
if (await this.permissions.isGranted(perm)) {
|
|
936
|
-
this.handleRedirect(permissions, perm, route, state);
|
|
937
|
-
return false;
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
// ONLY check
|
|
942
|
-
if (permissions.only?.length) {
|
|
943
|
-
for (const perm of permissions.only) {
|
|
944
|
-
if (await this.permissions.isGrantedAsync(perm)) {
|
|
945
|
-
return true;
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
this.handleRedirect(permissions, permissions.only[0], route, state);
|
|
835
|
+
return (this.store.state.tenant ? this.store.state.tenant.tenancyName : '.') + '\\' + userName;
|
|
836
|
+
}
|
|
837
|
+
changeTenantIfNeeded(tenantId) {
|
|
838
|
+
if (this.isCurrentTenant(tenantId)) {
|
|
949
839
|
return false;
|
|
950
840
|
}
|
|
841
|
+
// this.configState.SetTenantIdCookie(tenantId);
|
|
842
|
+
location.reload();
|
|
951
843
|
return true;
|
|
952
844
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
if (!
|
|
956
|
-
return;
|
|
957
|
-
// If redirectTo is a function
|
|
958
|
-
const resolvedRedirect = isFunction(redirectTo)
|
|
959
|
-
? redirectTo(failedPermission, route, state)
|
|
960
|
-
: redirectTo;
|
|
961
|
-
if (typeof resolvedRedirect === 'string') {
|
|
962
|
-
this.router.navigate([resolvedRedirect]); // wrap string in array
|
|
963
|
-
}
|
|
964
|
-
else if (Array.isArray(resolvedRedirect)) {
|
|
965
|
-
this.router.navigate(resolvedRedirect); // array is fine
|
|
966
|
-
}
|
|
967
|
-
else if (isPlainObject(resolvedRedirect)) {
|
|
968
|
-
// Object: check for failedPermission key first
|
|
969
|
-
const target = resolvedRedirect[failedPermission] ?? resolvedRedirect[DEFAULT_REDIRECT_KEY];
|
|
970
|
-
if (target) {
|
|
971
|
-
if (typeof target === 'string') {
|
|
972
|
-
this.router.navigate([target]);
|
|
973
|
-
}
|
|
974
|
-
else if (Array.isArray(target)) {
|
|
975
|
-
this.router.navigate(target);
|
|
976
|
-
}
|
|
977
|
-
else if (isFunction(target)) {
|
|
978
|
-
this.router.navigate([target(failedPermission, route, state)]);
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
else {
|
|
983
|
-
console.warn('Unknown redirect type', resolvedRedirect);
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, deps: [{ token: PermissionCheckerService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
987
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, providedIn: 'root' });
|
|
988
|
-
}
|
|
989
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, decorators: [{
|
|
990
|
-
type: Injectable,
|
|
991
|
-
args: [{ providedIn: 'root' }]
|
|
992
|
-
}], ctorParameters: () => [{ type: PermissionCheckerService }, { type: i2.Router }] });
|
|
993
|
-
|
|
994
|
-
// logger.interface.ts
|
|
995
|
-
var LogLevel;
|
|
996
|
-
(function (LogLevel) {
|
|
997
|
-
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
998
|
-
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
999
|
-
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
1000
|
-
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
1001
|
-
LogLevel[LogLevel["OFF"] = 4] = "OFF";
|
|
1002
|
-
})(LogLevel || (LogLevel = {}));
|
|
1003
|
-
|
|
1004
|
-
// logger.service.ts
|
|
1005
|
-
// Remove the separate LoggerConfig interface since we're using EnvironmentConfig
|
|
1006
|
-
// and extend EnvironmentConfig to include logger-specific properties
|
|
1007
|
-
class LoggerService {
|
|
1008
|
-
level = LogLevel.DEBUG;
|
|
1009
|
-
enableConsole = true;
|
|
1010
|
-
prefix = '[App]';
|
|
1011
|
-
timestamp = true;
|
|
1012
|
-
environmentService = inject(EnvironmentService);
|
|
1013
|
-
environment = this.environmentService?.getEnvironment();
|
|
1014
|
-
constructor() {
|
|
1015
|
-
// Use environment configuration if provided
|
|
1016
|
-
if (this.environment) {
|
|
1017
|
-
this.configureFromEnvironment(this.environment);
|
|
1018
|
-
}
|
|
1019
|
-
// Fallback: In production, default to WARN level
|
|
1020
|
-
if (typeof window !== 'undefined' && window.location.hostname !== 'localhost') {
|
|
1021
|
-
this.level = LogLevel.WARN;
|
|
1022
|
-
this.enableConsole = false;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
configureFromEnvironment(env) {
|
|
1026
|
-
// Map string log levels from environment to LogLevel enum
|
|
1027
|
-
this.level = this.mapLogLevel(env.logLevel);
|
|
1028
|
-
// Use production flag to determine console logging
|
|
1029
|
-
this.enableConsole = !env.production;
|
|
1030
|
-
// Set prefix from environment if available
|
|
1031
|
-
this.prefix = `[${env['appName'] || 'App'}]`;
|
|
1032
|
-
// Enable timestamp in development, disable in production for performance
|
|
1033
|
-
this.timestamp = !env.production;
|
|
1034
|
-
}
|
|
1035
|
-
mapLogLevel(level) {
|
|
1036
|
-
switch (level) {
|
|
1037
|
-
case 'debug': return LogLevel.DEBUG;
|
|
1038
|
-
case 'info': return LogLevel.INFO;
|
|
1039
|
-
case 'warn': return LogLevel.WARN;
|
|
1040
|
-
case 'error': return LogLevel.ERROR;
|
|
1041
|
-
case 'off': return LogLevel.OFF;
|
|
1042
|
-
default: return LogLevel.WARN;
|
|
845
|
+
isCurrentTenant(tenantId) {
|
|
846
|
+
let isTenant = tenantId ?? 0 > 0;
|
|
847
|
+
if (!isTenant && !this.tenant) { // this is host
|
|
848
|
+
return true;
|
|
1043
849
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
1047
|
-
this.log('DEBUG', message, args, 'color: blue');
|
|
850
|
+
if (!tenantId && this.tenant) {
|
|
851
|
+
return false;
|
|
1048
852
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
if (this.shouldLog(LogLevel.INFO)) {
|
|
1052
|
-
this.log('INFO', message, args, 'color: green');
|
|
853
|
+
else if (tenantId && (!this.tenant || this.tenant.id !== tenantId)) {
|
|
854
|
+
return false;
|
|
1053
855
|
}
|
|
856
|
+
return true;
|
|
1054
857
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
this.log('WARN', message, args, 'color: orange');
|
|
1058
|
-
}
|
|
858
|
+
get impersonatorUser() {
|
|
859
|
+
return this.store.state.impersonatorUser;
|
|
1059
860
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
this.log('ERROR', message, args, 'color: red');
|
|
1063
|
-
// Send to external services only for errors in production
|
|
1064
|
-
if (this.environment?.production) {
|
|
1065
|
-
this.sendToExternalService('ERROR', message, args);
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
861
|
+
get impersonatorUserId() {
|
|
862
|
+
return this.impersonatorUser ? this.impersonatorUser.id : 0;
|
|
1068
863
|
}
|
|
1069
|
-
|
|
1070
|
-
this.
|
|
864
|
+
get impersonatorTenant() {
|
|
865
|
+
return this.store.state.impersonatorTenant;
|
|
1071
866
|
}
|
|
1072
|
-
|
|
1073
|
-
return
|
|
867
|
+
get impersonatorTenancyName() {
|
|
868
|
+
return this.impersonatorTenant ? this.impersonatorTenant?.tenancyName ?? '' : '';
|
|
1074
869
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
return;
|
|
1078
|
-
const timestamp = this.timestamp ? new Date().toISOString() : '';
|
|
1079
|
-
const formattedPrefix = this.prefix ? `${this.prefix}` : '';
|
|
1080
|
-
const logMessage = `${timestamp} ${formattedPrefix} [${level}] ${message}`;
|
|
1081
|
-
if (args.length > 0) {
|
|
1082
|
-
console.log(`%c${logMessage}`, style, ...args);
|
|
1083
|
-
}
|
|
1084
|
-
else {
|
|
1085
|
-
console.log(`%c${logMessage}`, style);
|
|
1086
|
-
}
|
|
870
|
+
get impersonatorTenantId() {
|
|
871
|
+
return this.impersonatorTenant ? this.impersonatorTenant.id : 0;
|
|
1087
872
|
}
|
|
1088
|
-
|
|
1089
|
-
//
|
|
1090
|
-
|
|
1091
|
-
const sentryUrl = this.environment?.externalServices?.['sentry'];
|
|
1092
|
-
const logRocketUrl = this.environment?.externalServices?.['logRocket'];
|
|
1093
|
-
// Example: Send to configured external services
|
|
1094
|
-
if (sentryUrl) {
|
|
1095
|
-
// this.sendToSentry(level, message, args);
|
|
1096
|
-
}
|
|
1097
|
-
if (logRocketUrl) {
|
|
1098
|
-
// this.sendToLogRocket(level, message, args);
|
|
1099
|
-
}
|
|
1100
|
-
// Send to backend if apiUrl is available
|
|
1101
|
-
if (this.environment?.apis.default.url) {
|
|
1102
|
-
// this.http.post(`${this.environment.apiUrl}/logs`, {
|
|
1103
|
-
// level, message, args, timestamp: new Date()
|
|
1104
|
-
// }).subscribe();
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
catch (error) {
|
|
1108
|
-
// Don't use this.error here to avoid infinite loops
|
|
1109
|
-
console.error('Failed to send log to external service:', error);
|
|
1110
|
-
}
|
|
873
|
+
get multiTenancySide() {
|
|
874
|
+
// return this.configState.session?.multiTenancySide;
|
|
875
|
+
return 0;
|
|
1111
876
|
}
|
|
1112
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type:
|
|
1113
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type:
|
|
877
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, deps: [{ token: ConfigStateService }, { token: SsrCookieService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
878
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, providedIn: 'root' });
|
|
1114
879
|
}
|
|
1115
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type:
|
|
880
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, decorators: [{
|
|
1116
881
|
type: Injectable,
|
|
1117
882
|
args: [{
|
|
1118
|
-
providedIn: 'root'
|
|
883
|
+
providedIn: 'root',
|
|
1119
884
|
}]
|
|
1120
|
-
}], ctorParameters: () => [] });
|
|
885
|
+
}], ctorParameters: () => [{ type: ConfigStateService }, { type: SsrCookieService }] });
|
|
1121
886
|
|
|
1122
|
-
class
|
|
887
|
+
class LocalizationService {
|
|
888
|
+
sessionState;
|
|
889
|
+
injector;
|
|
890
|
+
configState;
|
|
891
|
+
latestLang = 'ar';
|
|
892
|
+
_languageChange$ = new Subject();
|
|
893
|
+
uiLocalizations$ = new BehaviorSubject(new Map());
|
|
894
|
+
localizations$ = new BehaviorSubject(new Map());
|
|
1123
895
|
/**
|
|
1124
|
-
*
|
|
1125
|
-
*
|
|
896
|
+
* Returns currently selected language
|
|
897
|
+
* Even though this looks like it's redundant to return the same value as `getLanguage()`,
|
|
898
|
+
* it's actually not. This could be invoked any time, and the latestLang could be different from the
|
|
899
|
+
* sessionState.getLanguage() value.
|
|
1126
900
|
*/
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
return null;
|
|
1130
|
-
const fields = idField.split(',').map(f => f.trim()).filter(Boolean);
|
|
1131
|
-
if (fields.length === 1) {
|
|
1132
|
-
return model[fields[0]];
|
|
1133
|
-
}
|
|
1134
|
-
return fields.map(f => model[f]);
|
|
901
|
+
get currentLanguage() {
|
|
902
|
+
return this.latestLang || this.sessionState.getLanguage();
|
|
1135
903
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
1166
|
-
else if (part.startsWith('$select=')) {
|
|
1167
|
-
this.parseSelect(part.substring('$select='.length), params);
|
|
1168
|
-
}
|
|
1169
|
-
else if (part.startsWith('$aggregate=')) {
|
|
1170
|
-
this.parseAggregate(part.substring('$aggregate='.length), params);
|
|
1171
|
-
}
|
|
1172
|
-
else if (part.startsWith('$top=')) {
|
|
1173
|
-
params.top = Number(part.substring('$top='.length));
|
|
1174
|
-
}
|
|
1175
|
-
else if (part.startsWith('$skip=')) {
|
|
1176
|
-
params.skip = Number(part.substring('$skip='.length));
|
|
1177
|
-
}
|
|
1178
|
-
else if (part.startsWith('$expand=')) {
|
|
1179
|
-
params.expand = part.substring('$expand='.length).split(',').map(f => f.trim());
|
|
904
|
+
get currentLang() {
|
|
905
|
+
return this.latestLang || this.sessionState.getLanguage();
|
|
906
|
+
}
|
|
907
|
+
get currentLang$() {
|
|
908
|
+
return this.sessionState.getLanguage$();
|
|
909
|
+
}
|
|
910
|
+
get languageChange$() {
|
|
911
|
+
return this._languageChange$.asObservable();
|
|
912
|
+
}
|
|
913
|
+
constructor(sessionState, injector, otherInstance, configState) {
|
|
914
|
+
this.sessionState = sessionState;
|
|
915
|
+
this.injector = injector;
|
|
916
|
+
this.configState = configState;
|
|
917
|
+
if (otherInstance)
|
|
918
|
+
throw new Error('LocalizationService should have only one instance.');
|
|
919
|
+
this.listenToSetLanguage();
|
|
920
|
+
this.initLocalizationValues();
|
|
921
|
+
this.latestLang = this.sessionState.getLanguage();
|
|
922
|
+
}
|
|
923
|
+
initLocalizationValues() {
|
|
924
|
+
localizations$.subscribe(val => this.addLocalization(val));
|
|
925
|
+
const legacyResources$ = this.configState.getDeep$('localization.values');
|
|
926
|
+
const remoteLocalizations$ = this.configState.getDeep$('localization.resources');
|
|
927
|
+
const currentLanguage$ = this.sessionState.getLanguage$();
|
|
928
|
+
const uiLocalizations$ = combineLatest([currentLanguage$, this.uiLocalizations$]).pipe(map(([currentLang, localizations]) => localizations.get(currentLang)));
|
|
929
|
+
combineLatest([legacyResources$, remoteLocalizations$, uiLocalizations$])
|
|
930
|
+
.pipe(map(([legacy, resource, local]) => {
|
|
931
|
+
if (!resource) {
|
|
932
|
+
return null;
|
|
1180
933
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
934
|
+
const remote = combineLegacyandNewResources(legacy || {}, resource);
|
|
935
|
+
if (remote) {
|
|
936
|
+
if (!local) {
|
|
937
|
+
local = new Map();
|
|
938
|
+
}
|
|
939
|
+
Object.entries(remote).forEach(entry => {
|
|
940
|
+
const resourceName = entry[0];
|
|
941
|
+
const remoteTexts = entry[1];
|
|
942
|
+
let resource = local?.get(resourceName) || {};
|
|
943
|
+
resource = { ...resource, ...remoteTexts };
|
|
944
|
+
local?.set(resourceName, resource);
|
|
945
|
+
});
|
|
1183
946
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
947
|
+
return local;
|
|
948
|
+
}), filter(Boolean))
|
|
949
|
+
.subscribe(val => this.localizations$.next(val));
|
|
1186
950
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
951
|
+
addLocalization(localizations) {
|
|
952
|
+
if (!localizations)
|
|
953
|
+
return;
|
|
954
|
+
const localizationMap = this.uiLocalizations$.value;
|
|
955
|
+
localizations.forEach(loc => {
|
|
956
|
+
const cultureMap = localizationMap.get(loc.culture) || new Map();
|
|
957
|
+
loc.resources.forEach(res => {
|
|
958
|
+
let resource = cultureMap.get(res.resourceName) || {};
|
|
959
|
+
resource = { ...resource, ...res.texts };
|
|
960
|
+
cultureMap.set(res.resourceName, resource);
|
|
961
|
+
});
|
|
962
|
+
localizationMap.set(loc.culture, cultureMap);
|
|
963
|
+
});
|
|
964
|
+
this.uiLocalizations$.next(localizationMap);
|
|
965
|
+
}
|
|
966
|
+
listenToSetLanguage() {
|
|
967
|
+
this.sessionState
|
|
968
|
+
.onLanguageChange$()
|
|
969
|
+
.pipe(filter(lang => this.configState.getDeep('localization.currentCulture.cultureName') !== lang), switchMap((lang) => this.configState.refreshLocalization(lang).pipe(map(() => lang))), filter(Boolean), switchMap((lang) => from(this.registerLocale(lang).then(() => lang))))
|
|
970
|
+
.subscribe((lang) => this._languageChange$.next(lang));
|
|
971
|
+
}
|
|
972
|
+
registerLocale(locale) {
|
|
973
|
+
const { registerLocaleFn } = this.injector.get(CORE_OPTIONS);
|
|
974
|
+
return registerLocaleFn(locale).then(module => {
|
|
975
|
+
if (module?.default)
|
|
976
|
+
registerLocaleData(module.default);
|
|
977
|
+
this.latestLang = locale;
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Returns an observable localized text with the given interpolation parameters in current language.
|
|
982
|
+
* @param key Localizaton key to replace with localized text
|
|
983
|
+
* @param interpolateParams Values to interpolate
|
|
984
|
+
*/
|
|
985
|
+
get(key, ...interpolateParams) {
|
|
986
|
+
return this.configState
|
|
987
|
+
.getAll$()
|
|
988
|
+
.pipe(map(state => this.getLocalization(state, key, ...interpolateParams)));
|
|
989
|
+
}
|
|
990
|
+
getResource(resourceName) {
|
|
991
|
+
return this.localizations$.value.get(resourceName);
|
|
992
|
+
}
|
|
993
|
+
getResource$(resourceName) {
|
|
994
|
+
return this.localizations$.pipe(map(res => res.get(resourceName)));
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Returns localized text with the given interpolation parameters in current language.
|
|
998
|
+
* @param key Localization key to replace with localized text
|
|
999
|
+
// const translateService = inject(TranslateService);// from '@ngx-translate/core'; // use it for fallback
|
|
1000
|
+
* @param interpolateParams Values to intepolate.
|
|
1001
|
+
*/
|
|
1002
|
+
instant(key, ...interpolateParams) {
|
|
1003
|
+
return this.getLocalization(this.configState.getAll(), key, ...interpolateParams);
|
|
1004
|
+
}
|
|
1005
|
+
localize(resourceName, key, defaultValue) {
|
|
1006
|
+
return this.configState.getOne$('localization').pipe(map(createLocalizer), map((localize) => localize(resourceName, key, defaultValue)));
|
|
1007
|
+
}
|
|
1008
|
+
get defaultResourceName() {
|
|
1009
|
+
return this.configState.getAll().localization ? this.configState.getAll().localization.defaultResourceName : 'FrameworkLocalization';
|
|
1010
|
+
}
|
|
1011
|
+
l(key) {
|
|
1012
|
+
const localization = this.configState.getOne('localization');
|
|
1013
|
+
return createLocalizer(localization)(this.defaultResourceName ?? '', key, key);
|
|
1014
|
+
}
|
|
1015
|
+
localizeSync(resourceName, key, defaultValue) {
|
|
1016
|
+
const localization = this.configState.getOne('localization');
|
|
1017
|
+
return createLocalizer(localization)(resourceName, key, defaultValue);
|
|
1018
|
+
}
|
|
1019
|
+
localizeWithFallback(resourceNames, keys, defaultValue) {
|
|
1020
|
+
return this.configState.getOne$('localization').pipe(map(createLocalizerWithFallback), map((localizeWithFallback) => localizeWithFallback(resourceNames, keys, defaultValue)));
|
|
1021
|
+
}
|
|
1022
|
+
localizeWithFallbackSync(resourceNames, keys, defaultValue) {
|
|
1023
|
+
const localization = this.configState.getOne('localization');
|
|
1024
|
+
return createLocalizerWithFallback(localization)(resourceNames, keys, defaultValue);
|
|
1025
|
+
}
|
|
1026
|
+
getLocalization(state, key, ...interpolateParams) {
|
|
1027
|
+
let defaultValue = '';
|
|
1028
|
+
if (!key) {
|
|
1029
|
+
return defaultValue;
|
|
1200
1030
|
}
|
|
1201
|
-
if (
|
|
1202
|
-
|
|
1203
|
-
|
|
1031
|
+
if (typeof key !== 'string') {
|
|
1032
|
+
defaultValue = key.defaultValue;
|
|
1033
|
+
key = key.key;
|
|
1204
1034
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1035
|
+
const keys = key.split('::');
|
|
1036
|
+
const warn = (message) => {
|
|
1037
|
+
if (isDevMode())
|
|
1038
|
+
console.warn(message);
|
|
1039
|
+
};
|
|
1040
|
+
if (keys.length < 2) {
|
|
1041
|
+
warn('The localization source separator (::) not found.');
|
|
1042
|
+
return defaultValue || key;
|
|
1208
1043
|
}
|
|
1209
|
-
if (
|
|
1210
|
-
|
|
1044
|
+
if (!state.localization)
|
|
1045
|
+
return defaultValue || keys[1];
|
|
1046
|
+
const sourceName = keys[0] || state.localization.defaultResourceName;
|
|
1047
|
+
const sourceKey = keys[1];
|
|
1048
|
+
if (sourceName === '_') {
|
|
1049
|
+
return defaultValue || sourceKey;
|
|
1211
1050
|
}
|
|
1212
|
-
if (
|
|
1213
|
-
|
|
1051
|
+
if (!sourceName) {
|
|
1052
|
+
warn('Localization source name is not specified and the defaultResourceName was not defined!');
|
|
1053
|
+
return defaultValue || sourceKey;
|
|
1214
1054
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1055
|
+
const source = this.localizations$.value.get(sourceName);
|
|
1056
|
+
if (!source) {
|
|
1057
|
+
warn('Could not find localization source: ' + sourceName);
|
|
1058
|
+
return defaultValue || sourceKey;
|
|
1217
1059
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1060
|
+
let localization = source[sourceKey];
|
|
1061
|
+
if (typeof localization === 'undefined') {
|
|
1062
|
+
return defaultValue || sourceKey;
|
|
1220
1063
|
}
|
|
1221
|
-
|
|
1064
|
+
interpolateParams = interpolateParams.filter(params => params != null);
|
|
1065
|
+
if (localization)
|
|
1066
|
+
localization = interpolate(localization, interpolateParams);
|
|
1067
|
+
if (typeof localization !== 'string')
|
|
1068
|
+
localization = '';
|
|
1069
|
+
return localization || defaultValue || key;
|
|
1222
1070
|
}
|
|
1223
|
-
static
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if (index === 0) {
|
|
1239
|
-
return group.conditions.length > 1 ? `(${groupStr})` : groupStr;
|
|
1240
|
-
}
|
|
1241
|
-
else {
|
|
1242
|
-
const joinOp = group.groupLogicalOperator || 'and';
|
|
1243
|
-
return group.conditions.length > 1 ? `${joinOp} (${groupStr})` : `${joinOp} ${groupStr}`;
|
|
1244
|
-
}
|
|
1245
|
-
}).join(' ');
|
|
1071
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LocalizationService, deps: [{ token: SessionStateService }, { token: i0.Injector }, { token: LocalizationService, optional: true, skipSelf: true }, { token: ConfigStateService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1072
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LocalizationService, providedIn: 'root' });
|
|
1073
|
+
}
|
|
1074
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LocalizationService, decorators: [{
|
|
1075
|
+
type: Injectable,
|
|
1076
|
+
args: [{ providedIn: 'root' }]
|
|
1077
|
+
}], ctorParameters: () => [{ type: SessionStateService }, { type: i0.Injector }, { type: LocalizationService, decorators: [{
|
|
1078
|
+
type: Optional
|
|
1079
|
+
}, {
|
|
1080
|
+
type: SkipSelf
|
|
1081
|
+
}] }, { type: ConfigStateService }] });
|
|
1082
|
+
function recursivelyMergeBaseResources(baseResourceName, source) {
|
|
1083
|
+
const item = source[baseResourceName];
|
|
1084
|
+
if (item.baseResources.length === 0) {
|
|
1085
|
+
return item;
|
|
1246
1086
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1087
|
+
return item.baseResources.reduce((acc, baseResource) => {
|
|
1088
|
+
const baseItem = recursivelyMergeBaseResources(baseResource, source);
|
|
1089
|
+
const texts = { ...baseItem.texts, ...item.texts };
|
|
1090
|
+
return { ...acc, texts };
|
|
1091
|
+
}, item);
|
|
1092
|
+
}
|
|
1093
|
+
function mergeResourcesWithBaseResource(resource) {
|
|
1094
|
+
const entities = Object.keys(resource).map(key => {
|
|
1095
|
+
const newValue = recursivelyMergeBaseResources(key, resource);
|
|
1096
|
+
return [key, newValue];
|
|
1097
|
+
});
|
|
1098
|
+
return entities.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
|
|
1099
|
+
}
|
|
1100
|
+
function combineLegacyandNewResources(legacy, resource) {
|
|
1101
|
+
const mergedResource = mergeResourcesWithBaseResource(resource);
|
|
1102
|
+
return Object.entries(mergedResource).reduce((acc, [key, value]) => {
|
|
1103
|
+
return { ...acc, [key]: value.texts };
|
|
1104
|
+
}, legacy);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
class SwalService {
|
|
1108
|
+
translate;
|
|
1109
|
+
defaultClass = {
|
|
1110
|
+
container: 'swal2-container'
|
|
1111
|
+
};
|
|
1112
|
+
constructor(translate) {
|
|
1113
|
+
this.translate = translate;
|
|
1273
1114
|
}
|
|
1274
|
-
|
|
1275
|
-
return
|
|
1276
|
-
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
1277
|
-
.map(item => {
|
|
1278
|
-
let selectStr = item.propertyName;
|
|
1279
|
-
// Add display name if provided
|
|
1280
|
-
if (item.displayName) {
|
|
1281
|
-
selectStr += ` as ${item.displayName}`;
|
|
1282
|
-
}
|
|
1283
|
-
// Add aggregate function if provided
|
|
1284
|
-
if (item.aggregateFunction) {
|
|
1285
|
-
selectStr += ` with ${item.aggregateFunction}`;
|
|
1286
|
-
}
|
|
1287
|
-
// Add visibility metadata
|
|
1288
|
-
const metadata = [];
|
|
1289
|
-
if (item.isVisible !== undefined) {
|
|
1290
|
-
metadata.push(`visible:${item.isVisible}`);
|
|
1291
|
-
}
|
|
1292
|
-
if (metadata.length > 0) {
|
|
1293
|
-
selectStr += `(${metadata.join(';')})`;
|
|
1294
|
-
}
|
|
1295
|
-
return selectStr;
|
|
1296
|
-
})
|
|
1297
|
-
.join(',');
|
|
1115
|
+
t(key) {
|
|
1116
|
+
return this.translate.instant(key);
|
|
1298
1117
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
.
|
|
1118
|
+
/** رسالة تأكيد */
|
|
1119
|
+
confirm(title = this.t('Confirm.Title'), text = this.t('Confirm.Text'), confirmButtonText = this.t('Confirm.Yes'), cancelButtonText = this.t('Confirm.Cancel')) {
|
|
1120
|
+
return Swal.fire({
|
|
1121
|
+
icon: 'warning',
|
|
1122
|
+
title,
|
|
1123
|
+
text,
|
|
1124
|
+
showCancelButton: true,
|
|
1125
|
+
confirmButtonText,
|
|
1126
|
+
cancelButtonText,
|
|
1127
|
+
customClass: this.defaultClass
|
|
1128
|
+
});
|
|
1309
1129
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
const operator = match[1];
|
|
1320
|
-
const segment = decodedString.substring(lastIndex, match.index).trim();
|
|
1321
|
-
if (segment) {
|
|
1322
|
-
segments.push({ condition: segment, operator });
|
|
1323
|
-
}
|
|
1324
|
-
lastIndex = match.index + match[0].length;
|
|
1325
|
-
}
|
|
1326
|
-
// Add the last segment
|
|
1327
|
-
const lastSegment = decodedString.substring(lastIndex).trim();
|
|
1328
|
-
if (lastSegment) {
|
|
1329
|
-
segments.push({ condition: lastSegment, operator: undefined });
|
|
1330
|
-
}
|
|
1331
|
-
// Parse each segment
|
|
1332
|
-
segments.forEach((segment, index) => {
|
|
1333
|
-
let conditions = [];
|
|
1334
|
-
// Check if it's a group with parentheses
|
|
1335
|
-
if (segment.condition.startsWith('(') && segment.condition.endsWith(')')) {
|
|
1336
|
-
const innerCondition = segment.condition.slice(1, -1).trim();
|
|
1337
|
-
conditions = this.parseConditions(innerCondition);
|
|
1338
|
-
}
|
|
1339
|
-
else {
|
|
1340
|
-
// Individual condition
|
|
1341
|
-
conditions = this.parseConditions(segment.condition);
|
|
1342
|
-
}
|
|
1343
|
-
if (conditions.length > 0) {
|
|
1344
|
-
const group = {
|
|
1345
|
-
logicalOperator: 'and',
|
|
1346
|
-
conditions: conditions
|
|
1347
|
-
};
|
|
1348
|
-
// For groups after the first, set the groupLogicalOperator
|
|
1349
|
-
if (index > 0) {
|
|
1350
|
-
group.groupLogicalOperator = segment.operator?.toLowerCase() || 'and';
|
|
1351
|
-
}
|
|
1352
|
-
// Detect the logical operator used within the group
|
|
1353
|
-
if (conditions.length === 1 && segment.condition.includes(' or ')) {
|
|
1354
|
-
group.logicalOperator = 'or';
|
|
1355
|
-
}
|
|
1356
|
-
else if (conditions.length > 1) {
|
|
1357
|
-
group.logicalOperator = segment.condition.toLowerCase().includes(' or ') ? 'or' : 'and';
|
|
1358
|
-
}
|
|
1359
|
-
groups.push(group);
|
|
1360
|
-
}
|
|
1130
|
+
/** رسالة نجاح */
|
|
1131
|
+
success(title, text, timer = 2000) {
|
|
1132
|
+
return Swal.fire({
|
|
1133
|
+
icon: 'success',
|
|
1134
|
+
title: this.t(title),
|
|
1135
|
+
text: text ? this.t(text) : undefined,
|
|
1136
|
+
timer,
|
|
1137
|
+
showConfirmButton: false,
|
|
1138
|
+
customClass: this.defaultClass
|
|
1361
1139
|
});
|
|
1362
|
-
params.filters = groups;
|
|
1363
1140
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
value = rawValue.slice(1, -1).replace(/''/g, "'");
|
|
1374
|
-
}
|
|
1375
|
-
else if (rawValue.startsWith('[') && rawValue.endsWith(']')) {
|
|
1376
|
-
// Handle array values for IN/NOT IN operators
|
|
1377
|
-
value = rawValue.slice(1, -1).split(',').map(v => {
|
|
1378
|
-
const trimmed = v.trim().replace(/^'|'$/g, '');
|
|
1379
|
-
return isNaN(Number(trimmed)) ? trimmed : Number(trimmed);
|
|
1380
|
-
});
|
|
1381
|
-
}
|
|
1382
|
-
else if (!isNaN(Number(rawValue))) {
|
|
1383
|
-
value = Number(rawValue);
|
|
1384
|
-
}
|
|
1385
|
-
else if (rawValue.toLowerCase() === 'true') {
|
|
1386
|
-
value = true;
|
|
1387
|
-
}
|
|
1388
|
-
else if (rawValue.toLowerCase() === 'false') {
|
|
1389
|
-
value = false;
|
|
1390
|
-
}
|
|
1391
|
-
else if (rawValue.toLowerCase() === 'null') {
|
|
1392
|
-
value = null;
|
|
1393
|
-
}
|
|
1394
|
-
conditions.push({
|
|
1395
|
-
field: field.trim(),
|
|
1396
|
-
operator: operator.trim().toLowerCase(),
|
|
1397
|
-
value
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
return conditions;
|
|
1141
|
+
/** رسالة خطأ */
|
|
1142
|
+
error(title, text, footer) {
|
|
1143
|
+
return Swal.fire({
|
|
1144
|
+
icon: 'error',
|
|
1145
|
+
title: this.t(title),
|
|
1146
|
+
text: text ? this.t(text) : undefined,
|
|
1147
|
+
footer: footer ? this.t(footer) : undefined,
|
|
1148
|
+
customClass: this.defaultClass
|
|
1149
|
+
});
|
|
1401
1150
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1151
|
+
/** رسالة معلومات */
|
|
1152
|
+
info(title, text) {
|
|
1153
|
+
return Swal.fire({
|
|
1154
|
+
icon: 'info',
|
|
1155
|
+
title: this.t(title),
|
|
1156
|
+
text: text ? this.t(text) : undefined,
|
|
1157
|
+
customClass: this.defaultClass
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
/** أي خيارات مخصصة */
|
|
1161
|
+
alert(options) {
|
|
1162
|
+
const translated = {
|
|
1163
|
+
...options,
|
|
1164
|
+
title: options.title ? this.t(options.title) : undefined,
|
|
1165
|
+
text: options.text ? this.t(options.text) : undefined,
|
|
1166
|
+
footer: options.footer ? this.t(options.footer) : undefined,
|
|
1167
|
+
customClass: this.defaultClass
|
|
1168
|
+
};
|
|
1169
|
+
return Swal.fire(translated);
|
|
1170
|
+
}
|
|
1171
|
+
/** Toast */
|
|
1172
|
+
toast(title, icon = 'info', position = 'top-end', timer = 3000) {
|
|
1173
|
+
const Toast = Swal.mixin({
|
|
1174
|
+
toast: true,
|
|
1175
|
+
position,
|
|
1176
|
+
timer,
|
|
1177
|
+
showConfirmButton: false,
|
|
1178
|
+
customClass: this.defaultClass
|
|
1179
|
+
});
|
|
1180
|
+
Toast.fire({ icon, title: this.t(title) });
|
|
1181
|
+
}
|
|
1182
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, deps: [{ token: LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1183
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, providedIn: 'root' });
|
|
1184
|
+
}
|
|
1185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SwalService, decorators: [{
|
|
1186
|
+
type: Injectable,
|
|
1187
|
+
args: [{ providedIn: 'root' }]
|
|
1188
|
+
}], ctorParameters: () => [{ type: LocalizationService }] });
|
|
1189
|
+
|
|
1190
|
+
class PermissionCheckerService {
|
|
1191
|
+
configState;
|
|
1192
|
+
constructor(configState) {
|
|
1193
|
+
this.configState = configState;
|
|
1194
|
+
}
|
|
1195
|
+
isPolicyGranted(key, grantedPolicies) {
|
|
1196
|
+
if (!key)
|
|
1197
|
+
return true;
|
|
1198
|
+
const orRegexp = /\|\|/g;
|
|
1199
|
+
const andRegexp = /&&/g;
|
|
1200
|
+
// TODO: Allow combination of ANDs & ORs
|
|
1201
|
+
if (orRegexp.test(key)) {
|
|
1202
|
+
const keys = key.split('||').filter(Boolean);
|
|
1203
|
+
if (keys.length < 2)
|
|
1204
|
+
return false;
|
|
1205
|
+
return keys.some(k => this.getPolicy(k.trim(), grantedPolicies));
|
|
1206
|
+
}
|
|
1207
|
+
else if (andRegexp.test(key)) {
|
|
1208
|
+
const keys = key.split('&&').filter(Boolean);
|
|
1209
|
+
if (keys.length < 2)
|
|
1210
|
+
return false;
|
|
1211
|
+
return keys.every(k => this.getPolicy(k.trim(), grantedPolicies));
|
|
1413
1212
|
}
|
|
1213
|
+
return this.getPolicy(key, grantedPolicies);
|
|
1414
1214
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1215
|
+
getGrantedPolicy$(key) {
|
|
1216
|
+
return this.getStream().pipe(map$1(grantedPolicies => this.isPolicyGranted(key, grantedPolicies)));
|
|
1217
|
+
}
|
|
1218
|
+
isGrantedAsync(permissionName) {
|
|
1219
|
+
if (!permissionName)
|
|
1220
|
+
return true;
|
|
1221
|
+
return this.getGrantedPolicy$(permissionName);
|
|
1222
|
+
}
|
|
1223
|
+
isGranted(permissionName) {
|
|
1224
|
+
if (!permissionName)
|
|
1225
|
+
return true;
|
|
1226
|
+
return this.getGrantedPolicy(permissionName);
|
|
1227
|
+
}
|
|
1228
|
+
getGrantedPolicy(key) {
|
|
1229
|
+
const policies = this.getSnapshot();
|
|
1230
|
+
return this.isPolicyGranted(key, policies);
|
|
1231
|
+
}
|
|
1232
|
+
getStream() {
|
|
1233
|
+
return this.configState.getAll$().pipe(map$1(this.mapToPolicies));
|
|
1234
|
+
}
|
|
1235
|
+
getSnapshot() {
|
|
1236
|
+
return this.mapToPolicies(this.configState.getAll());
|
|
1237
|
+
}
|
|
1238
|
+
mapToPolicies(applicationConfiguration) {
|
|
1239
|
+
return applicationConfiguration?.auth?.grantedPolicies || {};
|
|
1240
|
+
}
|
|
1241
|
+
getPolicy(key, grantedPolicies) {
|
|
1242
|
+
return grantedPolicies[key] || false;
|
|
1243
|
+
}
|
|
1244
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PermissionCheckerService, deps: [{ token: ConfigStateService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1245
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PermissionCheckerService, providedIn: 'root' });
|
|
1246
|
+
}
|
|
1247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PermissionCheckerService, decorators: [{
|
|
1248
|
+
type: Injectable,
|
|
1249
|
+
args: [{
|
|
1250
|
+
providedIn: 'root'
|
|
1251
|
+
}]
|
|
1252
|
+
}], ctorParameters: () => [{ type: ConfigStateService }] });
|
|
1253
|
+
|
|
1254
|
+
const ngxPermissionsGuard = (route, state) => {
|
|
1255
|
+
const guard = inject(NgxPermissionsGuard);
|
|
1256
|
+
if (state instanceof RouterStateSnapshot) {
|
|
1257
|
+
return guard.hasPermissions(route, state);
|
|
1258
|
+
}
|
|
1259
|
+
return guard.hasPermissions(route);
|
|
1260
|
+
};
|
|
1261
|
+
class NgxPermissionsGuard {
|
|
1262
|
+
permissions;
|
|
1263
|
+
router;
|
|
1264
|
+
constructor(permissions, router) {
|
|
1265
|
+
this.permissions = permissions;
|
|
1266
|
+
this.router = router;
|
|
1267
|
+
}
|
|
1268
|
+
canActivate(route, state) {
|
|
1269
|
+
return this.hasPermissions(route, state);
|
|
1270
|
+
}
|
|
1271
|
+
canActivateChild(route, state) {
|
|
1272
|
+
return this.hasPermissions(route, state);
|
|
1273
|
+
}
|
|
1274
|
+
canLoad(route) {
|
|
1275
|
+
return this.hasPermissions(route);
|
|
1276
|
+
}
|
|
1277
|
+
canMatch(route) {
|
|
1278
|
+
return this.hasPermissions(route);
|
|
1279
|
+
}
|
|
1280
|
+
async hasPermissions(route, state) {
|
|
1281
|
+
const data = route.data?.['permissions'];
|
|
1282
|
+
const only = [];
|
|
1283
|
+
const except = [];
|
|
1284
|
+
if (data?.only) {
|
|
1285
|
+
if (isFunction(data.only)) {
|
|
1286
|
+
const result = data.only(route, state);
|
|
1287
|
+
only.push(...transformStringToArray(result));
|
|
1436
1288
|
}
|
|
1437
1289
|
else {
|
|
1438
|
-
|
|
1290
|
+
only.push(...transformStringToArray(data.only));
|
|
1439
1291
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
switch (key) {
|
|
1446
|
-
case 'showTotal':
|
|
1447
|
-
group.showTotal = value.toLowerCase() === 'true';
|
|
1448
|
-
break;
|
|
1449
|
-
case 'totalBg':
|
|
1450
|
-
group.totalBackground = value;
|
|
1451
|
-
break;
|
|
1452
|
-
case 'headerBg':
|
|
1453
|
-
group.groupHeaderBackground = value;
|
|
1454
|
-
break;
|
|
1455
|
-
}
|
|
1456
|
-
});
|
|
1292
|
+
}
|
|
1293
|
+
if (data?.except) {
|
|
1294
|
+
if (isFunction(data.except)) {
|
|
1295
|
+
const result = data.except(route, state);
|
|
1296
|
+
except.push(...transformStringToArray(result));
|
|
1457
1297
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
}
|
|
1461
|
-
static parseSelect(selectString, params) {
|
|
1462
|
-
const decodedString = decodeURIComponent(selectString);
|
|
1463
|
-
const items = decodedString.split(',');
|
|
1464
|
-
params.select = items.map((itemStr, index) => {
|
|
1465
|
-
const item = {
|
|
1466
|
-
propertyName: '',
|
|
1467
|
-
isVisible: true,
|
|
1468
|
-
order: index
|
|
1469
|
-
};
|
|
1470
|
-
// Check for metadata in parentheses
|
|
1471
|
-
const metadataMatch = itemStr.match(/^(.*?)\((.*)\)$/);
|
|
1472
|
-
let baseStr = itemStr;
|
|
1473
|
-
let metadataStr = '';
|
|
1474
|
-
if (metadataMatch) {
|
|
1475
|
-
baseStr = metadataMatch[1];
|
|
1476
|
-
metadataStr = metadataMatch[2];
|
|
1298
|
+
else {
|
|
1299
|
+
except.push(...transformStringToArray(data.except));
|
|
1477
1300
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1301
|
+
}
|
|
1302
|
+
const permissions = {
|
|
1303
|
+
only,
|
|
1304
|
+
except,
|
|
1305
|
+
redirectTo: data?.redirectTo
|
|
1306
|
+
};
|
|
1307
|
+
// --- rest of the guard logic ---
|
|
1308
|
+
// EXCEPT check
|
|
1309
|
+
if (permissions.except?.length) {
|
|
1310
|
+
for (const perm of permissions.except) {
|
|
1311
|
+
if (await this.permissions.isGranted(perm)) {
|
|
1312
|
+
this.handleRedirect(permissions, perm, route, state);
|
|
1313
|
+
return false;
|
|
1487
1314
|
}
|
|
1488
1315
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
const [key, value] = part.split(':');
|
|
1497
|
-
if (key === 'visible') {
|
|
1498
|
-
item.isVisible = value.toLowerCase() === 'true';
|
|
1499
|
-
}
|
|
1500
|
-
});
|
|
1316
|
+
}
|
|
1317
|
+
// ONLY check
|
|
1318
|
+
if (permissions.only?.length) {
|
|
1319
|
+
for (const perm of permissions.only) {
|
|
1320
|
+
if (await this.permissions.isGrantedAsync(perm)) {
|
|
1321
|
+
return true;
|
|
1322
|
+
}
|
|
1501
1323
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1324
|
+
this.handleRedirect(permissions, permissions.only[0], route, state);
|
|
1325
|
+
return false;
|
|
1326
|
+
}
|
|
1327
|
+
return true;
|
|
1504
1328
|
}
|
|
1505
|
-
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1329
|
+
handleRedirect(permissions, failedPermission, route, state) {
|
|
1330
|
+
const redirectTo = permissions.redirectTo;
|
|
1331
|
+
if (!redirectTo)
|
|
1332
|
+
return;
|
|
1333
|
+
// If redirectTo is a function
|
|
1334
|
+
const resolvedRedirect = isFunction(redirectTo)
|
|
1335
|
+
? redirectTo(failedPermission, route, state)
|
|
1336
|
+
: redirectTo;
|
|
1337
|
+
if (typeof resolvedRedirect === 'string') {
|
|
1338
|
+
this.router.navigate([resolvedRedirect]); // wrap string in array
|
|
1339
|
+
}
|
|
1340
|
+
else if (Array.isArray(resolvedRedirect)) {
|
|
1341
|
+
this.router.navigate(resolvedRedirect); // array is fine
|
|
1342
|
+
}
|
|
1343
|
+
else if (isPlainObject(resolvedRedirect)) {
|
|
1344
|
+
// Object: check for failedPermission key first
|
|
1345
|
+
const target = resolvedRedirect[failedPermission] ?? resolvedRedirect[DEFAULT_REDIRECT_KEY];
|
|
1346
|
+
if (target) {
|
|
1347
|
+
if (typeof target === 'string') {
|
|
1348
|
+
this.router.navigate([target]);
|
|
1349
|
+
}
|
|
1350
|
+
else if (Array.isArray(target)) {
|
|
1351
|
+
this.router.navigate(target);
|
|
1352
|
+
}
|
|
1353
|
+
else if (isFunction(target)) {
|
|
1354
|
+
this.router.navigate([target(failedPermission, route, state)]);
|
|
1520
1355
|
}
|
|
1521
1356
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
static toODataQueryParameters(params) {
|
|
1527
|
-
return {
|
|
1528
|
-
Filters: params.filters.map(group => ({
|
|
1529
|
-
LogicalOperator: group.logicalOperator,
|
|
1530
|
-
GroupLogicalOperator: group.groupLogicalOperator,
|
|
1531
|
-
Conditions: group.conditions.map(cond => ({
|
|
1532
|
-
Field: cond.field,
|
|
1533
|
-
Operator: cond.operator,
|
|
1534
|
-
Value: cond.value
|
|
1535
|
-
}))
|
|
1536
|
-
})),
|
|
1537
|
-
OrderBy: params.orderBy?.map(order => ({
|
|
1538
|
-
Field: order.field,
|
|
1539
|
-
Direction: order.direction
|
|
1540
|
-
})) || [],
|
|
1541
|
-
GroupBy: params.groupBy?.map(group => ({
|
|
1542
|
-
PropertyName: group.propertyName,
|
|
1543
|
-
DisplayName: group.displayName,
|
|
1544
|
-
ShowTotal: group.showTotal ?? true,
|
|
1545
|
-
TotalBackground: group.totalBackground,
|
|
1546
|
-
GroupHeaderBackground: group.groupHeaderBackground,
|
|
1547
|
-
Order: group.order
|
|
1548
|
-
})) || [],
|
|
1549
|
-
Select: params.select?.map(sel => ({
|
|
1550
|
-
PropertyName: sel.propertyName,
|
|
1551
|
-
DisplayName: sel.displayName,
|
|
1552
|
-
AggregateFunction: sel.aggregateFunction,
|
|
1553
|
-
IsVisible: sel.isVisible ?? true,
|
|
1554
|
-
Order: sel.order
|
|
1555
|
-
})) || [],
|
|
1556
|
-
Aggregates: params.aggregates?.map(agg => ({
|
|
1557
|
-
PropertyName: agg.propertyName,
|
|
1558
|
-
AggregateFunction: agg.aggregateFunction,
|
|
1559
|
-
Alias: agg.alias
|
|
1560
|
-
})) || [],
|
|
1561
|
-
Top: params.top,
|
|
1562
|
-
Skip: params.skip,
|
|
1563
|
-
Expand: params.expand,
|
|
1564
|
-
IncludeCount: params.includeCount
|
|
1565
|
-
};
|
|
1566
|
-
}
|
|
1567
|
-
// Helper method to create query parameters from UI model
|
|
1568
|
-
static fromUIModel(model) {
|
|
1569
|
-
const params = {
|
|
1570
|
-
filters: model.advancedFilters || [],
|
|
1571
|
-
orderBy: model.sorting || [],
|
|
1572
|
-
groupBy: model.grouping || [],
|
|
1573
|
-
select: model.columns || [],
|
|
1574
|
-
aggregates: model.aggregates || [],
|
|
1575
|
-
top: model.pagination?.top,
|
|
1576
|
-
skip: model.pagination?.skip,
|
|
1577
|
-
expand: model.expand,
|
|
1578
|
-
includeCount: model.pagination?.includeCount
|
|
1579
|
-
};
|
|
1580
|
-
return params;
|
|
1357
|
+
}
|
|
1358
|
+
else {
|
|
1359
|
+
console.warn('Unknown redirect type', resolvedRedirect);
|
|
1360
|
+
}
|
|
1581
1361
|
}
|
|
1362
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, deps: [{ token: PermissionCheckerService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1363
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, providedIn: 'root' });
|
|
1582
1364
|
}
|
|
1365
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NgxPermissionsGuard, decorators: [{
|
|
1366
|
+
type: Injectable,
|
|
1367
|
+
args: [{ providedIn: 'root' }]
|
|
1368
|
+
}], ctorParameters: () => [{ type: PermissionCheckerService }, { type: i2.Router }] });
|
|
1583
1369
|
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1370
|
+
// logger.interface.ts
|
|
1371
|
+
var LogLevel;
|
|
1372
|
+
(function (LogLevel) {
|
|
1373
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
1374
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
1375
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
1376
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
1377
|
+
LogLevel[LogLevel["OFF"] = 4] = "OFF";
|
|
1378
|
+
})(LogLevel || (LogLevel = {}));
|
|
1379
|
+
|
|
1380
|
+
// logger.service.ts
|
|
1381
|
+
// Remove the separate LoggerConfig interface since we're using EnvironmentConfig
|
|
1382
|
+
// and extend EnvironmentConfig to include logger-specific properties
|
|
1383
|
+
class LoggerService {
|
|
1384
|
+
level = LogLevel.DEBUG;
|
|
1385
|
+
enableConsole = true;
|
|
1386
|
+
prefix = '[App]';
|
|
1387
|
+
timestamp = true;
|
|
1388
|
+
environmentService = inject(EnvironmentService);
|
|
1389
|
+
environment = this.environmentService?.getEnvironment();
|
|
1390
|
+
constructor() {
|
|
1391
|
+
// Use environment configuration if provided
|
|
1392
|
+
if (this.environment) {
|
|
1393
|
+
this.configureFromEnvironment(this.environment);
|
|
1394
|
+
}
|
|
1395
|
+
// Fallback: In production, default to WARN level
|
|
1396
|
+
if (typeof window !== 'undefined' && window.location.hostname !== 'localhost') {
|
|
1397
|
+
this.level = LogLevel.WARN;
|
|
1398
|
+
this.enableConsole = false;
|
|
1602
1399
|
}
|
|
1603
|
-
this.store.sliceUpdate(state => state).subscribe(this.updateLocalStorage);
|
|
1604
|
-
}
|
|
1605
|
-
setInitialLanguage() {
|
|
1606
|
-
const appLanguage = this.getLanguage();
|
|
1607
|
-
this.configState
|
|
1608
|
-
.getDeep$('localization.currentCulture.cultureName')
|
|
1609
|
-
.pipe(filter(cultureName => !!cultureName), take(1))
|
|
1610
|
-
.subscribe(lang => {
|
|
1611
|
-
if (lang.includes(';')) {
|
|
1612
|
-
lang = lang.split(';')[0];
|
|
1613
|
-
}
|
|
1614
|
-
this.setLanguage(lang);
|
|
1615
|
-
});
|
|
1616
1400
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1401
|
+
configureFromEnvironment(env) {
|
|
1402
|
+
// Map string log levels from environment to LogLevel enum
|
|
1403
|
+
this.level = this.mapLogLevel(env.logLevel);
|
|
1404
|
+
// Use production flag to determine console logging
|
|
1405
|
+
this.enableConsole = !env.production;
|
|
1406
|
+
// Set prefix from environment if available
|
|
1407
|
+
this.prefix = `[${env['appName'] || 'App'}]`;
|
|
1408
|
+
// Enable timestamp in development, disable in production for performance
|
|
1409
|
+
this.timestamp = !env.production;
|
|
1619
1410
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1411
|
+
mapLogLevel(level) {
|
|
1412
|
+
switch (level) {
|
|
1413
|
+
case 'debug': return LogLevel.DEBUG;
|
|
1414
|
+
case 'info': return LogLevel.INFO;
|
|
1415
|
+
case 'warn': return LogLevel.WARN;
|
|
1416
|
+
case 'error': return LogLevel.ERROR;
|
|
1417
|
+
case 'off': return LogLevel.OFF;
|
|
1418
|
+
default: return LogLevel.WARN;
|
|
1419
|
+
}
|
|
1622
1420
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1421
|
+
debug(message, ...args) {
|
|
1422
|
+
if (this.shouldLog(LogLevel.DEBUG)) {
|
|
1423
|
+
this.log('DEBUG', message, args, 'color: blue');
|
|
1424
|
+
}
|
|
1625
1425
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1426
|
+
info(message, ...args) {
|
|
1427
|
+
if (this.shouldLog(LogLevel.INFO)) {
|
|
1428
|
+
this.log('INFO', message, args, 'color: green');
|
|
1429
|
+
}
|
|
1628
1430
|
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1431
|
+
warn(message, ...args) {
|
|
1432
|
+
if (this.shouldLog(LogLevel.WARN)) {
|
|
1433
|
+
this.log('WARN', message, args, 'color: orange');
|
|
1434
|
+
}
|
|
1631
1435
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1436
|
+
error(message, ...args) {
|
|
1437
|
+
if (this.shouldLog(LogLevel.ERROR)) {
|
|
1438
|
+
this.log('ERROR', message, args, 'color: red');
|
|
1439
|
+
// Send to external services only for errors in production
|
|
1440
|
+
if (this.environment?.production) {
|
|
1441
|
+
this.sendToExternalService('ERROR', message, args);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1634
1444
|
}
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
return;
|
|
1638
|
-
this.store.set({ ...this.store.state, tenant });
|
|
1445
|
+
setLogLevel(level) {
|
|
1446
|
+
this.level = level;
|
|
1639
1447
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
return;
|
|
1643
|
-
this.store.set({ ...this.store.state, ...session });
|
|
1448
|
+
shouldLog(level) {
|
|
1449
|
+
return level >= this.level && this.enableConsole;
|
|
1644
1450
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1451
|
+
log(level, message, args, style) {
|
|
1452
|
+
if (!this.enableConsole)
|
|
1453
|
+
return;
|
|
1454
|
+
const timestamp = this.timestamp ? new Date().toISOString() : '';
|
|
1455
|
+
const formattedPrefix = this.prefix ? `${this.prefix}` : '';
|
|
1456
|
+
const logMessage = `${timestamp} ${formattedPrefix} [${level}] ${message}`;
|
|
1457
|
+
if (args.length > 0) {
|
|
1458
|
+
console.log(`%c${logMessage}`, style, ...args);
|
|
1649
1459
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
this.document.documentElement.setAttribute('lang', language);
|
|
1460
|
+
else {
|
|
1461
|
+
console.log(`%c${logMessage}`, style);
|
|
1653
1462
|
}
|
|
1654
1463
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1464
|
+
sendToExternalService(level, message, args) {
|
|
1465
|
+
// Integrate with external logging services from environment
|
|
1466
|
+
try {
|
|
1467
|
+
const sentryUrl = this.environment?.externalServices?.['sentry'];
|
|
1468
|
+
const logRocketUrl = this.environment?.externalServices?.['logRocket'];
|
|
1469
|
+
// Example: Send to configured external services
|
|
1470
|
+
if (sentryUrl) {
|
|
1471
|
+
// this.sendToSentry(level, message, args);
|
|
1472
|
+
}
|
|
1473
|
+
if (logRocketUrl) {
|
|
1474
|
+
// this.sendToLogRocket(level, message, args);
|
|
1475
|
+
}
|
|
1476
|
+
// Send to backend if apiUrl is available
|
|
1477
|
+
if (this.environment?.apis.default.url) {
|
|
1478
|
+
// this.http.post(`${this.environment.apiUrl}/logs`, {
|
|
1479
|
+
// level, message, args, timestamp: new Date()
|
|
1480
|
+
// }).subscribe();
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
catch (error) {
|
|
1484
|
+
// Don't use this.error here to avoid infinite loops
|
|
1485
|
+
console.error('Failed to send log to external service:', error);
|
|
1486
|
+
}
|
|
1657
1487
|
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1488
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1489
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LoggerService, providedIn: 'root' });
|
|
1490
|
+
}
|
|
1491
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: LoggerService, decorators: [{
|
|
1492
|
+
type: Injectable,
|
|
1493
|
+
args: [{
|
|
1494
|
+
providedIn: 'root'
|
|
1495
|
+
}]
|
|
1496
|
+
}], ctorParameters: () => [] });
|
|
1497
|
+
|
|
1498
|
+
class IdParserService {
|
|
1499
|
+
/**
|
|
1500
|
+
* Extract IDs from a model based on comma-separated field names.
|
|
1501
|
+
* Example: "id,biId" => [model.id, model.biId]
|
|
1502
|
+
*/
|
|
1503
|
+
parseIds(model, idField) {
|
|
1504
|
+
if (!idField)
|
|
1505
|
+
return null;
|
|
1506
|
+
const fields = idField.split(',').map(f => f.trim()).filter(Boolean);
|
|
1507
|
+
if (fields.length === 1) {
|
|
1508
|
+
return model[fields[0]];
|
|
1509
|
+
}
|
|
1510
|
+
return fields.map(f => model[f]);
|
|
1660
1511
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1512
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: IdParserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1513
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: IdParserService, providedIn: 'root' });
|
|
1514
|
+
}
|
|
1515
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: IdParserService, decorators: [{
|
|
1516
|
+
type: Injectable,
|
|
1517
|
+
args: [{ providedIn: 'root' }]
|
|
1518
|
+
}] });
|
|
1519
|
+
|
|
1520
|
+
class QueryParser {
|
|
1521
|
+
static parse(queryString) {
|
|
1522
|
+
const params = {
|
|
1523
|
+
filters: [],
|
|
1524
|
+
orderBy: [],
|
|
1525
|
+
groupBy: [],
|
|
1526
|
+
select: [],
|
|
1527
|
+
aggregates: []
|
|
1528
|
+
};
|
|
1529
|
+
if (!queryString)
|
|
1530
|
+
return params;
|
|
1531
|
+
const queryParts = queryString.split('&');
|
|
1532
|
+
for (const part of queryParts) {
|
|
1533
|
+
if (part.startsWith('$filter=')) {
|
|
1534
|
+
this.parseFilter(part.substring('$filter='.length), params);
|
|
1535
|
+
}
|
|
1536
|
+
else if (part.startsWith('$orderby=')) {
|
|
1537
|
+
this.parseOrderBy(part.substring('$orderby='.length), params);
|
|
1538
|
+
}
|
|
1539
|
+
else if (part.startsWith('$groupby=')) {
|
|
1540
|
+
this.parseGroupBy(part.substring('$groupby='.length), params);
|
|
1541
|
+
}
|
|
1542
|
+
else if (part.startsWith('$select=')) {
|
|
1543
|
+
this.parseSelect(part.substring('$select='.length), params);
|
|
1544
|
+
}
|
|
1545
|
+
else if (part.startsWith('$aggregate=')) {
|
|
1546
|
+
this.parseAggregate(part.substring('$aggregate='.length), params);
|
|
1547
|
+
}
|
|
1548
|
+
else if (part.startsWith('$top=')) {
|
|
1549
|
+
params.top = Number(part.substring('$top='.length));
|
|
1550
|
+
}
|
|
1551
|
+
else if (part.startsWith('$skip=')) {
|
|
1552
|
+
params.skip = Number(part.substring('$skip='.length));
|
|
1553
|
+
}
|
|
1554
|
+
else if (part.startsWith('$expand=')) {
|
|
1555
|
+
params.expand = part.substring('$expand='.length).split(',').map(f => f.trim());
|
|
1556
|
+
}
|
|
1557
|
+
else if (part.startsWith('$count=')) {
|
|
1558
|
+
params.includeCount = part.substring('$count='.length).toLowerCase() === 'true';
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
return params;
|
|
1663
1562
|
}
|
|
1664
|
-
|
|
1665
|
-
|
|
1563
|
+
static toString(params) {
|
|
1564
|
+
const parts = [];
|
|
1565
|
+
if (params.filters?.length) {
|
|
1566
|
+
const filterStr = this.buildFilterString(params.filters);
|
|
1567
|
+
parts.push(`$filter=${encodeURIComponent(filterStr)}`);
|
|
1568
|
+
}
|
|
1569
|
+
if (params.orderBy?.length) {
|
|
1570
|
+
const orderByStr = params.orderBy.map(o => `${o.field} ${o.direction}`).join(',');
|
|
1571
|
+
parts.push(`$orderby=${encodeURIComponent(orderByStr)}`);
|
|
1572
|
+
}
|
|
1573
|
+
if (params.groupBy?.length) {
|
|
1574
|
+
const groupByStr = this.buildGroupByString(params.groupBy);
|
|
1575
|
+
parts.push(`$groupby=${encodeURIComponent(groupByStr)}`);
|
|
1576
|
+
}
|
|
1577
|
+
if (params.select?.length) {
|
|
1578
|
+
const selectStr = this.buildSelectString(params.select);
|
|
1579
|
+
parts.push(`$select=${encodeURIComponent(selectStr)}`);
|
|
1580
|
+
}
|
|
1581
|
+
if (params.aggregates?.length) {
|
|
1582
|
+
const aggregateStr = this.buildAggregateString(params.aggregates);
|
|
1583
|
+
parts.push(`$aggregate=${encodeURIComponent(aggregateStr)}`);
|
|
1584
|
+
}
|
|
1585
|
+
if (params.top !== undefined) {
|
|
1586
|
+
parts.push(`$top=${params.top}`);
|
|
1587
|
+
}
|
|
1588
|
+
if (params.skip !== undefined) {
|
|
1589
|
+
parts.push(`$skip=${params.skip}`);
|
|
1590
|
+
}
|
|
1591
|
+
if (params.expand?.length) {
|
|
1592
|
+
parts.push(`$expand=${encodeURIComponent(params.expand.join(','))}`);
|
|
1593
|
+
}
|
|
1594
|
+
if (params.includeCount !== undefined) {
|
|
1595
|
+
parts.push(`$count=${params.includeCount}`);
|
|
1596
|
+
}
|
|
1597
|
+
return parts.join('&');
|
|
1666
1598
|
}
|
|
1667
|
-
|
|
1668
|
-
return
|
|
1599
|
+
static buildFilterString(filters) {
|
|
1600
|
+
return filters.map((group, index) => {
|
|
1601
|
+
const groupStr = group.conditions
|
|
1602
|
+
.map(condition => {
|
|
1603
|
+
let val = condition.value;
|
|
1604
|
+
if (typeof val === 'string') {
|
|
1605
|
+
val = `'${val.replace(/'/g, "''")}'`;
|
|
1606
|
+
}
|
|
1607
|
+
else if (typeof val === 'boolean') {
|
|
1608
|
+
val = val ? 'true' : 'false';
|
|
1609
|
+
}
|
|
1610
|
+
return `${condition.field} ${condition.operator} ${val}`;
|
|
1611
|
+
})
|
|
1612
|
+
.join(` ${group.logicalOperator} `);
|
|
1613
|
+
// For the first group, no groupLogicalOperator is needed
|
|
1614
|
+
if (index === 0) {
|
|
1615
|
+
return group.conditions.length > 1 ? `(${groupStr})` : groupStr;
|
|
1616
|
+
}
|
|
1617
|
+
else {
|
|
1618
|
+
const joinOp = group.groupLogicalOperator || 'and';
|
|
1619
|
+
return group.conditions.length > 1 ? `${joinOp} (${groupStr})` : `${joinOp} ${groupStr}`;
|
|
1620
|
+
}
|
|
1621
|
+
}).join(' ');
|
|
1669
1622
|
}
|
|
1670
|
-
|
|
1671
|
-
return
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1623
|
+
static buildGroupByString(groupBy) {
|
|
1624
|
+
return groupBy
|
|
1625
|
+
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
1626
|
+
.map(group => {
|
|
1627
|
+
let groupStr = group.propertyName;
|
|
1628
|
+
// Add display name if provided
|
|
1629
|
+
if (group.displayName) {
|
|
1630
|
+
groupStr += ` as ${group.displayName}`;
|
|
1631
|
+
}
|
|
1632
|
+
// Add metadata for UI
|
|
1633
|
+
const metadata = [];
|
|
1634
|
+
if (group.showTotal !== undefined) {
|
|
1635
|
+
metadata.push(`showTotal:${group.showTotal}`);
|
|
1636
|
+
}
|
|
1637
|
+
if (group.totalBackground) {
|
|
1638
|
+
metadata.push(`totalBg:${group.totalBackground}`);
|
|
1639
|
+
}
|
|
1640
|
+
if (group.groupHeaderBackground) {
|
|
1641
|
+
metadata.push(`headerBg:${group.groupHeaderBackground}`);
|
|
1642
|
+
}
|
|
1643
|
+
if (metadata.length > 0) {
|
|
1644
|
+
groupStr += `(${metadata.join(';')})`;
|
|
1645
|
+
}
|
|
1646
|
+
return groupStr;
|
|
1647
|
+
})
|
|
1648
|
+
.join(',');
|
|
1676
1649
|
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1650
|
+
static buildSelectString(select) {
|
|
1651
|
+
return select
|
|
1652
|
+
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
1653
|
+
.map(item => {
|
|
1654
|
+
let selectStr = item.propertyName;
|
|
1655
|
+
// Add display name if provided
|
|
1656
|
+
if (item.displayName) {
|
|
1657
|
+
selectStr += ` as ${item.displayName}`;
|
|
1658
|
+
}
|
|
1659
|
+
// Add aggregate function if provided
|
|
1660
|
+
if (item.aggregateFunction) {
|
|
1661
|
+
selectStr += ` with ${item.aggregateFunction}`;
|
|
1662
|
+
}
|
|
1663
|
+
// Add visibility metadata
|
|
1664
|
+
const metadata = [];
|
|
1665
|
+
if (item.isVisible !== undefined) {
|
|
1666
|
+
metadata.push(`visible:${item.isVisible}`);
|
|
1667
|
+
}
|
|
1668
|
+
if (metadata.length > 0) {
|
|
1669
|
+
selectStr += `(${metadata.join(';')})`;
|
|
1670
|
+
}
|
|
1671
|
+
return selectStr;
|
|
1672
|
+
})
|
|
1673
|
+
.join(',');
|
|
1680
1674
|
}
|
|
1681
|
-
|
|
1682
|
-
return
|
|
1675
|
+
static buildAggregateString(aggregates) {
|
|
1676
|
+
return aggregates
|
|
1677
|
+
.map(agg => {
|
|
1678
|
+
let aggStr = `${agg.aggregateFunction}(${agg.propertyName})`;
|
|
1679
|
+
if (agg.alias) {
|
|
1680
|
+
aggStr += ` as ${agg.alias}`;
|
|
1681
|
+
}
|
|
1682
|
+
return aggStr;
|
|
1683
|
+
})
|
|
1684
|
+
.join(',');
|
|
1683
1685
|
}
|
|
1684
|
-
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
|
|
1686
|
+
static parseFilter(filterString, params) {
|
|
1687
|
+
const decodedString = decodeURIComponent(filterString);
|
|
1688
|
+
const groups = [];
|
|
1689
|
+
// Split by top-level AND/OR operators
|
|
1690
|
+
const topLevelPattern = /(?:^|\s)(and|or)\s+(?=(?:[^()]*\([^()]*\))*[^()]*$)/gi;
|
|
1691
|
+
const segments = [];
|
|
1692
|
+
let lastIndex = 0;
|
|
1693
|
+
let match;
|
|
1694
|
+
while ((match = topLevelPattern.exec(decodedString)) !== null) {
|
|
1695
|
+
const operator = match[1];
|
|
1696
|
+
const segment = decodedString.substring(lastIndex, match.index).trim();
|
|
1697
|
+
if (segment) {
|
|
1698
|
+
segments.push({ condition: segment, operator });
|
|
1699
|
+
}
|
|
1700
|
+
lastIndex = match.index + match[0].length;
|
|
1688
1701
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
return false;
|
|
1702
|
+
// Add the last segment
|
|
1703
|
+
const lastSegment = decodedString.substring(lastIndex).trim();
|
|
1704
|
+
if (lastSegment) {
|
|
1705
|
+
segments.push({ condition: lastSegment, operator: undefined });
|
|
1694
1706
|
}
|
|
1695
|
-
//
|
|
1696
|
-
|
|
1697
|
-
|
|
1707
|
+
// Parse each segment
|
|
1708
|
+
segments.forEach((segment, index) => {
|
|
1709
|
+
let conditions = [];
|
|
1710
|
+
// Check if it's a group with parentheses
|
|
1711
|
+
if (segment.condition.startsWith('(') && segment.condition.endsWith(')')) {
|
|
1712
|
+
const innerCondition = segment.condition.slice(1, -1).trim();
|
|
1713
|
+
conditions = this.parseConditions(innerCondition);
|
|
1714
|
+
}
|
|
1715
|
+
else {
|
|
1716
|
+
// Individual condition
|
|
1717
|
+
conditions = this.parseConditions(segment.condition);
|
|
1718
|
+
}
|
|
1719
|
+
if (conditions.length > 0) {
|
|
1720
|
+
const group = {
|
|
1721
|
+
logicalOperator: 'and',
|
|
1722
|
+
conditions: conditions
|
|
1723
|
+
};
|
|
1724
|
+
// For groups after the first, set the groupLogicalOperator
|
|
1725
|
+
if (index > 0) {
|
|
1726
|
+
group.groupLogicalOperator = segment.operator?.toLowerCase() || 'and';
|
|
1727
|
+
}
|
|
1728
|
+
// Detect the logical operator used within the group
|
|
1729
|
+
if (conditions.length === 1 && segment.condition.includes(' or ')) {
|
|
1730
|
+
group.logicalOperator = 'or';
|
|
1731
|
+
}
|
|
1732
|
+
else if (conditions.length > 1) {
|
|
1733
|
+
group.logicalOperator = segment.condition.toLowerCase().includes(' or ') ? 'or' : 'and';
|
|
1734
|
+
}
|
|
1735
|
+
groups.push(group);
|
|
1736
|
+
}
|
|
1737
|
+
});
|
|
1738
|
+
params.filters = groups;
|
|
1698
1739
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1740
|
+
static parseConditions(conditionString) {
|
|
1741
|
+
const conditions = [];
|
|
1742
|
+
// Enhanced pattern to handle more operators and complex values
|
|
1743
|
+
const pattern = /(\w+(?:\.\w+)*)\s+(eq|ne|gt|ge|lt|le|contains|startswith|endswith|in|notin)\s+('[^']*'|\[[^\]]*\]|\d+|true|false|null)/gi;
|
|
1744
|
+
let match;
|
|
1745
|
+
while ((match = pattern.exec(conditionString)) !== null) {
|
|
1746
|
+
const [, field, operator, rawValue] = match;
|
|
1747
|
+
let value = rawValue.trim();
|
|
1748
|
+
if (rawValue.startsWith("'") && rawValue.endsWith("'")) {
|
|
1749
|
+
value = rawValue.slice(1, -1).replace(/''/g, "'");
|
|
1750
|
+
}
|
|
1751
|
+
else if (rawValue.startsWith('[') && rawValue.endsWith(']')) {
|
|
1752
|
+
// Handle array values for IN/NOT IN operators
|
|
1753
|
+
value = rawValue.slice(1, -1).split(',').map(v => {
|
|
1754
|
+
const trimmed = v.trim().replace(/^'|'$/g, '');
|
|
1755
|
+
return isNaN(Number(trimmed)) ? trimmed : Number(trimmed);
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
else if (!isNaN(Number(rawValue))) {
|
|
1759
|
+
value = Number(rawValue);
|
|
1760
|
+
}
|
|
1761
|
+
else if (rawValue.toLowerCase() === 'true') {
|
|
1762
|
+
value = true;
|
|
1763
|
+
}
|
|
1764
|
+
else if (rawValue.toLowerCase() === 'false') {
|
|
1765
|
+
value = false;
|
|
1766
|
+
}
|
|
1767
|
+
else if (rawValue.toLowerCase() === 'null') {
|
|
1768
|
+
value = null;
|
|
1769
|
+
}
|
|
1770
|
+
conditions.push({
|
|
1771
|
+
field: field.trim(),
|
|
1772
|
+
operator: operator.trim().toLowerCase(),
|
|
1773
|
+
value
|
|
1774
|
+
});
|
|
1709
1775
|
}
|
|
1710
|
-
return
|
|
1711
|
-
}
|
|
1712
|
-
get impersonatorUser() {
|
|
1713
|
-
return this.store.state.impersonatorUser;
|
|
1714
|
-
}
|
|
1715
|
-
get impersonatorUserId() {
|
|
1716
|
-
return this.impersonatorUser ? this.impersonatorUser.id : 0;
|
|
1717
|
-
}
|
|
1718
|
-
get impersonatorTenant() {
|
|
1719
|
-
return this.store.state.impersonatorTenant;
|
|
1720
|
-
}
|
|
1721
|
-
get impersonatorTenancyName() {
|
|
1722
|
-
return this.impersonatorTenant ? this.impersonatorTenant?.tenancyName ?? '' : '';
|
|
1723
|
-
}
|
|
1724
|
-
get impersonatorTenantId() {
|
|
1725
|
-
return this.impersonatorTenant ? this.impersonatorTenant.id : 0;
|
|
1726
|
-
}
|
|
1727
|
-
get multiTenancySide() {
|
|
1728
|
-
// return this.configState.session?.multiTenancySide;
|
|
1729
|
-
return 0;
|
|
1730
|
-
}
|
|
1731
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, deps: [{ token: ConfigStateService }, { token: SsrCookieService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1732
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, providedIn: 'root' });
|
|
1733
|
-
}
|
|
1734
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: SessionStateService, decorators: [{
|
|
1735
|
-
type: Injectable,
|
|
1736
|
-
args: [{
|
|
1737
|
-
providedIn: 'root',
|
|
1738
|
-
}]
|
|
1739
|
-
}], ctorParameters: () => [{ type: ConfigStateService }, { type: SsrCookieService }] });
|
|
1740
|
-
|
|
1741
|
-
class LocalizationService {
|
|
1742
|
-
sessionState;
|
|
1743
|
-
injector;
|
|
1744
|
-
configState;
|
|
1745
|
-
latestLang = 'ar';
|
|
1746
|
-
_languageChange$ = new Subject();
|
|
1747
|
-
uiLocalizations$ = new BehaviorSubject(new Map());
|
|
1748
|
-
localizations$ = new BehaviorSubject(new Map());
|
|
1749
|
-
/**
|
|
1750
|
-
* Returns currently selected language
|
|
1751
|
-
* Even though this looks like it's redundant to return the same value as `getLanguage()`,
|
|
1752
|
-
* it's actually not. This could be invoked any time, and the latestLang could be different from the
|
|
1753
|
-
* sessionState.getLanguage() value.
|
|
1754
|
-
*/
|
|
1755
|
-
get currentLanguage() {
|
|
1756
|
-
return this.latestLang || this.sessionState.getLanguage();
|
|
1757
|
-
}
|
|
1758
|
-
get currentLang() {
|
|
1759
|
-
return this.latestLang || this.sessionState.getLanguage();
|
|
1760
|
-
}
|
|
1761
|
-
get currentLang$() {
|
|
1762
|
-
return this.sessionState.getLanguage$();
|
|
1776
|
+
return conditions;
|
|
1763
1777
|
}
|
|
1764
|
-
|
|
1765
|
-
|
|
1778
|
+
static parseOrderBy(orderByString, params) {
|
|
1779
|
+
const decodedString = decodeURIComponent(orderByString);
|
|
1780
|
+
const clauses = decodedString.split(',');
|
|
1781
|
+
for (const clause of clauses) {
|
|
1782
|
+
const parts = clause.trim().split(/\s+/);
|
|
1783
|
+
const field = parts[0];
|
|
1784
|
+
const direction = parts[1]?.toLowerCase() || 'asc';
|
|
1785
|
+
params.orderBy?.push({
|
|
1786
|
+
field,
|
|
1787
|
+
direction
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1766
1790
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1791
|
+
static parseGroupBy(groupByString, params) {
|
|
1792
|
+
const decodedString = decodeURIComponent(groupByString);
|
|
1793
|
+
const groups = decodedString.split(',');
|
|
1794
|
+
params.groupBy = groups.map((groupStr, index) => {
|
|
1795
|
+
const group = {
|
|
1796
|
+
propertyName: '',
|
|
1797
|
+
order: index
|
|
1798
|
+
};
|
|
1799
|
+
// Check for metadata in parentheses
|
|
1800
|
+
const metadataMatch = groupStr.match(/^(.*?)\((.*)\)$/);
|
|
1801
|
+
let baseStr = groupStr;
|
|
1802
|
+
let metadataStr = '';
|
|
1803
|
+
if (metadataMatch) {
|
|
1804
|
+
baseStr = metadataMatch[1];
|
|
1805
|
+
metadataStr = metadataMatch[2];
|
|
1806
|
+
}
|
|
1807
|
+
// Check for display name alias
|
|
1808
|
+
const aliasMatch = baseStr.match(/^(.*?)\s+as\s+(.*)$/);
|
|
1809
|
+
if (aliasMatch) {
|
|
1810
|
+
group.propertyName = aliasMatch[1].trim();
|
|
1811
|
+
group.displayName = aliasMatch[2].trim();
|
|
1812
|
+
}
|
|
1813
|
+
else {
|
|
1814
|
+
group.propertyName = baseStr.trim();
|
|
1815
|
+
}
|
|
1816
|
+
// Parse metadata
|
|
1817
|
+
if (metadataStr) {
|
|
1818
|
+
const metadataParts = metadataStr.split(';');
|
|
1819
|
+
metadataParts.forEach(part => {
|
|
1820
|
+
const [key, value] = part.split(':');
|
|
1821
|
+
switch (key) {
|
|
1822
|
+
case 'showTotal':
|
|
1823
|
+
group.showTotal = value.toLowerCase() === 'true';
|
|
1824
|
+
break;
|
|
1825
|
+
case 'totalBg':
|
|
1826
|
+
group.totalBackground = value;
|
|
1827
|
+
break;
|
|
1828
|
+
case 'headerBg':
|
|
1829
|
+
group.groupHeaderBackground = value;
|
|
1830
|
+
break;
|
|
1831
|
+
}
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
return group;
|
|
1835
|
+
});
|
|
1776
1836
|
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
const
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1837
|
+
static parseSelect(selectString, params) {
|
|
1838
|
+
const decodedString = decodeURIComponent(selectString);
|
|
1839
|
+
const items = decodedString.split(',');
|
|
1840
|
+
params.select = items.map((itemStr, index) => {
|
|
1841
|
+
const item = {
|
|
1842
|
+
propertyName: '',
|
|
1843
|
+
isVisible: true,
|
|
1844
|
+
order: index
|
|
1845
|
+
};
|
|
1846
|
+
// Check for metadata in parentheses
|
|
1847
|
+
const metadataMatch = itemStr.match(/^(.*?)\((.*)\)$/);
|
|
1848
|
+
let baseStr = itemStr;
|
|
1849
|
+
let metadataStr = '';
|
|
1850
|
+
if (metadataMatch) {
|
|
1851
|
+
baseStr = metadataMatch[1];
|
|
1852
|
+
metadataStr = metadataMatch[2];
|
|
1787
1853
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1854
|
+
// Check for display name alias and aggregate function
|
|
1855
|
+
const aliasMatch = baseStr.match(/^(.*?)(?:\s+as\s+(.*?))?(?:\s+with\s+(\w+))?$/);
|
|
1856
|
+
if (aliasMatch) {
|
|
1857
|
+
item.propertyName = aliasMatch[1].trim();
|
|
1858
|
+
if (aliasMatch[2]) {
|
|
1859
|
+
item.displayName = aliasMatch[2].trim();
|
|
1792
1860
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1861
|
+
if (aliasMatch[3]) {
|
|
1862
|
+
item.aggregateFunction = aliasMatch[3].trim();
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
else {
|
|
1866
|
+
item.propertyName = baseStr.trim();
|
|
1867
|
+
}
|
|
1868
|
+
// Parse metadata
|
|
1869
|
+
if (metadataStr) {
|
|
1870
|
+
const metadataParts = metadataStr.split(';');
|
|
1871
|
+
metadataParts.forEach(part => {
|
|
1872
|
+
const [key, value] = part.split(':');
|
|
1873
|
+
if (key === 'visible') {
|
|
1874
|
+
item.isVisible = value.toLowerCase() === 'true';
|
|
1875
|
+
}
|
|
1799
1876
|
});
|
|
1800
1877
|
}
|
|
1801
|
-
return
|
|
1802
|
-
}), filter(Boolean))
|
|
1803
|
-
.subscribe(val => this.localizations$.next(val));
|
|
1804
|
-
}
|
|
1805
|
-
addLocalization(localizations) {
|
|
1806
|
-
if (!localizations)
|
|
1807
|
-
return;
|
|
1808
|
-
const localizationMap = this.uiLocalizations$.value;
|
|
1809
|
-
localizations.forEach(loc => {
|
|
1810
|
-
const cultureMap = localizationMap.get(loc.culture) || new Map();
|
|
1811
|
-
loc.resources.forEach(res => {
|
|
1812
|
-
let resource = cultureMap.get(res.resourceName) || {};
|
|
1813
|
-
resource = { ...resource, ...res.texts };
|
|
1814
|
-
cultureMap.set(res.resourceName, resource);
|
|
1815
|
-
});
|
|
1816
|
-
localizationMap.set(loc.culture, cultureMap);
|
|
1878
|
+
return item;
|
|
1817
1879
|
});
|
|
1818
|
-
this.uiLocalizations$.next(localizationMap);
|
|
1819
|
-
}
|
|
1820
|
-
listenToSetLanguage() {
|
|
1821
|
-
this.sessionState
|
|
1822
|
-
.onLanguageChange$()
|
|
1823
|
-
.pipe(filter(lang => this.configState.getDeep('localization.currentCulture.cultureName') !== lang), switchMap((lang) => this.configState.refreshLocalization(lang).pipe(map(() => lang))), filter(Boolean), switchMap((lang) => from(this.registerLocale(lang).then(() => lang))))
|
|
1824
|
-
.subscribe((lang) => this._languageChange$.next(lang));
|
|
1825
1880
|
}
|
|
1826
|
-
|
|
1827
|
-
const
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1881
|
+
static parseAggregate(aggregateString, params) {
|
|
1882
|
+
const decodedString = decodeURIComponent(aggregateString);
|
|
1883
|
+
const aggregates = decodedString.split(',');
|
|
1884
|
+
params.aggregates = aggregates.map(aggStr => {
|
|
1885
|
+
const agg = {
|
|
1886
|
+
propertyName: '',
|
|
1887
|
+
aggregateFunction: ''
|
|
1888
|
+
};
|
|
1889
|
+
// Match pattern: function(property) as alias
|
|
1890
|
+
const match = aggStr.match(/^(\w+)\((\w+)\)(?:\s+as\s+(\w+))?$/);
|
|
1891
|
+
if (match) {
|
|
1892
|
+
agg.aggregateFunction = match[1];
|
|
1893
|
+
agg.propertyName = match[2];
|
|
1894
|
+
if (match[3]) {
|
|
1895
|
+
agg.alias = match[3];
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
return agg;
|
|
1832
1899
|
});
|
|
1833
1900
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
}
|
|
1875
|
-
localizeWithFallbackSync(resourceNames, keys, defaultValue) {
|
|
1876
|
-
const localization = this.configState.getOne('localization');
|
|
1877
|
-
return createLocalizerWithFallback(localization)(resourceNames, keys, defaultValue);
|
|
1878
|
-
}
|
|
1879
|
-
getLocalization(state, key, ...interpolateParams) {
|
|
1880
|
-
let defaultValue = '';
|
|
1881
|
-
if (!key) {
|
|
1882
|
-
return defaultValue;
|
|
1883
|
-
}
|
|
1884
|
-
if (typeof key !== 'string') {
|
|
1885
|
-
defaultValue = key.defaultValue;
|
|
1886
|
-
key = key.key;
|
|
1887
|
-
}
|
|
1888
|
-
const keys = key.split('::');
|
|
1889
|
-
const warn = (message) => {
|
|
1890
|
-
if (isDevMode())
|
|
1891
|
-
console.warn(message);
|
|
1901
|
+
// Helper method to convert QueryParameters to ODataQueryParameters (C# equivalent)
|
|
1902
|
+
static toODataQueryParameters(params) {
|
|
1903
|
+
return {
|
|
1904
|
+
Filters: params.filters.map(group => ({
|
|
1905
|
+
LogicalOperator: group.logicalOperator,
|
|
1906
|
+
GroupLogicalOperator: group.groupLogicalOperator,
|
|
1907
|
+
Conditions: group.conditions.map(cond => ({
|
|
1908
|
+
Field: cond.field,
|
|
1909
|
+
Operator: cond.operator,
|
|
1910
|
+
Value: cond.value
|
|
1911
|
+
}))
|
|
1912
|
+
})),
|
|
1913
|
+
OrderBy: params.orderBy?.map(order => ({
|
|
1914
|
+
Field: order.field,
|
|
1915
|
+
Direction: order.direction
|
|
1916
|
+
})) || [],
|
|
1917
|
+
GroupBy: params.groupBy?.map(group => ({
|
|
1918
|
+
PropertyName: group.propertyName,
|
|
1919
|
+
DisplayName: group.displayName,
|
|
1920
|
+
ShowTotal: group.showTotal ?? true,
|
|
1921
|
+
TotalBackground: group.totalBackground,
|
|
1922
|
+
GroupHeaderBackground: group.groupHeaderBackground,
|
|
1923
|
+
Order: group.order
|
|
1924
|
+
})) || [],
|
|
1925
|
+
Select: params.select?.map(sel => ({
|
|
1926
|
+
PropertyName: sel.propertyName,
|
|
1927
|
+
DisplayName: sel.displayName,
|
|
1928
|
+
AggregateFunction: sel.aggregateFunction,
|
|
1929
|
+
IsVisible: sel.isVisible ?? true,
|
|
1930
|
+
Order: sel.order
|
|
1931
|
+
})) || [],
|
|
1932
|
+
Aggregates: params.aggregates?.map(agg => ({
|
|
1933
|
+
PropertyName: agg.propertyName,
|
|
1934
|
+
AggregateFunction: agg.aggregateFunction,
|
|
1935
|
+
Alias: agg.alias
|
|
1936
|
+
})) || [],
|
|
1937
|
+
Top: params.top,
|
|
1938
|
+
Skip: params.skip,
|
|
1939
|
+
Expand: params.expand,
|
|
1940
|
+
IncludeCount: params.includeCount
|
|
1892
1941
|
};
|
|
1893
|
-
if (keys.length < 2) {
|
|
1894
|
-
warn('The localization source separator (::) not found.');
|
|
1895
|
-
return defaultValue || key;
|
|
1896
|
-
}
|
|
1897
|
-
if (!state.localization)
|
|
1898
|
-
return defaultValue || keys[1];
|
|
1899
|
-
const sourceName = keys[0] || state.localization.defaultResourceName;
|
|
1900
|
-
const sourceKey = keys[1];
|
|
1901
|
-
if (sourceName === '_') {
|
|
1902
|
-
return defaultValue || sourceKey;
|
|
1903
|
-
}
|
|
1904
|
-
if (!sourceName) {
|
|
1905
|
-
warn('Localization source name is not specified and the defaultResourceName was not defined!');
|
|
1906
|
-
return defaultValue || sourceKey;
|
|
1907
|
-
}
|
|
1908
|
-
const source = this.localizations$.value.get(sourceName);
|
|
1909
|
-
if (!source) {
|
|
1910
|
-
warn('Could not find localization source: ' + sourceName);
|
|
1911
|
-
return defaultValue || sourceKey;
|
|
1912
|
-
}
|
|
1913
|
-
let localization = source[sourceKey];
|
|
1914
|
-
if (typeof localization === 'undefined') {
|
|
1915
|
-
return defaultValue || sourceKey;
|
|
1916
|
-
}
|
|
1917
|
-
interpolateParams = interpolateParams.filter(params => params != null);
|
|
1918
|
-
if (localization)
|
|
1919
|
-
localization = interpolate(localization, interpolateParams);
|
|
1920
|
-
if (typeof localization !== 'string')
|
|
1921
|
-
localization = '';
|
|
1922
|
-
return localization || defaultValue || key;
|
|
1923
1942
|
}
|
|
1924
|
-
|
|
1925
|
-
static
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
return item;
|
|
1943
|
+
// Helper method to create query parameters from UI model
|
|
1944
|
+
static fromUIModel(model) {
|
|
1945
|
+
const params = {
|
|
1946
|
+
filters: model.advancedFilters || [],
|
|
1947
|
+
orderBy: model.sorting || [],
|
|
1948
|
+
groupBy: model.grouping || [],
|
|
1949
|
+
select: model.columns || [],
|
|
1950
|
+
aggregates: model.aggregates || [],
|
|
1951
|
+
top: model.pagination?.top,
|
|
1952
|
+
skip: model.pagination?.skip,
|
|
1953
|
+
expand: model.expand,
|
|
1954
|
+
includeCount: model.pagination?.includeCount
|
|
1955
|
+
};
|
|
1956
|
+
return params;
|
|
1939
1957
|
}
|
|
1940
|
-
return item.baseResources.reduce((acc, baseResource) => {
|
|
1941
|
-
const baseItem = recursivelyMergeBaseResources(baseResource, source);
|
|
1942
|
-
const texts = { ...baseItem.texts, ...item.texts };
|
|
1943
|
-
return { ...acc, texts };
|
|
1944
|
-
}, item);
|
|
1945
|
-
}
|
|
1946
|
-
function mergeResourcesWithBaseResource(resource) {
|
|
1947
|
-
const entities = Object.keys(resource).map(key => {
|
|
1948
|
-
const newValue = recursivelyMergeBaseResources(key, resource);
|
|
1949
|
-
return [key, newValue];
|
|
1950
|
-
});
|
|
1951
|
-
return entities.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
|
|
1952
|
-
}
|
|
1953
|
-
function combineLegacyandNewResources(legacy, resource) {
|
|
1954
|
-
const mergedResource = mergeResourcesWithBaseResource(resource);
|
|
1955
|
-
return Object.entries(mergedResource).reduce((acc, [key, value]) => {
|
|
1956
|
-
return { ...acc, [key]: value.texts };
|
|
1957
|
-
}, legacy);
|
|
1958
1958
|
}
|
|
1959
1959
|
|
|
1960
1960
|
class LocalStorageListenerService {
|
|
@@ -2994,7 +2994,7 @@ async function getInitialData() {
|
|
|
2994
2994
|
if (!options.skipInitAuthService && authService) {
|
|
2995
2995
|
await authService.init();
|
|
2996
2996
|
}
|
|
2997
|
-
if (options.skipGetAppConfiguration)
|
|
2997
|
+
if (options.skipGetAppConfiguration || authService?.isAuthenticated == false)
|
|
2998
2998
|
return;
|
|
2999
2999
|
const result$ = configState.refreshAppState().pipe(tap(() => checkAuthenticationState(injector)), tap(() => {
|
|
3000
3000
|
const currentTenant = configState.getOne('currentTenant');
|