ngx-dsxlibrary 1.21.13 → 1.21.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngx-dsxlibrary-src-lib-components.mjs +6 -6
- package/fesm2022/ngx-dsxlibrary-src-lib-pipe.mjs +6 -6
- package/fesm2022/ngx-dsxlibrary.mjs +580 -94
- package/fesm2022/ngx-dsxlibrary.mjs.map +1 -1
- package/ngx-dsxlibrary-1.21.16.tgz +0 -0
- package/package.json +1 -1
- package/types/ngx-dsxlibrary-src-lib-models.d.ts +61 -1
- package/types/ngx-dsxlibrary.d.ts +407 -21
- package/ngx-dsxlibrary-1.21.13.tgz +0 -0
|
@@ -19,6 +19,7 @@ import * as i1$2 from 'primeng/menubar';
|
|
|
19
19
|
import { MenubarModule } from 'primeng/menubar';
|
|
20
20
|
import { ToastrService } from 'ngx-toastr';
|
|
21
21
|
import Swal from 'sweetalert2';
|
|
22
|
+
import { Router } from '@angular/router';
|
|
22
23
|
import { JwtHelperService } from '@auth0/angular-jwt';
|
|
23
24
|
import { CookieService } from 'ngx-cookie-service';
|
|
24
25
|
import { AccordionModule } from 'primeng/accordion';
|
|
@@ -54,17 +55,16 @@ import { TextareaModule } from 'primeng/textarea';
|
|
|
54
55
|
import { ToastModule } from 'primeng/toast';
|
|
55
56
|
import { ToggleButtonModule } from 'primeng/togglebutton';
|
|
56
57
|
import { TooltipModule } from 'primeng/tooltip';
|
|
57
|
-
import { Router } from '@angular/router';
|
|
58
58
|
import moment from 'moment-timezone';
|
|
59
59
|
|
|
60
60
|
class AppMessageErrorComponent {
|
|
61
61
|
// Control de formulario que se pasa como input
|
|
62
62
|
control;
|
|
63
63
|
form = null;
|
|
64
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
65
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.
|
|
64
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AppMessageErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
65
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: AppMessageErrorComponent, isStandalone: true, selector: "app-message-error", inputs: { control: "control", form: "form" }, ngImport: i0, template: "@if(control?.touched && control?.invalid){\r\n<div class=\"absolute dsx-error-message\">\r\n @if(control?.errors?.['required']){ El campo <strong>es requerido.</strong>\r\n } @else if(control?.errors?.['invalidNIT']){\r\n <strong>{{ control?.errors?.['invalidNIT']?.message }}</strong\r\n >. }@else if(control?.errors?.['invalidCUI']){\r\n <strong>{{ control?.errors?.['invalidCUI']?.message }}</strong\r\n >. } @else if(control?.errors?.['invalidDateRange']){\r\n <strong>{{ control?.errors?.['invalidDateRange']?.message }}</strong\r\n >. } @else if(control?.errors?.['dateNotRange']){\r\n <strong>{{ control?.errors?.['dateNotRange']?.message }}</strong\r\n >. } @else if(control?.errors?.['minlength']){ Debe tener al menos\r\n <strong>{{ control?.errors?.['minlength']?.requiredLength }}</strong>\r\n caracteres. } @else if(control?.errors?.['maxlength']){ Debe tener como m\u00E1ximo\r\n <strong>{{ control?.errors?.['maxlength']?.requiredLength }}</strong>\r\n caracteres. } @else if(control?.errors?.['min']){ El valor m\u00EDnimo permitido es\r\n <strong>{{ control?.errors?.['min']?.min }}</strong\r\n >. } @else if(control?.errors?.['max']){ El valor m\u00E1ximo permitido es\r\n <strong>{{ control?.errors?.['max']?.max | number:'1.2-2' }}</strong\r\n >. } @else if(control?.errors?.['email']){ Debe ser una direcci\u00F3n de correo\r\n v\u00E1lida. } @else if(control?.errors?.['pattern']){ El campo no tiene el formato\r\n requerido. } @else{ Existe un error a\u00FAn no identificado. }\r\n</div>\r\n}\r\n<!-- mensaje para formulario en general -->\r\n@if(form?.invalid && form?.touched){\r\n<div class=\"mt-2 mb-2\">\r\n @if(this.form?.errors?.['atLeastOneRequired']){\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ form?.getError(\"atLeastOneRequired\")?.message }}</p-tag\r\n >\r\n }\r\n</div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: TagModule }, { kind: "component", type: i1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "pipe", type: DecimalPipe, name: "number" }] });
|
|
66
66
|
}
|
|
67
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
67
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AppMessageErrorComponent, decorators: [{
|
|
68
68
|
type: Component,
|
|
69
69
|
args: [{ selector: 'app-message-error', imports: [TagModule, DecimalPipe], template: "@if(control?.touched && control?.invalid){\r\n<div class=\"absolute dsx-error-message\">\r\n @if(control?.errors?.['required']){ El campo <strong>es requerido.</strong>\r\n } @else if(control?.errors?.['invalidNIT']){\r\n <strong>{{ control?.errors?.['invalidNIT']?.message }}</strong\r\n >. }@else if(control?.errors?.['invalidCUI']){\r\n <strong>{{ control?.errors?.['invalidCUI']?.message }}</strong\r\n >. } @else if(control?.errors?.['invalidDateRange']){\r\n <strong>{{ control?.errors?.['invalidDateRange']?.message }}</strong\r\n >. } @else if(control?.errors?.['dateNotRange']){\r\n <strong>{{ control?.errors?.['dateNotRange']?.message }}</strong\r\n >. } @else if(control?.errors?.['minlength']){ Debe tener al menos\r\n <strong>{{ control?.errors?.['minlength']?.requiredLength }}</strong>\r\n caracteres. } @else if(control?.errors?.['maxlength']){ Debe tener como m\u00E1ximo\r\n <strong>{{ control?.errors?.['maxlength']?.requiredLength }}</strong>\r\n caracteres. } @else if(control?.errors?.['min']){ El valor m\u00EDnimo permitido es\r\n <strong>{{ control?.errors?.['min']?.min }}</strong\r\n >. } @else if(control?.errors?.['max']){ El valor m\u00E1ximo permitido es\r\n <strong>{{ control?.errors?.['max']?.max | number:'1.2-2' }}</strong\r\n >. } @else if(control?.errors?.['email']){ Debe ser una direcci\u00F3n de correo\r\n v\u00E1lida. } @else if(control?.errors?.['pattern']){ El campo no tiene el formato\r\n requerido. } @else{ Existe un error a\u00FAn no identificado. }\r\n</div>\r\n}\r\n<!-- mensaje para formulario en general -->\r\n@if(form?.invalid && form?.touched){\r\n<div class=\"mt-2 mb-2\">\r\n @if(this.form?.errors?.['atLeastOneRequired']){\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ form?.getError(\"atLeastOneRequired\")?.message }}</p-tag\r\n >\r\n }\r\n</div>\r\n}\r\n" }]
|
|
70
70
|
}], propDecorators: { control: [{
|
|
@@ -124,10 +124,10 @@ class KpicardComponent {
|
|
|
124
124
|
getSelectedOption() {
|
|
125
125
|
return this.options[this.option()] ?? this.options.currency; // Si no existe, usa `currency`
|
|
126
126
|
}
|
|
127
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
128
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.
|
|
127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KpicardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
128
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: KpicardComponent, isStandalone: true, selector: "app-kpicard", inputs: { option: { classPropertyName: "option", publicName: "option", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, iconType: { classPropertyName: "iconType", publicName: "iconType", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, valor: { classPropertyName: "valor", publicName: "valor", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"`kpi-card ${color()} ${theme()}-theme`\">\r\n <div class=\"kpi-container\">\r\n <span\r\n [countUp]=\"valor()\"\r\n [countUpOptions]=\"getSelectedOption()\"\r\n [class]=\"`card-value-${theme()}`\"\r\n >0</span\r\n >\r\n <span [class]=\"`card-text-${theme()}`\">{{ label() }}</span>\r\n </div>\r\n <i [class]=\"`${iconType()} icon icon-${theme()}`\"></i>\r\n</div>\r\n", styles: [".icon{float:right;font-size:500%;position:absolute;top:0rem;right:-.3rem;opacity:.2}.icon-light{color:#000}.icon-dark{color:#fff}.icon-aqua{color:#28cce9}.icon-sunset{color:#d1a9a5}.icon-mint{color:#91cc08}.icon-peach{color:#5e412f}.icon-plasma{color:#dcdde1}.icon-nebula{color:#d8d8d8}.kpi-card{--gradient-light: linear-gradient(to bottom, #00fffc, #008cff);--text-color-light: #495057;--card-value-gradient-light: linear-gradient( 45deg, #00fffc, #a200ff, #0094ff );--gradient-dark: linear-gradient(to bottom, #ff00ff, #ff0066);--text-color-dark: #d5d7d8;--card-value-gradient-dark: linear-gradient(45deg, #ff7e5f, #feb47b, #ff6a00);--gradient-aqua: linear-gradient(to bottom, #00e0ff, #0079ff);--text-color-aqua: #6fa6b8;--card-value-gradient-aqua: linear-gradient(45deg, #00e0ff, #00ffc8, #00b7ff);--gradient-sunset: linear-gradient(to bottom, #ff9a9e, #fad0c4);--text-color-sunset: #cfbfaf;--card-value-gradient-sunset: linear-gradient( 45deg, #ff9a9e, #fad0c4, #ff6f61 );--gradient-mint: linear-gradient(to bottom, #98ff98, #00d4ff);--text-color-mint: #a3ca36;--card-value-gradient-mint: linear-gradient(45deg, #98ff98, #00e1ff, #00ffa6);--gradient-peach: linear-gradient(to bottom, #ffecd2, #fcb69f);--text-color-peach: #5e412f;--card-value-gradient-peach: linear-gradient( 45deg, #ffecd2, #ffb347, #ffcccb );--gradient-plasma: linear-gradient(to bottom, #6a00f4, #240046);--text-color-plasma: #dcdde1;--card-value-gradient-plasma: linear-gradient( 45deg, #6a00f4, #8338ec, #3a0ca3 );--gradient-nebula: linear-gradient(to bottom, #38aa0c, #2632d4);--text-color-nebula: #a372d1;--card-value-gradient-nebula: linear-gradient( 45deg, #c4ffe2, #a6c9ff, #8a12f3 );overflow:hidden;position:relative;box-shadow:1px 1px 8px #000000a6;display:inline-block;padding:1em;border-radius:.8em;font-family:Montserrat,sans-serif;font-size:.9rem;width:90%;min-width:180px;margin-left:.5em;margin-top:.5em}.kpi-card:after{position:absolute;content:\"\";width:.25rem;inset:.65rem auto .65rem .5rem;border-radius:.125rem;background:var(--gradient);transition:transform .3s ease;z-index:4}.kpi-card.light-theme:after{background:var(--gradient-light)}.kpi-card.dark-theme:after{background:var(--gradient-dark)}.kpi-card.aqua-theme:after{background:var(--gradient-aqua)}.kpi-card.sunset-theme:after{background:var(--gradient-sunset)}.kpi-card.mint-theme:after{background:var(--gradient-mint)}.kpi-card.peach-theme:after{background:var(--gradient-peach)}.kpi-card.plasma-theme:after{background:var(--gradient-plasma)}.kpi-card.nebula-theme:after{background:var(--gradient-nebula)}.kpi-container{margin-left:.5em}.card-value-light{display:block;font-size:200%;font-weight:bolder;background:linear-gradient(45deg,#00fffc,#a200ff,#0094ff);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(0,255,252,.3),0 0 10px rgba(162,0,255,.2),0 0 15px rgba(0,148,255,.1)}.card-value-dark{display:block;font-size:200%;font-weight:bolder;background:linear-gradient(45deg,#ff7e5f,#feb47b,#ff6a00);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,126,95,.5),0 0 10px rgba(254,180,123,.4),0 0 15px rgba(255,106,0,.3)}.card-value-aqua{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-aqua);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(0,224,255,.3),0 0 10px rgba(0,255,200,.2),0 0 15px rgba(0,183,255,.1)}.card-value-sunset{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-sunset);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,154,158,.3),0 0 10px rgba(250,208,196,.2),0 0 15px rgba(255,111,97,.1)}.card-value-mint{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-mint);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(152,255,152,.4),0 0 10px rgba(0,225,255,.3),0 0 15px rgba(0,255,166,.2)}.card-value-peach{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-peach);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,236,210,.4),0 0 10px rgba(255,179,71,.3),0 0 15px rgba(255,204,203,.2)}.card-value-plasma{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-plasma);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(106,0,244,.5),0 0 10px rgba(131,56,236,.4),0 0 15px rgba(58,12,163,.3)}.card-value-nebula{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-nebula);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(27,27,47,.4),0 0 10px rgba(63,13,18,.3),0 0 15px rgba(142,45,226,.2)}.card-text{display:block;font-family:Roboto,sans-serif;padding-left:.2em}.card-text-light{color:var(--text-color-light)}.card-text-dark{color:var(--text-color-dark)}.card-text-aqua{color:var(--text-color-aqua)}.card-text-sunset{color:var(--text-color-sunset)}.card-text-mint{color:var(--text-color-mint)}.card-text-peach{color:var(--text-color-peach)}.card-text-plasma{color:var(--text-color-plasma)}.card-text-nebula{color:var(--text-color-nebula)}\n"], dependencies: [{ kind: "directive", type: CountUpDirective, selector: "[countUp]", inputs: ["countUp", "countUpOptions", "reanimateOnClick"], outputs: ["complete"] }] });
|
|
129
129
|
}
|
|
130
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
130
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: KpicardComponent, decorators: [{
|
|
131
131
|
type: Component,
|
|
132
132
|
args: [{ selector: 'app-kpicard', imports: [CountUpDirective], template: "<div [class]=\"`kpi-card ${color()} ${theme()}-theme`\">\r\n <div class=\"kpi-container\">\r\n <span\r\n [countUp]=\"valor()\"\r\n [countUpOptions]=\"getSelectedOption()\"\r\n [class]=\"`card-value-${theme()}`\"\r\n >0</span\r\n >\r\n <span [class]=\"`card-text-${theme()}`\">{{ label() }}</span>\r\n </div>\r\n <i [class]=\"`${iconType()} icon icon-${theme()}`\"></i>\r\n</div>\r\n", styles: [".icon{float:right;font-size:500%;position:absolute;top:0rem;right:-.3rem;opacity:.2}.icon-light{color:#000}.icon-dark{color:#fff}.icon-aqua{color:#28cce9}.icon-sunset{color:#d1a9a5}.icon-mint{color:#91cc08}.icon-peach{color:#5e412f}.icon-plasma{color:#dcdde1}.icon-nebula{color:#d8d8d8}.kpi-card{--gradient-light: linear-gradient(to bottom, #00fffc, #008cff);--text-color-light: #495057;--card-value-gradient-light: linear-gradient( 45deg, #00fffc, #a200ff, #0094ff );--gradient-dark: linear-gradient(to bottom, #ff00ff, #ff0066);--text-color-dark: #d5d7d8;--card-value-gradient-dark: linear-gradient(45deg, #ff7e5f, #feb47b, #ff6a00);--gradient-aqua: linear-gradient(to bottom, #00e0ff, #0079ff);--text-color-aqua: #6fa6b8;--card-value-gradient-aqua: linear-gradient(45deg, #00e0ff, #00ffc8, #00b7ff);--gradient-sunset: linear-gradient(to bottom, #ff9a9e, #fad0c4);--text-color-sunset: #cfbfaf;--card-value-gradient-sunset: linear-gradient( 45deg, #ff9a9e, #fad0c4, #ff6f61 );--gradient-mint: linear-gradient(to bottom, #98ff98, #00d4ff);--text-color-mint: #a3ca36;--card-value-gradient-mint: linear-gradient(45deg, #98ff98, #00e1ff, #00ffa6);--gradient-peach: linear-gradient(to bottom, #ffecd2, #fcb69f);--text-color-peach: #5e412f;--card-value-gradient-peach: linear-gradient( 45deg, #ffecd2, #ffb347, #ffcccb );--gradient-plasma: linear-gradient(to bottom, #6a00f4, #240046);--text-color-plasma: #dcdde1;--card-value-gradient-plasma: linear-gradient( 45deg, #6a00f4, #8338ec, #3a0ca3 );--gradient-nebula: linear-gradient(to bottom, #38aa0c, #2632d4);--text-color-nebula: #a372d1;--card-value-gradient-nebula: linear-gradient( 45deg, #c4ffe2, #a6c9ff, #8a12f3 );overflow:hidden;position:relative;box-shadow:1px 1px 8px #000000a6;display:inline-block;padding:1em;border-radius:.8em;font-family:Montserrat,sans-serif;font-size:.9rem;width:90%;min-width:180px;margin-left:.5em;margin-top:.5em}.kpi-card:after{position:absolute;content:\"\";width:.25rem;inset:.65rem auto .65rem .5rem;border-radius:.125rem;background:var(--gradient);transition:transform .3s ease;z-index:4}.kpi-card.light-theme:after{background:var(--gradient-light)}.kpi-card.dark-theme:after{background:var(--gradient-dark)}.kpi-card.aqua-theme:after{background:var(--gradient-aqua)}.kpi-card.sunset-theme:after{background:var(--gradient-sunset)}.kpi-card.mint-theme:after{background:var(--gradient-mint)}.kpi-card.peach-theme:after{background:var(--gradient-peach)}.kpi-card.plasma-theme:after{background:var(--gradient-plasma)}.kpi-card.nebula-theme:after{background:var(--gradient-nebula)}.kpi-container{margin-left:.5em}.card-value-light{display:block;font-size:200%;font-weight:bolder;background:linear-gradient(45deg,#00fffc,#a200ff,#0094ff);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(0,255,252,.3),0 0 10px rgba(162,0,255,.2),0 0 15px rgba(0,148,255,.1)}.card-value-dark{display:block;font-size:200%;font-weight:bolder;background:linear-gradient(45deg,#ff7e5f,#feb47b,#ff6a00);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,126,95,.5),0 0 10px rgba(254,180,123,.4),0 0 15px rgba(255,106,0,.3)}.card-value-aqua{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-aqua);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(0,224,255,.3),0 0 10px rgba(0,255,200,.2),0 0 15px rgba(0,183,255,.1)}.card-value-sunset{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-sunset);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,154,158,.3),0 0 10px rgba(250,208,196,.2),0 0 15px rgba(255,111,97,.1)}.card-value-mint{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-mint);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(152,255,152,.4),0 0 10px rgba(0,225,255,.3),0 0 15px rgba(0,255,166,.2)}.card-value-peach{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-peach);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(255,236,210,.4),0 0 10px rgba(255,179,71,.3),0 0 15px rgba(255,204,203,.2)}.card-value-plasma{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-plasma);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(106,0,244,.5),0 0 10px rgba(131,56,236,.4),0 0 15px rgba(58,12,163,.3)}.card-value-nebula{display:block;font-size:200%;font-weight:bolder;background:var(--card-value-gradient-nebula);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 0 5px rgba(27,27,47,.4),0 0 10px rgba(63,13,18,.3),0 0 15px rgba(142,45,226,.2)}.card-text{display:block;font-family:Roboto,sans-serif;padding-left:.2em}.card-text-light{color:var(--text-color-light)}.card-text-dark{color:var(--text-color-dark)}.card-text-aqua{color:var(--text-color-aqua)}.card-text-sunset{color:var(--text-color-sunset)}.card-text-mint{color:var(--text-color-mint)}.card-text-peach{color:var(--text-color-peach)}.card-text-plasma{color:var(--text-color-plasma)}.card-text-nebula{color:var(--text-color-nebula)}\n"] }]
|
|
133
133
|
}], propDecorators: { option: [{ type: i0.Input, args: [{ isSignal: true, alias: "option", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], iconType: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconType", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], valor: [{ type: i0.Input, args: [{ isSignal: true, alias: "valor", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }] } });
|
|
@@ -150,10 +150,10 @@ class IconDsxService {
|
|
|
150
150
|
this.cache.set(name, request$);
|
|
151
151
|
return request$;
|
|
152
152
|
}
|
|
153
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
154
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
153
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconDsxService, deps: [{ token: i1$1.HttpClient }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
154
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconDsxService, providedIn: 'root' });
|
|
155
155
|
}
|
|
156
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
156
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconDsxService, decorators: [{
|
|
157
157
|
type: Injectable,
|
|
158
158
|
args: [{
|
|
159
159
|
providedIn: 'root',
|
|
@@ -170,10 +170,10 @@ class IconDsxComponent {
|
|
|
170
170
|
ngOnInit() {
|
|
171
171
|
this.svg$ = this.iconService.getIcon(this.name); // 👈 AHORA CUADRA CON EL async
|
|
172
172
|
}
|
|
173
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
174
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.
|
|
173
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconDsxComponent, deps: [{ token: IconDsxService }], target: i0.ɵɵFactoryTarget.Component });
|
|
174
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: IconDsxComponent, isStandalone: true, selector: "icon-dsx", inputs: { name: "name" }, ngImport: i0, template: "<span class=\"dsx-icon\" [innerHTML]=\"svg$ | async\"></span>\r\n", styles: ["app-icon-dsx .dsx-icon svg{fill:currentColor!important}:host ::ng-deep .dsx-icon svg{fill:currentColor}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }] });
|
|
175
175
|
}
|
|
176
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
176
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IconDsxComponent, decorators: [{
|
|
177
177
|
type: Component,
|
|
178
178
|
args: [{ selector: 'icon-dsx', imports: [AsyncPipe], template: "<span class=\"dsx-icon\" [innerHTML]=\"svg$ | async\"></span>\r\n", styles: ["app-icon-dsx .dsx-icon svg{fill:currentColor!important}:host ::ng-deep .dsx-icon svg{fill:currentColor}\n"] }]
|
|
179
179
|
}], ctorParameters: () => [{ type: IconDsxService }], propDecorators: { name: [{
|
|
@@ -205,17 +205,239 @@ class JsonHighlightPipe {
|
|
|
205
205
|
.replace(/,/g, '<span class="json-comma">$&</span>')
|
|
206
206
|
.replace(/:/g, '<span class="json-colon">$&</span>');
|
|
207
207
|
}
|
|
208
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
209
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.
|
|
208
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: JsonHighlightPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
209
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: JsonHighlightPipe, isStandalone: true, name: "jsonHighlight" });
|
|
210
210
|
}
|
|
211
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
211
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: JsonHighlightPipe, decorators: [{
|
|
212
212
|
type: Pipe,
|
|
213
213
|
args: [{
|
|
214
214
|
name: 'jsonHighlight',
|
|
215
215
|
}]
|
|
216
216
|
}] });
|
|
217
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Esquema de configuración del entorno - Fuente única de verdad (Single Source of Truth)
|
|
220
|
+
*
|
|
221
|
+
* Este objeto define todos los campos requeridos y sus tipos esperados para la configuración del entorno.
|
|
222
|
+
* Sirve como referencia automática para:
|
|
223
|
+
* - Generar el tipo TypeScript `EnvironmentConfig`
|
|
224
|
+
* - Validar la presencia de campos requeridos
|
|
225
|
+
* - Validar los tipos de datos en runtime
|
|
226
|
+
* - Detectar automáticamente campos que requieren validación especial (URLs)
|
|
227
|
+
*
|
|
228
|
+
* **Cómo agregar una nueva propiedad:**
|
|
229
|
+
* 1. Agrégala a este objeto con su tipo: 'string', 'boolean' o 'number'
|
|
230
|
+
* 2. Todo lo demás se actualiza automáticamente (tipo TypeScript, validaciones, etc.)
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* const ENVIRONMENT_SCHEMA = {
|
|
235
|
+
* production: 'boolean' as const,
|
|
236
|
+
* myAppUrl: 'string' as const,
|
|
237
|
+
* apiTimeout: 'number' as const, // ← Agregar nueva propiedad
|
|
238
|
+
* } as const;
|
|
239
|
+
* ```
|
|
240
|
+
*
|
|
241
|
+
* @internal
|
|
242
|
+
*/
|
|
243
|
+
const ENVIRONMENT_SCHEMA = {
|
|
244
|
+
production: 'boolean',
|
|
245
|
+
myAppUrl: 'string',
|
|
246
|
+
SeguridadITApiUrl: 'string',
|
|
247
|
+
tokenName: 'string',
|
|
248
|
+
tokenNameRF: 'string',
|
|
249
|
+
sessionStatus: 'string',
|
|
250
|
+
refreshTokenExpiry: 'string',
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Token de inyección de dependencias para la configuración del entorno.
|
|
254
|
+
*
|
|
255
|
+
* Este token se utiliza para inyectar la configuración del entorno en servicios y componentes.
|
|
256
|
+
* **IMPORTANTE:** No uses este token directamente en providers. En su lugar, usa la función
|
|
257
|
+
* `provideEnvironment()` que incluye validación automática.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```typescript
|
|
261
|
+
* // ✅ Forma correcta - En tu configuración de app
|
|
262
|
+
* import { provideEnvironment } from '@devsoftxela/ngx-dsx';
|
|
263
|
+
* import { environment } from './environments/environment';
|
|
264
|
+
*
|
|
265
|
+
* export const appConfig: ApplicationConfig = {
|
|
266
|
+
* providers: [
|
|
267
|
+
* provideEnvironment(environment), // ← Con validación automática
|
|
268
|
+
* ]
|
|
269
|
+
* };
|
|
270
|
+
* ```
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* // ✅ Forma correcta - Inyectar en servicios
|
|
275
|
+
* import { inject } from '@angular/core';
|
|
276
|
+
* import { ENVIRONMENT, EnvironmentConfig } from '@devsoftxela/ngx-dsx';
|
|
277
|
+
*
|
|
278
|
+
* export class MiServicio {
|
|
279
|
+
* private environment: EnvironmentConfig = inject(ENVIRONMENT);
|
|
280
|
+
* }
|
|
281
|
+
* ```
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```typescript
|
|
285
|
+
* // ❌ Forma incorrecta - Sin validación
|
|
286
|
+
* providers: [
|
|
287
|
+
* { provide: ENVIRONMENT, useValue: environment } // ← Sin validación
|
|
288
|
+
* ]
|
|
289
|
+
* ```
|
|
290
|
+
*
|
|
291
|
+
* @see {@link provideEnvironment} para configurar con validación
|
|
292
|
+
* @see {@link EnvironmentConfig} para la estructura de datos
|
|
293
|
+
*/
|
|
218
294
|
const ENVIRONMENT = new InjectionToken('EnvironmentConfig');
|
|
295
|
+
/**
|
|
296
|
+
* Valida que la configuración del entorno esté completa y correctamente configurada.
|
|
297
|
+
*
|
|
298
|
+
* Esta función verifica que:
|
|
299
|
+
* - La configuración del entorno no sea null o undefined
|
|
300
|
+
* - Todas las propiedades requeridas estén presentes y no estén vacías
|
|
301
|
+
* - Las URLs tengan un formato válido
|
|
302
|
+
*
|
|
303
|
+
* @param environment - Configuración del entorno a validar
|
|
304
|
+
* @throws Error si alguna validación falla, con un mensaje descriptivo del problema
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* const config: EnvironmentConfig = { ... };
|
|
309
|
+
* validateEnvironmentConfig(config);
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
function validateEnvironmentConfig(environment) {
|
|
313
|
+
if (!environment) {
|
|
314
|
+
throw new Error('[ENVIRONMENT] La configuración del entorno no está definida. ' +
|
|
315
|
+
'Asegúrate de proporcionar una configuración válida usando provideEnvironment().');
|
|
316
|
+
}
|
|
317
|
+
// Obtener automáticamente todos los campos requeridos del schema
|
|
318
|
+
const requiredFields = Object.keys(ENVIRONMENT_SCHEMA);
|
|
319
|
+
const missingFields = [];
|
|
320
|
+
const emptyFields = [];
|
|
321
|
+
const wrongTypeFields = [];
|
|
322
|
+
// Validar que todos los campos requeridos existan, no estén vacíos y tengan el tipo correcto
|
|
323
|
+
requiredFields.forEach((field) => {
|
|
324
|
+
const expectedType = ENVIRONMENT_SCHEMA[field];
|
|
325
|
+
if (!(field in environment)) {
|
|
326
|
+
missingFields.push(field);
|
|
327
|
+
}
|
|
328
|
+
else if (environment[field] === null ||
|
|
329
|
+
environment[field] === undefined) {
|
|
330
|
+
emptyFields.push(field);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Validar tipo de dato
|
|
334
|
+
const actualType = typeof environment[field];
|
|
335
|
+
if (actualType !== expectedType) {
|
|
336
|
+
wrongTypeFields.push(`${field} (esperado: ${expectedType}, recibido: ${actualType})`);
|
|
337
|
+
}
|
|
338
|
+
// Validar que strings no estén vacíos
|
|
339
|
+
if (expectedType === 'string' &&
|
|
340
|
+
typeof environment[field] === 'string' &&
|
|
341
|
+
environment[field].trim() === '') {
|
|
342
|
+
emptyFields.push(field);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
// Reportar campos faltantes
|
|
347
|
+
if (missingFields.length > 0) {
|
|
348
|
+
throw new Error(`[ENVIRONMENT] Faltan los siguientes campos en la configuración del entorno: ${missingFields.join(', ')}. ` + 'Por favor, verifica tu configuración de environment.');
|
|
349
|
+
}
|
|
350
|
+
// Reportar campos vacíos
|
|
351
|
+
if (emptyFields.length > 0) {
|
|
352
|
+
throw new Error(`[ENVIRONMENT] Los siguientes campos están vacíos en la configuración del entorno: ${emptyFields.join(', ')}. ` + 'Por favor, proporciona valores válidos para estos campos.');
|
|
353
|
+
}
|
|
354
|
+
// Reportar campos con tipo incorrecto
|
|
355
|
+
if (wrongTypeFields.length > 0) {
|
|
356
|
+
throw new Error(`[ENVIRONMENT] Los siguientes campos tienen un tipo de dato incorrecto: ${wrongTypeFields.join(', ')}. ` + 'Por favor, corrige los tipos de datos.');
|
|
357
|
+
}
|
|
358
|
+
// Validar formato de URLs (solo para campos que contengan 'url' en su nombre)
|
|
359
|
+
requiredFields.forEach((field) => {
|
|
360
|
+
if (field.toLowerCase().includes('url') &&
|
|
361
|
+
typeof environment[field] === 'string') {
|
|
362
|
+
validateUrl(field, environment[field]);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Valida que una URL tenga un formato válido.
|
|
368
|
+
*
|
|
369
|
+
* @param fieldName - Nombre del campo para mensajes de error
|
|
370
|
+
* @param url - URL a validar
|
|
371
|
+
* @throws Error si la URL no tiene un formato válido
|
|
372
|
+
*/
|
|
373
|
+
function validateUrl(fieldName, url) {
|
|
374
|
+
try {
|
|
375
|
+
// Intentar crear un objeto URL para validar el formato
|
|
376
|
+
new URL(url);
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
// Si falla, verificar si al menos tiene un formato básico válido
|
|
380
|
+
const urlPattern = /^https?:\/\/.+/;
|
|
381
|
+
if (!urlPattern.test(url)) {
|
|
382
|
+
throw new Error(`[ENVIRONMENT] El campo '${fieldName}' no tiene un formato de URL válido. ` +
|
|
383
|
+
`Valor actual: '${url}'. Debe comenzar con http:// o https://`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// Validar que la URL termine con '/' para evitar problemas de concatenación
|
|
387
|
+
if (!url.endsWith('/')) {
|
|
388
|
+
console.warn(`[ENVIRONMENT] Advertencia: El campo '${fieldName}' no termina con '/'. ` +
|
|
389
|
+
`Valor actual: '${url}'. Se recomienda que las URLs base terminen con '/' para evitar problemas de concatenación.`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Proporciona una configuración de entorno validada para la inyección de dependencias.
|
|
394
|
+
*
|
|
395
|
+
* Esta función crea un provider que valida automáticamente la configuración del entorno
|
|
396
|
+
* cuando la aplicación se inicializa. Si la configuración es inválida, lanza un error
|
|
397
|
+
* descriptivo que indica qué está mal configurado.
|
|
398
|
+
*
|
|
399
|
+
* @param environment - Configuración del entorno a proporcionar
|
|
400
|
+
* @returns Provider de Angular configurado con la validación integrada
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```typescript
|
|
404
|
+
* // En app.config.ts o main.ts
|
|
405
|
+
* import { provideEnvironment } from './path/to/environment.token';
|
|
406
|
+
* import { environment } from './environments/environment';
|
|
407
|
+
*
|
|
408
|
+
* export const appConfig: ApplicationConfig = {
|
|
409
|
+
* providers: [
|
|
410
|
+
* provideEnvironment(environment),
|
|
411
|
+
* // ... otros providers
|
|
412
|
+
* ]
|
|
413
|
+
* };
|
|
414
|
+
* ```
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```typescript
|
|
418
|
+
* // Para módulos (NgModule)
|
|
419
|
+
* import { provideEnvironment } from './path/to/environment.token';
|
|
420
|
+
* import { environment } from './environments/environment';
|
|
421
|
+
*
|
|
422
|
+
* @NgModule({
|
|
423
|
+
* providers: [
|
|
424
|
+
* provideEnvironment(environment),
|
|
425
|
+
* // ... otros providers
|
|
426
|
+
* ]
|
|
427
|
+
* })
|
|
428
|
+
* export class AppModule { }
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
function provideEnvironment(environment) {
|
|
432
|
+
return {
|
|
433
|
+
provide: ENVIRONMENT,
|
|
434
|
+
useFactory: () => {
|
|
435
|
+
// Validar la configuración al momento de la inyección
|
|
436
|
+
validateEnvironmentConfig(environment);
|
|
437
|
+
return environment;
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
}
|
|
219
441
|
|
|
220
442
|
class JsonValuesDebujComponent {
|
|
221
443
|
form;
|
|
@@ -227,10 +449,10 @@ class JsonValuesDebujComponent {
|
|
|
227
449
|
isDev() {
|
|
228
450
|
return this.isDevSignal();
|
|
229
451
|
}
|
|
230
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
231
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.
|
|
452
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: JsonValuesDebujComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
453
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: JsonValuesDebujComponent, isStandalone: true, selector: "app-json-values-debuj", inputs: { form: "form" }, ngImport: i0, template: "@if(isDev()){\r\n<div class=\"custom-container\">\r\n <pre\r\n class=\"custom-pre\"\r\n [innerHTML]=\"form.getRawValue() | jsonHighlight\"\r\n ></pre>\r\n</div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;background-color:#f3f4f6;padding:.5rem;border-radius:.5rem;margin-bottom:.75rem}.custom-pre{white-space:pre-wrap;word-break:break-word;font-size:.875rem}\n"], dependencies: [{ kind: "pipe", type: JsonHighlightPipe, name: "jsonHighlight" }] });
|
|
232
454
|
}
|
|
233
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
455
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: JsonValuesDebujComponent, decorators: [{
|
|
234
456
|
type: Component,
|
|
235
457
|
args: [{ selector: 'app-json-values-debuj', imports: [JsonHighlightPipe], template: "@if(isDev()){\r\n<div class=\"custom-container\">\r\n <pre\r\n class=\"custom-pre\"\r\n [innerHTML]=\"form.getRawValue() | jsonHighlight\"\r\n ></pre>\r\n</div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;background-color:#f3f4f6;padding:.5rem;border-radius:.5rem;margin-bottom:.75rem}.custom-pre{white-space:pre-wrap;word-break:break-word;font-size:.875rem}\n"] }]
|
|
236
458
|
}], propDecorators: { form: [{
|
|
@@ -249,10 +471,10 @@ class SpinnerLoadingService {
|
|
|
249
471
|
hide() {
|
|
250
472
|
this.spinnerVisible.set(false);
|
|
251
473
|
}
|
|
252
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
253
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
474
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SpinnerLoadingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
475
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SpinnerLoadingService, providedIn: 'root' });
|
|
254
476
|
}
|
|
255
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
477
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SpinnerLoadingService, decorators: [{
|
|
256
478
|
type: Injectable,
|
|
257
479
|
args: [{
|
|
258
480
|
providedIn: 'root',
|
|
@@ -274,10 +496,10 @@ class LoadingLottieComponent {
|
|
|
274
496
|
};
|
|
275
497
|
});
|
|
276
498
|
}
|
|
277
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
278
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.
|
|
499
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoadingLottieComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
500
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: LoadingLottieComponent, isStandalone: true, selector: "app-loading-lottie", inputs: { jsonUrl: { classPropertyName: "jsonUrl", publicName: "jsonUrl", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(_spinnerService.spinnerVisible()){\r\n<div class=\"loader-container\">\r\n <ng-lottie [options]=\"options\" [width]=\"size()\" [height]=\"size()\"></ng-lottie>\r\n <p class=\"loading-text\">©DevsoftXela {{ currentYear }}</p>\r\n</div>\r\n}\r\n", styles: [".loader-container{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#000000e6;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden}.loading-text{position:absolute;bottom:calc(53% - 175px);z-index:2;font-family:Montserrat,sans-serif;text-transform:uppercase;background:linear-gradient(45deg,#0ff,#f0f);-webkit-background-clip:text;background-clip:text;color:transparent;font-weight:700;text-align:center;pointer-events:none}\n"], dependencies: [{ kind: "component", type: LottieComponent, selector: "ng-lottie", inputs: ["width", "height"] }] });
|
|
279
501
|
}
|
|
280
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
502
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoadingLottieComponent, decorators: [{
|
|
281
503
|
type: Component,
|
|
282
504
|
args: [{ selector: 'app-loading-lottie', imports: [LottieComponent], template: "@if(_spinnerService.spinnerVisible()){\r\n<div class=\"loader-container\">\r\n <ng-lottie [options]=\"options\" [width]=\"size()\" [height]=\"size()\"></ng-lottie>\r\n <p class=\"loading-text\">©DevsoftXela {{ currentYear }}</p>\r\n</div>\r\n}\r\n", styles: [".loader-container{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#000000e6;display:flex;justify-content:center;align-items:center;z-index:9999;overflow:hidden}.loading-text{position:absolute;bottom:calc(53% - 175px);z-index:2;font-family:Montserrat,sans-serif;text-transform:uppercase;background:linear-gradient(45deg,#0ff,#f0f);-webkit-background-clip:text;background-clip:text;color:transparent;font-weight:700;text-align:center;pointer-events:none}\n"] }]
|
|
283
505
|
}], ctorParameters: () => [], propDecorators: { jsonUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "jsonUrl", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
@@ -289,10 +511,10 @@ class LoadingComponent {
|
|
|
289
511
|
constructor() {
|
|
290
512
|
this.currentYear = new Date().getFullYear(); // Asigna el año actual
|
|
291
513
|
}
|
|
292
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
293
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.
|
|
514
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
515
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: LoadingComponent, isStandalone: true, selector: "app-loading", ngImport: i0, template: "<!-- Actualizaci\u00F3n 2025-31-01 12:00 -->\r\n@if(_spinnerService.spinnerVisible()){\r\n<div class=\"spinner-overlay\">\r\n <div class=\"loader\">\r\n <div class=\"external-shadow\">\r\n <div class=\"central\"></div>\r\n </div>\r\n <img src=\"/icon/secure.png\" class=\"spinner-image\" />\r\n </div>\r\n <p class=\"loading-text\">©DevsoftXela {{ currentYear }}</p>\r\n</div>\r\n}\r\n", styles: [".spinner-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#000000e6;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:9999}.loader{display:flex;justify-content:center;align-items:center;position:relative;cursor:not-allowed;scale:.8}.central{display:flex;justify-content:center;align-items:center;position:relative;width:10em;height:10em;border-radius:50%;box-shadow:.5em 1em 1em #8a2be2,-.5em .5em 1em #00f,.5em -.5em 1em purple,-.5em -.5em 1em #0ff;background-color:#0003}.external-shadow{width:10em;height:10em;border-radius:50%;display:flex;justify-content:center;align-items:center;position:relative;box-shadow:.5em .5em 3em #8a2be2,-.5em .5em 3em #00f,.5em -.5em 3em purple,-.5em -.5em 3em #0ff;z-index:999;animation:rotate 3s linear infinite;background-color:#21212180}@keyframes rotate{0%{transform:rotate(0)}50%{transform:rotate(180deg)}to{transform:rotate(360deg)}}.spinner-image{width:70%;height:70%;border-radius:50%;object-fit:cover;position:absolute;z-index:1000}.loading-text{font-family:Montserrat,sans-serif;text-transform:uppercase;letter-spacing:3px;background:linear-gradient(45deg,#0ff,#f0f);-webkit-background-clip:text;background-clip:text;color:transparent;margin-top:1em}@keyframes pulse{0%,to{opacity:.7}50%{opacity:1}}\n"] });
|
|
294
516
|
}
|
|
295
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
517
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LoadingComponent, decorators: [{
|
|
296
518
|
type: Component,
|
|
297
519
|
args: [{ selector: 'app-loading', imports: [], template: "<!-- Actualizaci\u00F3n 2025-31-01 12:00 -->\r\n@if(_spinnerService.spinnerVisible()){\r\n<div class=\"spinner-overlay\">\r\n <div class=\"loader\">\r\n <div class=\"external-shadow\">\r\n <div class=\"central\"></div>\r\n </div>\r\n <img src=\"/icon/secure.png\" class=\"spinner-image\" />\r\n </div>\r\n <p class=\"loading-text\">©DevsoftXela {{ currentYear }}</p>\r\n</div>\r\n}\r\n", styles: [".spinner-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#000000e6;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:9999}.loader{display:flex;justify-content:center;align-items:center;position:relative;cursor:not-allowed;scale:.8}.central{display:flex;justify-content:center;align-items:center;position:relative;width:10em;height:10em;border-radius:50%;box-shadow:.5em 1em 1em #8a2be2,-.5em .5em 1em #00f,.5em -.5em 1em purple,-.5em -.5em 1em #0ff;background-color:#0003}.external-shadow{width:10em;height:10em;border-radius:50%;display:flex;justify-content:center;align-items:center;position:relative;box-shadow:.5em .5em 3em #8a2be2,-.5em .5em 3em #00f,.5em -.5em 3em purple,-.5em -.5em 3em #0ff;z-index:999;animation:rotate 3s linear infinite;background-color:#21212180}@keyframes rotate{0%{transform:rotate(0)}50%{transform:rotate(180deg)}to{transform:rotate(360deg)}}.spinner-image{width:70%;height:70%;border-radius:50%;object-fit:cover;position:absolute;z-index:1000}.loading-text{font-family:Montserrat,sans-serif;text-transform:uppercase;letter-spacing:3px;background:linear-gradient(45deg,#0ff,#f0f);-webkit-background-clip:text;background-clip:text;color:transparent;margin-top:1em}@keyframes pulse{0%,to{opacity:.7}50%{opacity:1}}\n"] }]
|
|
298
520
|
}], ctorParameters: () => [] });
|
|
@@ -500,10 +722,10 @@ class AlertaService {
|
|
|
500
722
|
});
|
|
501
723
|
}
|
|
502
724
|
}
|
|
503
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
504
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
725
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
726
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertaService, providedIn: 'root' });
|
|
505
727
|
}
|
|
506
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
728
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertaService, decorators: [{
|
|
507
729
|
type: Injectable,
|
|
508
730
|
args: [{
|
|
509
731
|
providedIn: 'root',
|
|
@@ -512,32 +734,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.5", ngImpor
|
|
|
512
734
|
|
|
513
735
|
const INITIAL_PARAMETERS = new InjectionToken('InitialParameters');
|
|
514
736
|
|
|
737
|
+
/**
|
|
738
|
+
* Servicio de seguridad que gestiona la autenticación y autorización mediante tokens JWT.
|
|
739
|
+
*
|
|
740
|
+
* Este servicio proporciona métodos para:
|
|
741
|
+
* - Refrescar tokens de acceso
|
|
742
|
+
* - Revocar tokens de refresco
|
|
743
|
+
* - Obtener parámetros de seguridad
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* constructor(private securityService: SecurityService) {}
|
|
748
|
+
*
|
|
749
|
+
* refreshToken() {
|
|
750
|
+
* this.securityService.tokenRefresh(this.refreshToken)
|
|
751
|
+
* .subscribe(data => console.log(data));
|
|
752
|
+
* }
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
515
755
|
class SecurityService {
|
|
516
|
-
|
|
756
|
+
/** Servicio HttpClient para realizar peticiones HTTP */
|
|
517
757
|
http = inject(HttpClient);
|
|
518
|
-
|
|
758
|
+
/**
|
|
759
|
+
* Configuración del entorno inyectada mediante el token ENVIRONMENT.
|
|
760
|
+
* La validación se realiza automáticamente al usar provideEnvironment().
|
|
761
|
+
*/
|
|
519
762
|
environment = inject(ENVIRONMENT);
|
|
520
|
-
|
|
521
|
-
urlApi = `${this.environment.myAppUrl}api/
|
|
763
|
+
/** URL base de la API JWT construida desde la configuración del entorno */
|
|
764
|
+
urlApi = `${this.environment.myAppUrl}api/parameter`;
|
|
765
|
+
SeguridadITApi = `${this.environment.SeguridadITApiUrl}api/jwt`;
|
|
522
766
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
767
|
+
* Obtiene un nuevo token de acceso utilizando un refresh token válido.
|
|
768
|
+
*
|
|
769
|
+
* Este método envía una solicitud POST al endpoint de refresco de token
|
|
770
|
+
* y devuelve un nuevo par de tokens (access token y refresh token).
|
|
771
|
+
*
|
|
772
|
+
* @param refreshToken - El refresh token válido para obtener un nuevo token de acceso
|
|
773
|
+
* @returns Observable que emite un objeto DataToken con el nuevo par de tokens
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```typescript
|
|
777
|
+
* this.securityService.tokenRefresh('your-refresh-token')
|
|
778
|
+
* .subscribe({
|
|
779
|
+
* next: (data) => console.log('Nuevo token:', data.accessToken),
|
|
780
|
+
* error: (err) => console.error('Error al refrescar token:', err)
|
|
781
|
+
* });
|
|
782
|
+
* ```
|
|
526
783
|
*/
|
|
527
784
|
tokenRefresh(refreshToken) {
|
|
528
785
|
// Crea el cuerpo de la solicitud con el refresh token
|
|
529
786
|
const body = { refreshToken };
|
|
530
787
|
// Realiza una solicitud POST al endpoint de refresco de token
|
|
531
|
-
return this.http.post(`${this.
|
|
788
|
+
return this.http.post(`${this.SeguridadITApi}/refresh-token/`, body, {
|
|
789
|
+
headers: new HttpHeaders({
|
|
790
|
+
'Content-Type': 'application/json', // Establece el tipo de contenido como JSON
|
|
791
|
+
}),
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Revoca un refresh token para invalidarlo y prevenir su uso futuro.
|
|
796
|
+
*
|
|
797
|
+
* Este método envía una solicitud POST al endpoint de revocación de token
|
|
798
|
+
* para invalidar permanentemente el refresh token proporcionado.
|
|
799
|
+
*
|
|
800
|
+
* @param refreshToken - El refresh token que se desea revocar
|
|
801
|
+
* @returns Observable que emite true si la revocación fue exitosa, false en caso contrario
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```typescript
|
|
805
|
+
* this.securityService.tokenRevok('your-refresh-token')
|
|
806
|
+
* .subscribe({
|
|
807
|
+
* next: (success) => {
|
|
808
|
+
* if (success) console.log('Token revocado exitosamente');
|
|
809
|
+
* },
|
|
810
|
+
* error: (err) => console.error('Error al revocar token:', err)
|
|
811
|
+
* });
|
|
812
|
+
* ```
|
|
813
|
+
*/
|
|
814
|
+
tokenRevok(refreshToken) {
|
|
815
|
+
// Crea el cuerpo de la solicitud con el refresh token
|
|
816
|
+
const body = { refreshToken };
|
|
817
|
+
// Realiza una solicitud POST al endpoint de revocación de token
|
|
818
|
+
return this.http.post(`${this.SeguridadITApi}/revoke-token/`, body, {
|
|
532
819
|
headers: new HttpHeaders({
|
|
533
820
|
'Content-Type': 'application/json', // Establece el tipo de contenido como JSON
|
|
534
821
|
}),
|
|
535
822
|
});
|
|
536
823
|
}
|
|
537
824
|
/**
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
825
|
+
* Obtiene los parámetros de seguridad de la aplicación desde el servidor.
|
|
826
|
+
*
|
|
827
|
+
* Este método recupera la configuración de seguridad que incluye políticas de contraseñas,
|
|
828
|
+
* tiempos de expiración de sesión, y otras configuraciones relacionadas con la seguridad.
|
|
829
|
+
*
|
|
830
|
+
* @param invalidCacheParam - Indica si se debe invalidar la caché del servidor.
|
|
831
|
+
* Si es true, fuerza al servidor a devolver los datos más recientes
|
|
832
|
+
* sin usar la caché. Por defecto es false.
|
|
833
|
+
* @returns Observable que emite un objeto SeguridadITParameter con la configuración de seguridad
|
|
834
|
+
*
|
|
835
|
+
* @example
|
|
836
|
+
* ```typescript
|
|
837
|
+
* // Obtener parámetros usando caché
|
|
838
|
+
* this.securityService.getParameterSecurity()
|
|
839
|
+
* .subscribe(params => console.log('Parámetros:', params));
|
|
840
|
+
*
|
|
841
|
+
* // Obtener parámetros sin usar caché
|
|
842
|
+
* this.securityService.getParameterSecurity(true)
|
|
843
|
+
* .subscribe(params => console.log('Parámetros actualizados:', params));
|
|
844
|
+
* ```
|
|
541
845
|
*/
|
|
542
846
|
getParameterSecurity(invalidCacheParam = false) {
|
|
543
847
|
// Crea los parámetros de la solicitud, incluyendo el parámetro invalidCacheParam,
|
|
@@ -546,10 +850,10 @@ class SecurityService {
|
|
|
546
850
|
// Realiza una solicitud GET al endpoint de parámetros de seguridad
|
|
547
851
|
return this.http.get(`${this.urlApi}/security-parameter/`, { params });
|
|
548
852
|
}
|
|
549
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
550
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
853
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
854
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SecurityService, providedIn: 'root' });
|
|
551
855
|
}
|
|
552
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
856
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SecurityService, decorators: [{
|
|
553
857
|
type: Injectable,
|
|
554
858
|
args: [{
|
|
555
859
|
providedIn: 'root',
|
|
@@ -639,7 +943,7 @@ class ParameterValuesService {
|
|
|
639
943
|
return of([...this.dataParameter]); // copia mutable
|
|
640
944
|
}
|
|
641
945
|
return this.apiService.getParameterSecurity(force).pipe(map((response) => {
|
|
642
|
-
const apiParameters = response.parameterSecurity ?? [];
|
|
946
|
+
const apiParameters = response.data?.parameterSecurity ?? [];
|
|
643
947
|
this.validateParameters(apiParameters);
|
|
644
948
|
const values = this.mapToMyParameterValues(apiParameters);
|
|
645
949
|
this.setDataParameter(values);
|
|
@@ -805,10 +1109,10 @@ class ParameterValuesService {
|
|
|
805
1109
|
return (this.dataParameter.find((p) => p.parameterName === parameterName)
|
|
806
1110
|
?.values ?? []);
|
|
807
1111
|
}
|
|
808
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
809
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
1112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ParameterValuesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1113
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ParameterValuesService, providedIn: 'root' });
|
|
810
1114
|
}
|
|
811
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ParameterValuesService, decorators: [{
|
|
812
1116
|
type: Injectable,
|
|
813
1117
|
args: [{
|
|
814
1118
|
providedIn: 'root',
|
|
@@ -864,10 +1168,10 @@ class NavbarDsxComponent {
|
|
|
864
1168
|
complete: () => this._parameterSecurityService.clearParameterCache(),
|
|
865
1169
|
});
|
|
866
1170
|
}
|
|
867
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
868
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.
|
|
1171
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NavbarDsxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1172
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: NavbarDsxComponent, isStandalone: true, selector: "app-navbar-dsx", inputs: { logoWidth: { classPropertyName: "logoWidth", publicName: "logoWidth", isSignal: true, isRequired: false, transformFunction: null }, appVersion: { classPropertyName: "appVersion", publicName: "appVersion", isSignal: true, isRequired: false, transformFunction: null }, urlLogo: { classPropertyName: "urlLogo", publicName: "urlLogo", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<p-menubar>\r\n <ng-template #start>\r\n <p-image\r\n class=\"ms-15\"\r\n [src]=\"urlLogo()\"\r\n alt=\"Image\"\r\n [width]=\"logoWidth()\"\r\n />\r\n <span class=\"version-text\">{{ appVersion() }}</span>\r\n </ng-template>\r\n <ng-template #end>\r\n <div>\r\n <p-button\r\n class=\"mr-2\"\r\n label=\"Permisos\"\r\n variant=\"text\"\r\n severity=\"info\"\r\n (click)=\"actualizarSeguridadIT()\"\r\n >\r\n <span class=\"material-symbols-outlined mr-1\">local_police</span>\r\n </p-button>\r\n <label class=\"ui-switch\">\r\n <input\r\n type=\"checkbox\"\r\n [(ngModel)]=\"checked\"\r\n (click)=\"onThemeChange(!checked ? true : false)\"\r\n />\r\n <div class=\"slider\">\r\n <div class=\"circle\"></div>\r\n </div>\r\n </label>\r\n <!-- <p-inputSwitch\r\n [(ngModel)]=\"checked\"\r\n (onChange)=\"onThemeChange($event.checked)\"\r\n ></p-inputSwitch> -->\r\n </div>\r\n </ng-template>\r\n</p-menubar>\r\n", styles: [":host ::ng-deep .p-menubar{display:flex;align-items:center!important;padding:0!important;border:none!important;background:none!important;margin-left:4rem;margin-right:2.5rem}:host ::ng-deep .p-menubar-end>*{display:flex;align-items:center}.ui-switch{--switch-bg: rgb(135, 150, 165);--switch-width: 48px;--switch-height: 20px;--circle-diameter: 32px;--circle-bg: rgb(232, 89, 15);--circle-inset: calc((var(--circle-diameter) - var(--switch-height)) / 2)}.ui-switch input{display:none}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:var(--switch-width);height:var(--switch-height);background:var(--switch-bg);border-radius:999px;position:relative;cursor:pointer}.slider .circle{top:calc(var(--circle-inset) * -1);left:0;width:var(--circle-diameter);height:var(--circle-diameter);position:absolute;background:var(--circle-bg);border-radius:inherit;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTkuMzA1IDEuNjY3VjMuNzVoMS4zODlWMS42NjdoLTEuMzl6bS00LjcwNyAxLjk1bC0uOTgyLjk4Mkw1LjA5IDYuMDcybC45ODItLjk4Mi0xLjQ3My0xLjQ3M3ptMTAuODAyIDBMMTMuOTI3IDUuMDlsLjk4Mi45ODIgMS40NzMtMS40NzMtLjk4Mi0uOTgyek0xMCA1LjEzOWE0Ljg3MiA0Ljg3MiAwIDAwLTQuODYyIDQuODZBNC44NzIgNC44NzIgMCAwMDEwIDE0Ljg2MiA0Ljg3MiA0Ljg3MiAwIDAwMTQuODYgMTAgNC44NzIgNC44NzIgMCAwMDEwIDUuMTM5em0wIDEuMzg5QTMuNDYyIDMuNDYyIDAgMDExMy40NzEgMTBhMy40NjIgMy40NjIgMCAwMS0zLjQ3MyAzLjQ3MkEzLjQ2MiAzLjQ2MiAwIDAxNi41MjcgMTAgMy40NjIgMy40NjIgMCAwMTEwIDYuNTI4ek0xLjY2NSA5LjMwNXYxLjM5aDIuMDgzdi0xLjM5SDEuNjY2em0xNC41ODMgMHYxLjM5aDIuMDg0di0xLjM5aC0yLjA4NHpNNS4wOSAxMy45MjhMMy42MTYgMTUuNGwuOTgyLjk4MiAxLjQ3My0xLjQ3My0uOTgyLS45ODJ6bTkuODIgMGwtLjk4Mi45ODIgMS40NzMgMS40NzMuOTgyLS45ODItMS40NzMtMS40NzN6TTkuMzA1IDE2LjI1djIuMDgzaDEuMzg5VjE2LjI1aC0xLjM5eiIgLz4KPC9zdmc+);background-repeat:no-repeat;background-position:center center;-webkit-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;-o-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms;transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;box-shadow:0 2px 1px -1px #0003,0 1px 1px #00000024,0 1px 3px #0000001f}.slider .circle:before{content:\"\";position:absolute;width:100%;height:100%;background:#ffffffbf;border-radius:inherit;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s;opacity:0}.ui-switch input:checked+.slider .circle{left:calc(100% - var(--circle-diameter));background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTQuMiAyLjVsLS43IDEuOC0xLjguNyAxLjguNy43IDEuOC42LTEuOEw2LjcgNWwtMS45LS43LS42LTEuOHptMTUgOC4zYTYuNyA2LjcgMCAxMS02LjYtNi42IDUuOCA1LjggMCAwMDYuNiA2LjZ6IiAvPgo8L3N2Zz4=);background-color:#003892}.ui-switch input:active+.slider .circle:before{-webkit-transition:0s;-o-transition:0s;transition:0s;opacity:1;width:0;height:0}\n"], dependencies: [{ kind: "ngmodule", type: MenubarModule }, { kind: "component", type: i1$2.Menubar, selector: "p-menubar", inputs: ["model", "styleClass", "autoZIndex", "baseZIndex", "autoDisplay", "autoHide", "breakpoint", "autoHideDelay", "id", "ariaLabel", "ariaLabelledBy"], outputs: ["onFocus", "onBlur"] }, { kind: "ngmodule", type: ImageModule }, { kind: "component", type: i2$1.Image, selector: "p-image", inputs: ["imageClass", "imageStyle", "styleClass", "src", "srcSet", "sizes", "previewImageSrc", "previewImageSrcSet", "previewImageSizes", "alt", "width", "height", "loading", "preview", "showTransitionOptions", "hideTransitionOptions", "modalEnterAnimation", "modalLeaveAnimation", "appendTo", "maskMotionOptions", "motionOptions"], outputs: ["onShow", "onHide", "onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
869
1173
|
}
|
|
870
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1174
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NavbarDsxComponent, decorators: [{
|
|
871
1175
|
type: Component,
|
|
872
1176
|
args: [{ selector: 'app-navbar-dsx', imports: [MenubarModule, ImageModule, ButtonModule, FormsModule], template: "<p-menubar>\r\n <ng-template #start>\r\n <p-image\r\n class=\"ms-15\"\r\n [src]=\"urlLogo()\"\r\n alt=\"Image\"\r\n [width]=\"logoWidth()\"\r\n />\r\n <span class=\"version-text\">{{ appVersion() }}</span>\r\n </ng-template>\r\n <ng-template #end>\r\n <div>\r\n <p-button\r\n class=\"mr-2\"\r\n label=\"Permisos\"\r\n variant=\"text\"\r\n severity=\"info\"\r\n (click)=\"actualizarSeguridadIT()\"\r\n >\r\n <span class=\"material-symbols-outlined mr-1\">local_police</span>\r\n </p-button>\r\n <label class=\"ui-switch\">\r\n <input\r\n type=\"checkbox\"\r\n [(ngModel)]=\"checked\"\r\n (click)=\"onThemeChange(!checked ? true : false)\"\r\n />\r\n <div class=\"slider\">\r\n <div class=\"circle\"></div>\r\n </div>\r\n </label>\r\n <!-- <p-inputSwitch\r\n [(ngModel)]=\"checked\"\r\n (onChange)=\"onThemeChange($event.checked)\"\r\n ></p-inputSwitch> -->\r\n </div>\r\n </ng-template>\r\n</p-menubar>\r\n", styles: [":host ::ng-deep .p-menubar{display:flex;align-items:center!important;padding:0!important;border:none!important;background:none!important;margin-left:4rem;margin-right:2.5rem}:host ::ng-deep .p-menubar-end>*{display:flex;align-items:center}.ui-switch{--switch-bg: rgb(135, 150, 165);--switch-width: 48px;--switch-height: 20px;--circle-diameter: 32px;--circle-bg: rgb(232, 89, 15);--circle-inset: calc((var(--circle-diameter) - var(--switch-height)) / 2)}.ui-switch input{display:none}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:var(--switch-width);height:var(--switch-height);background:var(--switch-bg);border-radius:999px;position:relative;cursor:pointer}.slider .circle{top:calc(var(--circle-inset) * -1);left:0;width:var(--circle-diameter);height:var(--circle-diameter);position:absolute;background:var(--circle-bg);border-radius:inherit;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTkuMzA1IDEuNjY3VjMuNzVoMS4zODlWMS42NjdoLTEuMzl6bS00LjcwNyAxLjk1bC0uOTgyLjk4Mkw1LjA5IDYuMDcybC45ODItLjk4Mi0xLjQ3My0xLjQ3M3ptMTAuODAyIDBMMTMuOTI3IDUuMDlsLjk4Mi45ODIgMS40NzMtMS40NzMtLjk4Mi0uOTgyek0xMCA1LjEzOWE0Ljg3MiA0Ljg3MiAwIDAwLTQuODYyIDQuODZBNC44NzIgNC44NzIgMCAwMDEwIDE0Ljg2MiA0Ljg3MiA0Ljg3MiAwIDAwMTQuODYgMTAgNC44NzIgNC44NzIgMCAwMDEwIDUuMTM5em0wIDEuMzg5QTMuNDYyIDMuNDYyIDAgMDExMy40NzEgMTBhMy40NjIgMy40NjIgMCAwMS0zLjQ3MyAzLjQ3MkEzLjQ2MiAzLjQ2MiAwIDAxNi41MjcgMTAgMy40NjIgMy40NjIgMCAwMTEwIDYuNTI4ek0xLjY2NSA5LjMwNXYxLjM5aDIuMDgzdi0xLjM5SDEuNjY2em0xNC41ODMgMHYxLjM5aDIuMDg0di0xLjM5aC0yLjA4NHpNNS4wOSAxMy45MjhMMy42MTYgMTUuNGwuOTgyLjk4MiAxLjQ3My0xLjQ3My0uOTgyLS45ODJ6bTkuODIgMGwtLjk4Mi45ODIgMS40NzMgMS40NzMuOTgyLS45ODItMS40NzMtMS40NzN6TTkuMzA1IDE2LjI1djIuMDgzaDEuMzg5VjE2LjI1aC0xLjM5eiIgLz4KPC9zdmc+);background-repeat:no-repeat;background-position:center center;-webkit-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;-o-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms;transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;box-shadow:0 2px 1px -1px #0003,0 1px 1px #00000024,0 1px 3px #0000001f}.slider .circle:before{content:\"\";position:absolute;width:100%;height:100%;background:#ffffffbf;border-radius:inherit;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s;opacity:0}.ui-switch input:checked+.slider .circle{left:calc(100% - var(--circle-diameter));background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTQuMiAyLjVsLS43IDEuOC0xLjguNyAxLjguNy43IDEuOC42LTEuOEw2LjcgNWwtMS45LS43LS42LTEuOHptMTUgOC4zYTYuNyA2LjcgMCAxMS02LjYtNi42IDUuOCA1LjggMCAwMDYuNiA2LjZ6IiAvPgo8L3N2Zz4=);background-color:#003892}.ui-switch input:active+.slider .circle:before{-webkit-transition:0s;-o-transition:0s;transition:0s;opacity:1;width:0;height:0}\n"] }]
|
|
873
1177
|
}], propDecorators: { logoWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoWidth", required: false }] }], appVersion: [{ type: i0.Input, args: [{ isSignal: true, alias: "appVersion", required: false }] }], urlLogo: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlLogo", required: false }] }] } });
|
|
@@ -947,10 +1251,10 @@ class OnlyRangoPatternDirective {
|
|
|
947
1251
|
event.preventDefault();
|
|
948
1252
|
}
|
|
949
1253
|
}
|
|
950
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
951
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.
|
|
1254
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OnlyRangoPatternDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1255
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: OnlyRangoPatternDirective, isStandalone: true, selector: "[appOnlyRangoPattern]", host: { listeners: { "keydown": "onKeyDown($event)", "paste": "onPaste($event)" } }, ngImport: i0 });
|
|
952
1256
|
}
|
|
953
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1257
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OnlyRangoPatternDirective, decorators: [{
|
|
954
1258
|
type: Directive,
|
|
955
1259
|
args: [{
|
|
956
1260
|
selector: '[appOnlyRangoPattern]',
|
|
@@ -970,10 +1274,10 @@ class SelectAllOnFocusDirective {
|
|
|
970
1274
|
htmlInput.select();
|
|
971
1275
|
}
|
|
972
1276
|
}
|
|
973
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
974
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.
|
|
1277
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectAllOnFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1278
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: SelectAllOnFocusDirective, isStandalone: true, selector: "[appSelectAllOnFocus]", host: { listeners: { "onFocus": "selectAll($event)", "focus": "selectAll($event)" } }, ngImport: i0 });
|
|
975
1279
|
}
|
|
976
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SelectAllOnFocusDirective, decorators: [{
|
|
977
1281
|
type: Directive,
|
|
978
1282
|
args: [{
|
|
979
1283
|
selector: '[appSelectAllOnFocus]',
|
|
@@ -990,8 +1294,10 @@ const CACHE_KEYS = new InjectionToken('CACHE_KEYS');
|
|
|
990
1294
|
|
|
991
1295
|
class AuthorizeService {
|
|
992
1296
|
_cookieService = inject(CookieService);
|
|
1297
|
+
_router = inject(Router);
|
|
993
1298
|
helperJwt = new JwtHelperService();
|
|
994
1299
|
_isRefreshing = false;
|
|
1300
|
+
_securityService = inject(SecurityService);
|
|
995
1301
|
environment = inject(ENVIRONMENT);
|
|
996
1302
|
// Función para obtener opciones de cookies estándar
|
|
997
1303
|
getCookieOptions(expiryDate) {
|
|
@@ -1059,20 +1365,31 @@ class AuthorizeService {
|
|
|
1059
1365
|
tokenExpiryDate.setMinutes(tokenExpiryDate.getMinutes() + 30);
|
|
1060
1366
|
this.setCookie(this.environment.sessionStatus, Date.now().toString(), tokenExpiryDate);
|
|
1061
1367
|
}
|
|
1368
|
+
getLastActivity() {
|
|
1369
|
+
// Obtiene el valor de la cookie
|
|
1370
|
+
const lastActivity = this._cookieService.get(this.environment.sessionStatus);
|
|
1371
|
+
if (lastActivity) {
|
|
1372
|
+
// Intenta convertir el valor en un número
|
|
1373
|
+
const timestamp = parseInt(lastActivity, 10);
|
|
1374
|
+
// Verifica que sea un número válido
|
|
1375
|
+
if (!isNaN(timestamp)) {
|
|
1376
|
+
return timestamp;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
// Si no hay cookie o el valor no es válido, devuelve null
|
|
1380
|
+
return null;
|
|
1381
|
+
}
|
|
1062
1382
|
// Almacenar los tokens en cookies
|
|
1063
1383
|
tokenReload(tokens) {
|
|
1064
1384
|
const tokenExpiryDate = new Date();
|
|
1065
1385
|
tokenExpiryDate.setMinutes(tokenExpiryDate.getMinutes() + 30); // Access token expiry: 30 mins
|
|
1066
|
-
|
|
1067
|
-
refreshTokenExpiryDate
|
|
1068
|
-
// Guardar el access token y refresh token
|
|
1386
|
+
// Usar la fecha de expiración que viene del servidor para el refresh token
|
|
1387
|
+
const refreshTokenExpiryDate = new Date(tokens.refreshTokenExpiry);
|
|
1388
|
+
// Guardar el access token y refresh token con sus fechas de expiración
|
|
1069
1389
|
this.setCookie(this.environment.tokenName, tokens.token, tokenExpiryDate);
|
|
1070
1390
|
this.setCookie(this.environment.tokenNameRF, tokens.tokenRefresh, refreshTokenExpiryDate);
|
|
1071
1391
|
// Guardar el estado de sesión
|
|
1072
1392
|
this.setLastActivity();
|
|
1073
|
-
// Almacenar la fecha de expiración del refresh token en localStorage
|
|
1074
|
-
const expiryDate = new Date(tokens.refreshTokenExpiry).toISOString();
|
|
1075
|
-
localStorage.setItem(this.environment.refreshTokenExpiry, expiryDate);
|
|
1076
1393
|
}
|
|
1077
1394
|
getTokenValid(token) {
|
|
1078
1395
|
// Devuelve true si el token NO ha expirado
|
|
@@ -1118,10 +1435,179 @@ class AuthorizeService {
|
|
|
1118
1435
|
isTokenExpired: this.helperJwt.isTokenExpired(token),
|
|
1119
1436
|
};
|
|
1120
1437
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1438
|
+
/**
|
|
1439
|
+
* Verifica si el usuario está autenticado.
|
|
1440
|
+
*
|
|
1441
|
+
* La validación se basa en la existencia del refresh token en cookies.
|
|
1442
|
+
* El navegador gestiona automáticamente la expiración de las cookies.
|
|
1443
|
+
*
|
|
1444
|
+
* @returns `true` si el usuario está autenticado, `false` en caso contrario
|
|
1445
|
+
*/
|
|
1446
|
+
isAuthenticated() {
|
|
1447
|
+
const refreshToken = this.getTokenRefresh();
|
|
1448
|
+
return !!(refreshToken && refreshToken.trim() !== '');
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Cierra la sesión del usuario de forma segura y controlada.
|
|
1452
|
+
*
|
|
1453
|
+
* Este método implementa un proceso de logout robusto que:
|
|
1454
|
+
* 1. Verifica el estado actual de la sesión y la ubicación del usuario
|
|
1455
|
+
* 2. Intenta revocar el refresh token en el servidor (si existe)
|
|
1456
|
+
* 3. Limpia todos los datos de sesión local
|
|
1457
|
+
* 4. Redirige al usuario a la página de login
|
|
1458
|
+
*
|
|
1459
|
+
* **Casos manejados:**
|
|
1460
|
+
* - Usuario ya en página de login: Solo limpia datos locales
|
|
1461
|
+
* - Sin refresh token: Limpia datos locales y redirige
|
|
1462
|
+
* - Con refresh token: Intenta revocarlo, luego limpia y redirige
|
|
1463
|
+
* - Error al revocar: Limpia datos locales de todas formas (seguridad)
|
|
1464
|
+
* - Modo desarrollo: Maneja tokens de prueba correctamente
|
|
1465
|
+
*
|
|
1466
|
+
* **Importante:** Este método es **asíncrono** en su ejecución interna pero no retorna una promesa.
|
|
1467
|
+
* La redirección al login ocurre después de limpiar la sesión, independientemente del resultado de la revocación.
|
|
1468
|
+
*
|
|
1469
|
+
* @example
|
|
1470
|
+
* ```typescript
|
|
1471
|
+
* // Uso básico desde un componente
|
|
1472
|
+
* this.authorizeService.logout();
|
|
1473
|
+
*
|
|
1474
|
+
* // Uso con navegación posterior controlada
|
|
1475
|
+
* this.authorizeService.logout();
|
|
1476
|
+
* // La redirección al login es automática
|
|
1477
|
+
* ```
|
|
1478
|
+
*
|
|
1479
|
+
* @see {@link clearSessionData} para el proceso de limpieza de datos
|
|
1480
|
+
* @see {@link SecurityService.tokenRevok} para la revocación en el servidor
|
|
1481
|
+
*/
|
|
1482
|
+
logout() {
|
|
1483
|
+
try {
|
|
1484
|
+
// 1️⃣ Prevenir acciones innecesarias si ya está en el login
|
|
1485
|
+
if (this._router.url === '/login') {
|
|
1486
|
+
console.info('[AuthorizeService] Usuario ya en página de login, limpiando sesión local...');
|
|
1487
|
+
this.clearSessionData();
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
// 2️⃣ Obtener el refresh token de forma segura
|
|
1491
|
+
const refreshToken = this.getTokenRefresh();
|
|
1492
|
+
// 3️⃣ Si no hay refresh token, proceder con limpieza directa
|
|
1493
|
+
if (!refreshToken || refreshToken.trim() === '') {
|
|
1494
|
+
console.warn('[AuthorizeService] No se encontró refresh token, limpiando sesión local...');
|
|
1495
|
+
this.clearSessionData();
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
// 4️⃣ Intentar revocar el token en el servidor
|
|
1499
|
+
console.info('[AuthorizeService] Revocando refresh token en el servidor...');
|
|
1500
|
+
this._securityService.tokenRevok(refreshToken).subscribe({
|
|
1501
|
+
next: (success) => {
|
|
1502
|
+
if (success) {
|
|
1503
|
+
console.info('[AuthorizeService] Refresh token revocado exitosamente en el servidor');
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
console.warn('[AuthorizeService] El servidor no pudo revocar el token, pero continuando con logout');
|
|
1507
|
+
}
|
|
1508
|
+
this.clearSessionData();
|
|
1509
|
+
},
|
|
1510
|
+
error: (error) => {
|
|
1511
|
+
// 5️⃣ Manejar errores de revocación con información detallada
|
|
1512
|
+
console.error('[AuthorizeService] Error al revocar el refresh token:', {
|
|
1513
|
+
message: error?.message || 'Error desconocido',
|
|
1514
|
+
status: error?.status,
|
|
1515
|
+
statusText: error?.statusText,
|
|
1516
|
+
url: error?.url,
|
|
1517
|
+
});
|
|
1518
|
+
// Por seguridad, limpiar la sesión incluso si falla la revocación
|
|
1519
|
+
console.warn('[AuthorizeService] Limpiando sesión local por seguridad a pesar del error');
|
|
1520
|
+
this.clearSessionData();
|
|
1521
|
+
},
|
|
1522
|
+
complete: () => {
|
|
1523
|
+
console.info('[AuthorizeService] Proceso de logout completado');
|
|
1524
|
+
},
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
catch (error) {
|
|
1528
|
+
// 6️⃣ Capturar cualquier error inesperado en el proceso de logout
|
|
1529
|
+
console.error('[AuthorizeService] Error crítico durante el proceso de logout:', error);
|
|
1530
|
+
// Garantizar que la sesión se limpie incluso si ocurre un error inesperado
|
|
1531
|
+
try {
|
|
1532
|
+
this.clearSessionData();
|
|
1533
|
+
}
|
|
1534
|
+
catch (cleanupError) {
|
|
1535
|
+
console.error('[AuthorizeService] Error crítico al limpiar sesión:', cleanupError);
|
|
1536
|
+
// Último recurso: redirigir al login sin importar qué
|
|
1537
|
+
this._router.navigate(['/login']).catch((navError) => {
|
|
1538
|
+
console.error('[AuthorizeService] Error al navegar a login:', navError);
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Limpia todos los datos de sesión del usuario de forma segura.
|
|
1545
|
+
*
|
|
1546
|
+
* Este método privado se encarga de:
|
|
1547
|
+
* - Eliminar todas las cookies relacionadas con autenticación
|
|
1548
|
+
* - Limpiar el localStorage completamente
|
|
1549
|
+
* - Redirigir al usuario a la página de login
|
|
1550
|
+
*
|
|
1551
|
+
* **Cookies eliminadas:**
|
|
1552
|
+
* - Token de acceso (access token)
|
|
1553
|
+
* - Token de refresco (refresh token)
|
|
1554
|
+
* - Estado de sesión (session status)
|
|
1555
|
+
*
|
|
1556
|
+
* **Consideraciones:**
|
|
1557
|
+
* - Se eliminan las cookies con path '/' para asegurar su borrado
|
|
1558
|
+
* - En producción, también se considera el dominio configurado
|
|
1559
|
+
* - El localStorage se limpia completamente por seguridad
|
|
1560
|
+
* - La redirección es forzada incluso si hay errores previos
|
|
1561
|
+
*
|
|
1562
|
+
* @private
|
|
1563
|
+
*/
|
|
1564
|
+
clearSessionData() {
|
|
1565
|
+
try {
|
|
1566
|
+
console.info('[AuthorizeService] Iniciando limpieza de datos de sesión...');
|
|
1567
|
+
// 1️⃣ Eliminar cookies con path explícito
|
|
1568
|
+
const cookiesToDelete = [
|
|
1569
|
+
this.environment.tokenName,
|
|
1570
|
+
this.environment.tokenNameRF,
|
|
1571
|
+
this.environment.sessionStatus,
|
|
1572
|
+
];
|
|
1573
|
+
cookiesToDelete.forEach((cookieName) => {
|
|
1574
|
+
try {
|
|
1575
|
+
// Eliminar con path '/'
|
|
1576
|
+
this._cookieService.delete(cookieName, '/');
|
|
1577
|
+
// En producción, también intentar eliminar con dominio específico
|
|
1578
|
+
if (this.environment.production) {
|
|
1579
|
+
this._cookieService.delete(cookieName, '/', '.itgtxela.com');
|
|
1580
|
+
}
|
|
1581
|
+
console.debug(`[AuthorizeService] Cookie eliminada: ${cookieName}`);
|
|
1582
|
+
}
|
|
1583
|
+
catch (error) {
|
|
1584
|
+
console.error(`[AuthorizeService] Error al eliminar cookie ${cookieName}:`, error);
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
// 2️⃣ Limpiar localStorage
|
|
1588
|
+
try {
|
|
1589
|
+
localStorage.clear();
|
|
1590
|
+
console.debug('[AuthorizeService] localStorage limpiado');
|
|
1591
|
+
}
|
|
1592
|
+
catch (error) {
|
|
1593
|
+
console.error('[AuthorizeService] Error al limpiar localStorage:', error);
|
|
1594
|
+
}
|
|
1595
|
+
// 3️⃣ Redirigir al login
|
|
1596
|
+
console.info('[AuthorizeService] Redirigiendo a página de login...');
|
|
1597
|
+
this._router.navigate(['/login']).then(() => console.info('[AuthorizeService] Redirección exitosa a /login'), (error) => console.error('[AuthorizeService] Error en la redirección:', error));
|
|
1598
|
+
}
|
|
1599
|
+
catch (error) {
|
|
1600
|
+
console.error('[AuthorizeService] Error crítico en clearSessionData:', error);
|
|
1601
|
+
// Último recurso: intentar redirigir sin importar qué
|
|
1602
|
+
this._router.navigate(['/login']).catch((navError) => {
|
|
1603
|
+
console.error('[AuthorizeService] Error final al intentar redirigir:', navError);
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AuthorizeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1608
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AuthorizeService, providedIn: 'root' });
|
|
1123
1609
|
}
|
|
1124
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1610
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AuthorizeService, decorators: [{
|
|
1125
1611
|
type: Injectable,
|
|
1126
1612
|
args: [{
|
|
1127
1613
|
providedIn: 'root',
|
|
@@ -1173,10 +1659,10 @@ class ErrorHandlerService {
|
|
|
1173
1659
|
// Retornar el error para continuar con el flujo de manejo de errores
|
|
1174
1660
|
return throwError(() => new Error(technicalMessage));
|
|
1175
1661
|
}
|
|
1176
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1177
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
1662
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ErrorHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1663
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ErrorHandlerService, providedIn: 'root' });
|
|
1178
1664
|
}
|
|
1179
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1665
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ErrorHandlerService, decorators: [{
|
|
1180
1666
|
type: Injectable,
|
|
1181
1667
|
args: [{
|
|
1182
1668
|
providedIn: 'root',
|
|
@@ -1240,12 +1726,12 @@ const httpAuthorizeInterceptor = (req, next) => {
|
|
|
1240
1726
|
// Solicita el refresh del token
|
|
1241
1727
|
return _securityService.tokenRefresh(refreshToken).pipe(switchMap((response) => {
|
|
1242
1728
|
isRefreshing = false;
|
|
1243
|
-
_authorizeService.tokenReload(response); // Actualiza el token en el servicio
|
|
1244
|
-
refreshTokenSubject.next(response.token); // Emite el nuevo token
|
|
1729
|
+
_authorizeService.tokenReload(response.data); // Actualiza el token en el servicio
|
|
1730
|
+
refreshTokenSubject.next(response.data?.token); // Emite el nuevo token
|
|
1245
1731
|
// Repite la petición original con el nuevo token
|
|
1246
1732
|
return next(req.clone({
|
|
1247
1733
|
setHeaders: {
|
|
1248
|
-
Authorization: `Bearer ${response.token}`,
|
|
1734
|
+
Authorization: `Bearer ${response.data?.token}`,
|
|
1249
1735
|
},
|
|
1250
1736
|
}));
|
|
1251
1737
|
}), catchError((err) => {
|
|
@@ -1281,17 +1767,17 @@ function createInitialCache(cacheKeys) {
|
|
|
1281
1767
|
}
|
|
1282
1768
|
|
|
1283
1769
|
class DsxAddToolsModule {
|
|
1284
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1285
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.
|
|
1770
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DsxAddToolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1771
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: DsxAddToolsModule, imports: [IconDsxComponent, JsonValuesDebujComponent], exports: [CommonModule,
|
|
1286
1772
|
FormsModule,
|
|
1287
1773
|
IconDsxComponent,
|
|
1288
1774
|
JsonValuesDebujComponent,
|
|
1289
1775
|
ReactiveFormsModule] });
|
|
1290
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.
|
|
1776
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DsxAddToolsModule, imports: [CommonModule,
|
|
1291
1777
|
FormsModule,
|
|
1292
1778
|
ReactiveFormsModule] });
|
|
1293
1779
|
}
|
|
1294
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1780
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DsxAddToolsModule, decorators: [{
|
|
1295
1781
|
type: NgModule,
|
|
1296
1782
|
args: [{
|
|
1297
1783
|
declarations: [],
|
|
@@ -1347,8 +1833,8 @@ const PRIME_NG_MODULES = [
|
|
|
1347
1833
|
TooltipModule,
|
|
1348
1834
|
];
|
|
1349
1835
|
class PrimeNgModule {
|
|
1350
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1351
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.
|
|
1836
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PrimeNgModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1837
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: PrimeNgModule, exports: [AccordionModule,
|
|
1352
1838
|
AutoCompleteModule,
|
|
1353
1839
|
AutoFocusModule,
|
|
1354
1840
|
AvatarGroupModule,
|
|
@@ -1385,7 +1871,7 @@ class PrimeNgModule {
|
|
|
1385
1871
|
ToastModule,
|
|
1386
1872
|
ToggleButtonModule,
|
|
1387
1873
|
TooltipModule] });
|
|
1388
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.
|
|
1874
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PrimeNgModule, imports: [AccordionModule,
|
|
1389
1875
|
AutoCompleteModule,
|
|
1390
1876
|
AutoFocusModule,
|
|
1391
1877
|
AvatarGroupModule,
|
|
@@ -1423,7 +1909,7 @@ class PrimeNgModule {
|
|
|
1423
1909
|
ToggleButtonModule,
|
|
1424
1910
|
TooltipModule] });
|
|
1425
1911
|
}
|
|
1426
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1912
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PrimeNgModule, decorators: [{
|
|
1427
1913
|
type: NgModule,
|
|
1428
1914
|
args: [{
|
|
1429
1915
|
declarations: [],
|
|
@@ -1460,10 +1946,10 @@ class TruncatePipe {
|
|
|
1460
1946
|
// Trunca el texto y añade el ellipsis si la longitud del texto supera el límite.
|
|
1461
1947
|
return value.length > limit ? value.slice(0, limit) + ellipsis : value;
|
|
1462
1948
|
}
|
|
1463
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1464
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.
|
|
1949
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TruncatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1950
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: TruncatePipe, isStandalone: true, name: "truncate" });
|
|
1465
1951
|
}
|
|
1466
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
1952
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TruncatePipe, decorators: [{
|
|
1467
1953
|
type: Pipe,
|
|
1468
1954
|
args: [{
|
|
1469
1955
|
name: 'truncate',
|
|
@@ -1565,10 +2051,10 @@ class CacheService {
|
|
|
1565
2051
|
this._options.set(current);
|
|
1566
2052
|
this.alert.toastrAlerts(2, 'Estado', 'Datos actualizados (cache).', 2, 1000);
|
|
1567
2053
|
}
|
|
1568
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1569
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
2054
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2055
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CacheService, providedIn: 'root' });
|
|
1570
2056
|
}
|
|
1571
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
2057
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CacheService, decorators: [{
|
|
1572
2058
|
type: Injectable,
|
|
1573
2059
|
args: [{
|
|
1574
2060
|
providedIn: 'root',
|
|
@@ -1603,10 +2089,10 @@ class EndpointService {
|
|
|
1603
2089
|
delete(endpoint, id, softDelete = true) {
|
|
1604
2090
|
return this.http.delete(`${this.getUrl(endpoint)}/delete/${id}/${softDelete}`);
|
|
1605
2091
|
}
|
|
1606
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
1607
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
2092
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EndpointService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2093
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EndpointService, providedIn: 'root' });
|
|
1608
2094
|
}
|
|
1609
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
2095
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EndpointService, decorators: [{
|
|
1610
2096
|
type: Injectable,
|
|
1611
2097
|
args: [{
|
|
1612
2098
|
providedIn: 'root',
|
|
@@ -2071,10 +2557,10 @@ class UtilityAddService {
|
|
|
2071
2557
|
this._serviceAlerta.toastrAlerts(4, 'Error', error instanceof Error ? error.message : String(error), 2);
|
|
2072
2558
|
}
|
|
2073
2559
|
}
|
|
2074
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.
|
|
2075
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.
|
|
2560
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UtilityAddService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2561
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UtilityAddService, providedIn: 'root' });
|
|
2076
2562
|
}
|
|
2077
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.
|
|
2563
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UtilityAddService, decorators: [{
|
|
2078
2564
|
type: Injectable,
|
|
2079
2565
|
args: [{
|
|
2080
2566
|
providedIn: 'root',
|
|
@@ -2312,5 +2798,5 @@ function CUICorrecto(cui) {
|
|
|
2312
2798
|
* Generated bundle index. Do not edit.
|
|
2313
2799
|
*/
|
|
2314
2800
|
|
|
2315
|
-
export { AlertaService, AppMessageErrorComponent, AuthorizeService, CACHE_KEYS, CacheService, DsxAddToolsModule, ENVIRONMENT, EndpointService, ErrorHandlerService, INITIAL_PARAMETERS, IconDsxComponent, JsonHighlightPipe, JsonValuesDebujComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, NavbarDsxComponent, OnlyRangoPatternDirective, ParameterValuesService, PrimeNgModule, SecurityService, SelectAllOnFocusDirective, TruncatePipe, UtilityAddService, atLeastOneFieldRequiredValidator, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, httpAuthorizeInterceptor, nitValidator };
|
|
2801
|
+
export { AlertaService, AppMessageErrorComponent, AuthorizeService, CACHE_KEYS, CacheService, DsxAddToolsModule, ENVIRONMENT, EndpointService, ErrorHandlerService, INITIAL_PARAMETERS, IconDsxComponent, JsonHighlightPipe, JsonValuesDebujComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, NavbarDsxComponent, OnlyRangoPatternDirective, ParameterValuesService, PrimeNgModule, SecurityService, SelectAllOnFocusDirective, TruncatePipe, UtilityAddService, atLeastOneFieldRequiredValidator, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, httpAuthorizeInterceptor, nitValidator, provideEnvironment, validateEnvironmentConfig };
|
|
2316
2802
|
//# sourceMappingURL=ngx-dsxlibrary.mjs.map
|