@sd-angular/core 19.0.36 → 19.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/components/index.d.ts +1 -0
- package/components/table/src/table.component.d.ts +1 -1
- package/components/timeline/index.d.ts +2 -0
- package/components/{history/models/history.model.d.ts → timeline/models/timeline.model.d.ts} +1 -1
- package/components/timeline/src/timeline.component.d.ts +7 -0
- package/configurations/src/sd-core.configuration.d.ts +0 -1
- package/fesm2022/sd-angular-core-components-tab-router.mjs +10 -4
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +100 -29
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-timeline.mjs +49 -0
- package/fesm2022/sd-angular-core-components-timeline.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components.mjs +1 -0
- package/fesm2022/sd-angular-core-components.mjs.map +1 -1
- package/fesm2022/sd-angular-core-configurations.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +10 -10
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +4 -4
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/i18n/src/en.d.ts +1 -1
- package/package.json +9 -17
- package/components/base/index.d.ts +0 -1
- package/components/base/src/base-secure.component.d.ts +0 -8
- package/components/history/index.d.ts +0 -1
- package/components/history/src/history.component.d.ts +0 -7
- package/fesm2022/sd-angular-core-components-base.mjs +0 -23
- package/fesm2022/sd-angular-core-components-base.mjs.map +0 -1
- package/fesm2022/sd-angular-core-components-history.mjs +0 -51
- package/fesm2022/sd-angular-core-components-history.mjs.map +0 -1
- package/fesm2022/sd-angular-core-services-license.mjs +0 -97
- package/fesm2022/sd-angular-core-services-license.mjs.map +0 -1
- package/services/license/index.d.ts +0 -1
- package/services/license/src/license.service.d.ts +0 -9
- /package/components/{history → timeline}/pipes/view-date.pipe.d.ts +0 -0
package/i18n/src/en.d.ts
CHANGED
|
@@ -290,7 +290,7 @@ export declare const EN_MESSAGES: {
|
|
|
290
290
|
readonly 'core.component.form-builder.break': "Break";
|
|
291
291
|
readonly 'core.component.code-editor.copied': "Copied!";
|
|
292
292
|
readonly 'core.component.code-editor.copy': "Copy code";
|
|
293
|
-
readonly 'core.component.
|
|
293
|
+
readonly 'core.component.timeline.by': "By";
|
|
294
294
|
readonly 'core.component.import-excel.choose-hint': "Choose an .xlsx template file with up to {limit} rows.";
|
|
295
295
|
readonly 'core.component.import-excel.choose-file': "Choose Excel file";
|
|
296
296
|
readonly 'core.component.import-excel.template': "Download template";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-angular/core",
|
|
3
|
-
"version": "19.0.
|
|
3
|
+
"version": "19.0.38",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
6
6
|
"@angular/core": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"types": "./components/index.d.ts",
|
|
43
43
|
"default": "./fesm2022/sd-angular-core-components.mjs"
|
|
44
44
|
},
|
|
45
|
-
"./directives": {
|
|
46
|
-
"types": "./directives/index.d.ts",
|
|
47
|
-
"default": "./fesm2022/sd-angular-core-directives.mjs"
|
|
48
|
-
},
|
|
49
45
|
"./configurations": {
|
|
50
46
|
"types": "./configurations/index.d.ts",
|
|
51
47
|
"default": "./fesm2022/sd-angular-core-configurations.mjs"
|
|
52
48
|
},
|
|
49
|
+
"./directives": {
|
|
50
|
+
"types": "./directives/index.d.ts",
|
|
51
|
+
"default": "./fesm2022/sd-angular-core-directives.mjs"
|
|
52
|
+
},
|
|
53
53
|
"./forms": {
|
|
54
54
|
"types": "./forms/index.d.ts",
|
|
55
55
|
"default": "./fesm2022/sd-angular-core-forms.mjs"
|
|
@@ -102,10 +102,6 @@
|
|
|
102
102
|
"types": "./components/badge/index.d.ts",
|
|
103
103
|
"default": "./fesm2022/sd-angular-core-components-badge.mjs"
|
|
104
104
|
},
|
|
105
|
-
"./components/base": {
|
|
106
|
-
"types": "./components/base/index.d.ts",
|
|
107
|
-
"default": "./fesm2022/sd-angular-core-components-base.mjs"
|
|
108
|
-
},
|
|
109
105
|
"./components/button": {
|
|
110
106
|
"types": "./components/button/index.d.ts",
|
|
111
107
|
"default": "./fesm2022/sd-angular-core-components-button.mjs"
|
|
@@ -138,10 +134,6 @@
|
|
|
138
134
|
"types": "./components/form-generic/index.d.ts",
|
|
139
135
|
"default": "./fesm2022/sd-angular-core-components-form-generic.mjs"
|
|
140
136
|
},
|
|
141
|
-
"./components/history": {
|
|
142
|
-
"types": "./components/history/index.d.ts",
|
|
143
|
-
"default": "./fesm2022/sd-angular-core-components-history.mjs"
|
|
144
|
-
},
|
|
145
137
|
"./components/import-excel": {
|
|
146
138
|
"types": "./components/import-excel/index.d.ts",
|
|
147
139
|
"default": "./fesm2022/sd-angular-core-components-import-excel.mjs"
|
|
@@ -214,6 +206,10 @@
|
|
|
214
206
|
"types": "./components/table/index.d.ts",
|
|
215
207
|
"default": "./fesm2022/sd-angular-core-components-table.mjs"
|
|
216
208
|
},
|
|
209
|
+
"./components/timeline": {
|
|
210
|
+
"types": "./components/timeline/index.d.ts",
|
|
211
|
+
"default": "./fesm2022/sd-angular-core-components-timeline.mjs"
|
|
212
|
+
},
|
|
217
213
|
"./components/tree": {
|
|
218
214
|
"types": "./components/tree/index.d.ts",
|
|
219
215
|
"default": "./fesm2022/sd-angular-core-components-tree.mjs"
|
|
@@ -338,10 +334,6 @@
|
|
|
338
334
|
"types": "./services/excel/index.d.ts",
|
|
339
335
|
"default": "./fesm2022/sd-angular-core-services-excel.mjs"
|
|
340
336
|
},
|
|
341
|
-
"./services/license": {
|
|
342
|
-
"types": "./services/license/index.d.ts",
|
|
343
|
-
"default": "./fesm2022/sd-angular-core-services-license.mjs"
|
|
344
|
-
},
|
|
345
337
|
"./services/loading": {
|
|
346
338
|
"types": "./services/loading/index.d.ts",
|
|
347
339
|
"default": "./fesm2022/sd-angular-core-services-loading.mjs"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src/base-secure.component';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { SdLicenseService } from '@sd-angular/core/services/license';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare abstract class SdBaseSecureComponent {
|
|
4
|
-
protected licenseService: SdLicenseService;
|
|
5
|
-
constructor();
|
|
6
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SdBaseSecureComponent, never>;
|
|
7
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<SdBaseSecureComponent, never, never, {}, {}, never, never, true, never>;
|
|
8
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src/history.component';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SdHistoryItemType } from '../models/history.model';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class SdHistoryItem {
|
|
4
|
-
items: SdHistoryItemType[];
|
|
5
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SdHistoryItem, never>;
|
|
6
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SdHistoryItem, "sd-history", never, { "items": { "alias": "items"; "required": false; }; }, {}, never, never, true, never>;
|
|
7
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Directive } from '@angular/core';
|
|
3
|
-
import { SdLicenseService } from '@sd-angular/core/services/license';
|
|
4
|
-
|
|
5
|
-
// base.component.ts
|
|
6
|
-
class SdBaseSecureComponent {
|
|
7
|
-
licenseService = inject(SdLicenseService);
|
|
8
|
-
constructor() {
|
|
9
|
-
this.licenseService.enforceLicense();
|
|
10
|
-
}
|
|
11
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdBaseSecureComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
12
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: SdBaseSecureComponent, isStandalone: true, ngImport: i0 });
|
|
13
|
-
}
|
|
14
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdBaseSecureComponent, decorators: [{
|
|
15
|
-
type: Directive
|
|
16
|
-
}], ctorParameters: () => [] });
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Generated bundle index. Do not edit.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export { SdBaseSecureComponent };
|
|
23
|
-
//# sourceMappingURL=sd-angular-core-components-base.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-base.mjs","sources":["../../../projects/sd-angular/components/base/src/base-secure.component.ts","../../../projects/sd-angular/components/base/sd-angular-core-components-base.ts"],"sourcesContent":["// base.component.ts\nimport { Directive, inject } from '@angular/core';\nimport { SdLicenseService } from '@sd-angular/core/services/license';\n\n@Directive() // Dùng Directive cho abstract class trong Angular\nexport abstract class SdBaseSecureComponent {\n protected licenseService = inject(SdLicenseService);\n constructor() {\n this.licenseService.enforceLicense();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAAA;MAKsB,qBAAqB,CAAA;AAC/B,IAAA,cAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACnD,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE;IACtC;wGAJoB,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAArB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAD1C;;;ACJD;;AAEG;;;;"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import * as i1 from '@angular/common';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import * as i0 from '@angular/core';
|
|
4
|
-
import { Pipe, Injectable, Input, Component } from '@angular/core';
|
|
5
|
-
import { SdBadge } from '@sd-angular/core/components/badge';
|
|
6
|
-
import { DateUtilities } from '@sd-angular/core/utilities';
|
|
7
|
-
import { EMPTY_STR } from '@sdcorejs/utils/constants';
|
|
8
|
-
import { TranslatePipe } from '@sd-angular/core/i18n';
|
|
9
|
-
|
|
10
|
-
class ViewDateTimePipe {
|
|
11
|
-
transform(value) {
|
|
12
|
-
if (!value || !DateUtilities.isDate(value)) {
|
|
13
|
-
return EMPTY_STR;
|
|
14
|
-
}
|
|
15
|
-
return DateUtilities.toFormat(value, 'HH:mm dd/MM/yyyy');
|
|
16
|
-
}
|
|
17
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ViewDateTimePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
18
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.21", ngImport: i0, type: ViewDateTimePipe, isStandalone: true, name: "viewDateTime" });
|
|
19
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ViewDateTimePipe, providedIn: 'root' });
|
|
20
|
-
}
|
|
21
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ViewDateTimePipe, decorators: [{
|
|
22
|
-
type: Pipe,
|
|
23
|
-
args: [{
|
|
24
|
-
name: 'viewDateTime',
|
|
25
|
-
standalone: true,
|
|
26
|
-
}]
|
|
27
|
-
}, {
|
|
28
|
-
type: Injectable,
|
|
29
|
-
args: [{
|
|
30
|
-
providedIn: 'root',
|
|
31
|
-
}]
|
|
32
|
-
}] });
|
|
33
|
-
|
|
34
|
-
class SdHistoryItem {
|
|
35
|
-
items = [];
|
|
36
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdHistoryItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
37
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdHistoryItem, isStandalone: true, selector: "sd-history", inputs: { items: "items" }, ngImport: i0, template: "<div class=\"sd-history\">\n <div class=\"history-container\">\n <div class=\"history-line\"></div>\n <div *ngFor=\"let item of items; let i = index\" class=\"history-item\">\n <div class=\"dot\"></div>\n <div class=\"card\">\n <div class=\"header\">\n <div class=\"title-wrapper\">\n <span class=\"title\">{{ item.title }}</span>\n <span class=\"status\">\n @if (item?.status) {\n <sd-badge\n [icon]=\"item.status?.icon\"\n [title]=\"item.status?.title\"\n [color]=\"item.status?.color\"></sd-badge>\n }\n </span>\n </div>\n <span class=\"date\">{{ item?.date | viewDateTime }}</span>\n </div>\n <div class=\"meta\">\n @if (item?.actor) {\n <span>{{ 'core.component.history.by' | translate }} <strong>@{{ item.actor }}</strong></span>\n }\n @if (item?.source) {\n <span> · {{ item.source }}</span>\n }\n </div>\n <div class=\"description\">\n {{ item?.description }}\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".sd-history{padding:16px}.history-container{position:relative;padding-left:20px;font-size:14px;line-height:20px;min-width:470px;max-width:100%}.history-line{position:absolute;left:8px;top:0;bottom:0;width:2px;background-color:#94b0ff}.history-item{position:relative;margin-bottom:16px;padding-left:10px}.history-item .dot{position:absolute;left:-16px;top:12px;width:12px;height:12px;background-color:#94b0ff;border-radius:50%}.history-item .card{background:#fff;border-radius:6px;box-shadow:0 2px 4px #0000001a;padding:8px 8px 8px 16px}.history-item .card .header{display:flex;justify-content:space-between;align-items:center}.history-item .card .header .title-wrapper{display:flex;align-items:flex-start;padding-right:8px}.history-item .card .header .title{margin-right:8px;color:#757575}.history-item .card .header .status{display:flex;align-items:center}.history-item .card .header .status mat-icon{margin-right:4px}.history-item .card .header .date{color:#757575;font-size:12px;line-height:16px}.history-item .card .meta{color:#757575;margin-top:4px}.history-item .card .meta strong{color:#000}.history-item .card .description{margin-top:4px;color:#000;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: SdBadge, selector: "sd-badge", inputs: ["type", "color", "primary", "secondary", "success", "info", "warning", "error", "fontSet", "title", "description", "tooltip", "icon", "size"], outputs: ["click"] }, { kind: "pipe", type: ViewDateTimePipe, name: "viewDateTime" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
38
|
-
}
|
|
39
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdHistoryItem, decorators: [{
|
|
40
|
-
type: Component,
|
|
41
|
-
args: [{ selector: 'sd-history', imports: [CommonModule, SdBadge, ViewDateTimePipe, TranslatePipe], template: "<div class=\"sd-history\">\n <div class=\"history-container\">\n <div class=\"history-line\"></div>\n <div *ngFor=\"let item of items; let i = index\" class=\"history-item\">\n <div class=\"dot\"></div>\n <div class=\"card\">\n <div class=\"header\">\n <div class=\"title-wrapper\">\n <span class=\"title\">{{ item.title }}</span>\n <span class=\"status\">\n @if (item?.status) {\n <sd-badge\n [icon]=\"item.status?.icon\"\n [title]=\"item.status?.title\"\n [color]=\"item.status?.color\"></sd-badge>\n }\n </span>\n </div>\n <span class=\"date\">{{ item?.date | viewDateTime }}</span>\n </div>\n <div class=\"meta\">\n @if (item?.actor) {\n <span>{{ 'core.component.history.by' | translate }} <strong>@{{ item.actor }}</strong></span>\n }\n @if (item?.source) {\n <span> · {{ item.source }}</span>\n }\n </div>\n <div class=\"description\">\n {{ item?.description }}\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".sd-history{padding:16px}.history-container{position:relative;padding-left:20px;font-size:14px;line-height:20px;min-width:470px;max-width:100%}.history-line{position:absolute;left:8px;top:0;bottom:0;width:2px;background-color:#94b0ff}.history-item{position:relative;margin-bottom:16px;padding-left:10px}.history-item .dot{position:absolute;left:-16px;top:12px;width:12px;height:12px;background-color:#94b0ff;border-radius:50%}.history-item .card{background:#fff;border-radius:6px;box-shadow:0 2px 4px #0000001a;padding:8px 8px 8px 16px}.history-item .card .header{display:flex;justify-content:space-between;align-items:center}.history-item .card .header .title-wrapper{display:flex;align-items:flex-start;padding-right:8px}.history-item .card .header .title{margin-right:8px;color:#757575}.history-item .card .header .status{display:flex;align-items:center}.history-item .card .header .status mat-icon{margin-right:4px}.history-item .card .header .date{color:#757575;font-size:12px;line-height:16px}.history-item .card .meta{color:#757575;margin-top:4px}.history-item .card .meta strong{color:#000}.history-item .card .description{margin-top:4px;color:#000;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
42
|
-
}], propDecorators: { items: [{
|
|
43
|
-
type: Input
|
|
44
|
-
}] } });
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Generated bundle index. Do not edit.
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
export { SdHistoryItem };
|
|
51
|
-
//# sourceMappingURL=sd-angular-core-components-history.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-history.mjs","sources":["../../../projects/sd-angular/components/history/pipes/view-date.pipe.ts","../../../projects/sd-angular/components/history/src/history.component.ts","../../../projects/sd-angular/components/history/src/history.component.html","../../../projects/sd-angular/components/history/sd-angular-core-components-history.ts"],"sourcesContent":["import { Injectable, Pipe, PipeTransform } from '@angular/core';\nimport { DateUtilities } from '@sd-angular/core/utilities';\nimport { EMPTY_STR } from '@sdcorejs/utils/constants';\n\n@Pipe({\n name: 'viewDateTime',\n standalone: true,\n})\n@Injectable({\n providedIn: 'root',\n})\nexport class ViewDateTimePipe implements PipeTransform {\n transform(value: any): string {\n if (!value || !DateUtilities.isDate(value)) {\n return EMPTY_STR;\n }\n return DateUtilities.toFormat(value, 'HH:mm dd/MM/yyyy');\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { Component, Input } from '@angular/core';\nimport { SdBadge } from '@sd-angular/core/components/badge';\nimport { SdHistoryItemType } from '../models/history.model';\nimport { ViewDateTimePipe } from '../pipes/view-date.pipe';\nimport { TranslatePipe } from '@sd-angular/core/i18n';\n\n@Component({\n selector: 'sd-history',\n imports: [CommonModule, SdBadge, ViewDateTimePipe, TranslatePipe],\n templateUrl: './history.component.html',\n styleUrl: './history.component.scss',\n})\nexport class SdHistoryItem {\n @Input() items: SdHistoryItemType[] = [];\n}\n","<div class=\"sd-history\">\n <div class=\"history-container\">\n <div class=\"history-line\"></div>\n <div *ngFor=\"let item of items; let i = index\" class=\"history-item\">\n <div class=\"dot\"></div>\n <div class=\"card\">\n <div class=\"header\">\n <div class=\"title-wrapper\">\n <span class=\"title\">{{ item.title }}</span>\n <span class=\"status\">\n @if (item?.status) {\n <sd-badge\n [icon]=\"item.status?.icon\"\n [title]=\"item.status?.title\"\n [color]=\"item.status?.color\"></sd-badge>\n }\n </span>\n </div>\n <span class=\"date\">{{ item?.date | viewDateTime }}</span>\n </div>\n <div class=\"meta\">\n @if (item?.actor) {\n <span>{{ 'core.component.history.by' | translate }} <strong>@{{ item.actor }}</strong></span>\n }\n @if (item?.source) {\n <span> · {{ item.source }}</span>\n }\n </div>\n <div class=\"description\">\n {{ item?.description }}\n </div>\n </div>\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAWa,gBAAgB,CAAA;AAC3B,IAAA,SAAS,CAAC,KAAU,EAAA;QAClB,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAC1C,YAAA,OAAO,SAAS;QAClB;QACA,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IAC1D;wGANW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA;sGAAhB,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,cAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,gBAAgB,cAFf,MAAM,EAAA,CAAA;;4FAEP,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAP5B,IAAI;AAAC,YAAA,IAAA,EAAA,CAAA;AACJ,oBAAA,IAAI,EAAE,cAAc;AACpB,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;kBACA,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA;;;MCGY,aAAa,CAAA;IACf,KAAK,GAAwB,EAAE;wGAD7B,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECb1B,msCAmCA,EAAA,MAAA,EAAA,CAAA,qvCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED1BY,YAAY,4JAAE,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,EAAA,SAAA,EAAA,WAAA,EAAA,SAAA,EAAA,MAAA,EAAA,SAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,aAAA,EAAA,SAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAE,gBAAgB,EAAA,IAAA,EAAA,cAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAE,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA;;4FAIrD,aAAa,EAAA,UAAA,EAAA,CAAA;kBANzB,SAAS;+BACE,YAAY,EAAA,OAAA,EACb,CAAC,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAA,QAAA,EAAA,msCAAA,EAAA,MAAA,EAAA,CAAA,qvCAAA,CAAA,EAAA;8BAKxD,KAAK,EAAA,CAAA;sBAAb;;;AEdH;;AAEG;;;;"}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable } from '@angular/core';
|
|
3
|
-
import { SD_CORE_CONFIGURATION } from '@sd-angular/core/configurations';
|
|
4
|
-
|
|
5
|
-
class SdLicenseService {
|
|
6
|
-
#SALT = 'angular-core-976e2fa6f8b44dadbc63f87b057a331f';
|
|
7
|
-
#isValid = false;
|
|
8
|
-
coreConfiguration = inject(SD_CORE_CONFIGURATION, { optional: true });
|
|
9
|
-
constructor() {
|
|
10
|
-
this.#verify();
|
|
11
|
-
}
|
|
12
|
-
enforceLicense = () => {
|
|
13
|
-
if (!this.#isValid) {
|
|
14
|
-
this.#throwSecurityError();
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
#verify = () => {
|
|
18
|
-
const hostname = window.location.hostname; // Ví dụ: store.uat.nexa.mobi
|
|
19
|
-
// 1. Bypass Localhost
|
|
20
|
-
if (this.#isLocalhost(hostname)) {
|
|
21
|
-
this.#isValid = true;
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const configKeys = this.#getConfiguredKeys();
|
|
25
|
-
if (configKeys.length === 0) {
|
|
26
|
-
this.#isValid = false;
|
|
27
|
-
this.#throwSecurityError();
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
// 2. CHECK EXACT MATCH (Ưu tiên khớp chính xác 100%)
|
|
31
|
-
// Hash chuỗi: "store.uat.nexa.mobi" + SALT
|
|
32
|
-
if (this.#checkMatch(hostname, configKeys)) {
|
|
33
|
-
this.#isValid = true;
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
// 3. CHECK WILDCARD MATCH (Thử các trường hợp có dấu *)
|
|
37
|
-
const parts = hostname.split('.'); // ["store", "uat", "nexa", "mobi"]
|
|
38
|
-
// Lặp để cắt dần subdomain bên trái và thêm "*." vào
|
|
39
|
-
// Điều kiện > 2 để đảm bảo không check các case vô nghĩa như *.mobi hay *.com
|
|
40
|
-
while (parts.length > 2) {
|
|
41
|
-
parts.shift(); // Bỏ phần đầu: ["uat", "nexa", "mobi"]
|
|
42
|
-
// Tạo domain wildcard: "*.uat.nexa.mobi"
|
|
43
|
-
const wildcardDomain = '*.' + parts.join('.');
|
|
44
|
-
// Hash chuỗi: "*.uat.nexa.mobi" + SALT
|
|
45
|
-
if (this.#checkMatch(wildcardDomain, configKeys)) {
|
|
46
|
-
this.#isValid = true;
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// Nếu chạy hết vòng lặp mà không khớp cái nào
|
|
51
|
-
this.#isValid = false;
|
|
52
|
-
this.#throwSecurityError();
|
|
53
|
-
};
|
|
54
|
-
// Helper để check xem hash của input có nằm trong list key không
|
|
55
|
-
#checkMatch = (inputString, validKeys) => {
|
|
56
|
-
const hash = this.#generateHash(inputString + this.#SALT);
|
|
57
|
-
return validKeys.includes(hash);
|
|
58
|
-
};
|
|
59
|
-
#getConfiguredKeys = () => {
|
|
60
|
-
const keyOrKeys = this.coreConfiguration?.licenseKey;
|
|
61
|
-
if (!keyOrKeys)
|
|
62
|
-
return [];
|
|
63
|
-
return Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];
|
|
64
|
-
};
|
|
65
|
-
#isLocalhost = (domain) => {
|
|
66
|
-
return domain === 'localhost' || domain === '127.0.0.1' || domain.includes('localhost');
|
|
67
|
-
};
|
|
68
|
-
#generateHash = (input) => {
|
|
69
|
-
let hash = 0;
|
|
70
|
-
if (input.length === 0)
|
|
71
|
-
return hash.toString();
|
|
72
|
-
for (let i = 0; i < input.length; i++) {
|
|
73
|
-
const char = input.charCodeAt(i);
|
|
74
|
-
hash = (hash << 5) - hash + char;
|
|
75
|
-
hash = hash & hash;
|
|
76
|
-
}
|
|
77
|
-
return btoa(hash.toString() + 'signed');
|
|
78
|
-
};
|
|
79
|
-
#throwSecurityError = () => {
|
|
80
|
-
throw new Error(`[Security] Unauthorized usage of UI Lib on domain: ${window.location.hostname}`);
|
|
81
|
-
};
|
|
82
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
83
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, providedIn: 'root' });
|
|
84
|
-
}
|
|
85
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, decorators: [{
|
|
86
|
-
type: Injectable,
|
|
87
|
-
args: [{
|
|
88
|
-
providedIn: 'root',
|
|
89
|
-
}]
|
|
90
|
-
}], ctorParameters: () => [] });
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Generated bundle index. Do not edit.
|
|
94
|
-
*/
|
|
95
|
-
|
|
96
|
-
export { SdLicenseService };
|
|
97
|
-
//# sourceMappingURL=sd-angular-core-services-license.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-services-license.mjs","sources":["../../../projects/sd-angular/services/license/src/license.service.ts","../../../projects/sd-angular/services/license/sd-angular-core-services-license.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { ISdCoreConfiguration, SD_CORE_CONFIGURATION } from '@sd-angular/core/configurations';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SdLicenseService {\n readonly #SALT = 'angular-core-976e2fa6f8b44dadbc63f87b057a331f';\n #isValid = false;\n private readonly coreConfiguration: ISdCoreConfiguration | null = inject(SD_CORE_CONFIGURATION, { optional: true });\n\n constructor() {\n this.#verify();\n }\n\n enforceLicense = () => {\n if (!this.#isValid) {\n this.#throwSecurityError();\n }\n };\n\n #verify = () => {\n const hostname = window.location.hostname; // Ví dụ: store.uat.nexa.mobi\n\n // 1. Bypass Localhost\n if (this.#isLocalhost(hostname)) {\n this.#isValid = true;\n return;\n }\n\n const configKeys = this.#getConfiguredKeys();\n if (configKeys.length === 0) {\n this.#isValid = false;\n this.#throwSecurityError();\n return;\n }\n\n // 2. CHECK EXACT MATCH (Ưu tiên khớp chính xác 100%)\n // Hash chuỗi: \"store.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(hostname, configKeys)) {\n this.#isValid = true;\n return;\n }\n\n // 3. CHECK WILDCARD MATCH (Thử các trường hợp có dấu *)\n const parts = hostname.split('.'); // [\"store\", \"uat\", \"nexa\", \"mobi\"]\n\n // Lặp để cắt dần subdomain bên trái và thêm \"*.\" vào\n // Điều kiện > 2 để đảm bảo không check các case vô nghĩa như *.mobi hay *.com\n while (parts.length > 2) {\n parts.shift(); // Bỏ phần đầu: [\"uat\", \"nexa\", \"mobi\"]\n \n // Tạo domain wildcard: \"*.uat.nexa.mobi\"\n const wildcardDomain = '*.' + parts.join('.'); \n \n // Hash chuỗi: \"*.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(wildcardDomain, configKeys)) {\n this.#isValid = true;\n return;\n }\n }\n\n // Nếu chạy hết vòng lặp mà không khớp cái nào\n this.#isValid = false;\n this.#throwSecurityError();\n };\n\n // Helper để check xem hash của input có nằm trong list key không\n #checkMatch = (inputString: string, validKeys: string[]): boolean => {\n const hash = this.#generateHash(inputString + this.#SALT);\n return validKeys.includes(hash);\n };\n\n #getConfiguredKeys = (): string[] => {\n const keyOrKeys = this.coreConfiguration?.licenseKey;\n if (!keyOrKeys) return [];\n return Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];\n };\n\n #isLocalhost = (domain: string) => {\n return domain === 'localhost' || domain === '127.0.0.1' || domain.includes('localhost');\n };\n\n #generateHash = (input: string): string => {\n let hash = 0;\n if (input.length === 0) return hash.toString();\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return btoa(hash.toString() + 'signed');\n };\n\n #throwSecurityError = () => {\n throw new Error(`[Security] Unauthorized usage of UI Lib on domain: ${window.location.hostname}`);\n };\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './src/license.service';
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as i0 from "@angular/core";
|
|
2
|
-
export declare class SdLicenseService {
|
|
3
|
-
#private;
|
|
4
|
-
private readonly coreConfiguration;
|
|
5
|
-
constructor();
|
|
6
|
-
enforceLicense: () => void;
|
|
7
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SdLicenseService, never>;
|
|
8
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<SdLicenseService>;
|
|
9
|
-
}
|
|
File without changes
|