@rolatech/angular-platform 20.3.0-beta.2

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.
Files changed (51) hide show
  1. package/README.md +3 -0
  2. package/fesm2022/rolatech-angular-platform-application-create-DqPMquaO.mjs +129 -0
  3. package/fesm2022/rolatech-angular-platform-application-create-DqPMquaO.mjs.map +1 -0
  4. package/fesm2022/rolatech-angular-platform-application-detail-BoITs_yE.mjs +54 -0
  5. package/fesm2022/rolatech-angular-platform-application-detail-BoITs_yE.mjs.map +1 -0
  6. package/fesm2022/rolatech-angular-platform-application-index-BlCbJVDc.mjs +82 -0
  7. package/fesm2022/rolatech-angular-platform-application-index-BlCbJVDc.mjs.map +1 -0
  8. package/fesm2022/rolatech-angular-platform-application-organization-index-D7TJ8CID.mjs +54 -0
  9. package/fesm2022/rolatech-angular-platform-application-organization-index-D7TJ8CID.mjs.map +1 -0
  10. package/fesm2022/rolatech-angular-platform-application-role-index-9_XVRBgD.mjs +66 -0
  11. package/fesm2022/rolatech-angular-platform-application-role-index-9_XVRBgD.mjs.map +1 -0
  12. package/fesm2022/rolatech-angular-platform-application-routes-DE5CJMgn.mjs +38 -0
  13. package/fesm2022/rolatech-angular-platform-application-routes-DE5CJMgn.mjs.map +1 -0
  14. package/fesm2022/rolatech-angular-platform-platform-auth-client-detail-BMvM7PvP.mjs +137 -0
  15. package/fesm2022/rolatech-angular-platform-platform-auth-client-detail-BMvM7PvP.mjs.map +1 -0
  16. package/fesm2022/rolatech-angular-platform-platform-auth-client-editor-75GPRUsF.mjs +281 -0
  17. package/fesm2022/rolatech-angular-platform-platform-auth-client-editor-75GPRUsF.mjs.map +1 -0
  18. package/fesm2022/rolatech-angular-platform-platform-auth-client-index-DilT3UzO.mjs +95 -0
  19. package/fesm2022/rolatech-angular-platform-platform-auth-client-index-DilT3UzO.mjs.map +1 -0
  20. package/fesm2022/rolatech-angular-platform-platform-auth-client.routes-D_VFpAgu.mjs +21 -0
  21. package/fesm2022/rolatech-angular-platform-platform-auth-client.routes-D_VFpAgu.mjs.map +1 -0
  22. package/fesm2022/rolatech-angular-platform-platform-endpoint-detail-CEaO9MFQ.mjs +57 -0
  23. package/fesm2022/rolatech-angular-platform-platform-endpoint-detail-CEaO9MFQ.mjs.map +1 -0
  24. package/fesm2022/rolatech-angular-platform-platform-endpoint-index-69W62bRP.mjs +92 -0
  25. package/fesm2022/rolatech-angular-platform-platform-endpoint-index-69W62bRP.mjs.map +1 -0
  26. package/fesm2022/rolatech-angular-platform-platform-endpoint.routes-Cj66S7N-.mjs +13 -0
  27. package/fesm2022/rolatech-angular-platform-platform-endpoint.routes-Cj66S7N-.mjs.map +1 -0
  28. package/fesm2022/rolatech-angular-platform-platform-role-index-8kRxDJiW.mjs +35 -0
  29. package/fesm2022/rolatech-angular-platform-platform-role-index-8kRxDJiW.mjs.map +1 -0
  30. package/fesm2022/rolatech-angular-platform-platform-service-registry-detail-CQ4Wk1R8.mjs +89 -0
  31. package/fesm2022/rolatech-angular-platform-platform-service-registry-detail-CQ4Wk1R8.mjs.map +1 -0
  32. package/fesm2022/rolatech-angular-platform-platform-service-registry-editor-Bd3nIfxd.mjs +246 -0
  33. package/fesm2022/rolatech-angular-platform-platform-service-registry-editor-Bd3nIfxd.mjs.map +1 -0
  34. package/fesm2022/rolatech-angular-platform-platform-service-registry-index-D4470pau.mjs +95 -0
  35. package/fesm2022/rolatech-angular-platform-platform-service-registry-index-D4470pau.mjs.map +1 -0
  36. package/fesm2022/rolatech-angular-platform-platform-service-registry.routes-DlWUwwws.mjs +21 -0
  37. package/fesm2022/rolatech-angular-platform-platform-service-registry.routes-DlWUwwws.mjs.map +1 -0
  38. package/fesm2022/rolatech-angular-platform-platform-user-detail-fzo89PHV.mjs +81 -0
  39. package/fesm2022/rolatech-angular-platform-platform-user-detail-fzo89PHV.mjs.map +1 -0
  40. package/fesm2022/rolatech-angular-platform-platform-user-index-DBT4N0zi.mjs +89 -0
  41. package/fesm2022/rolatech-angular-platform-platform-user-index-DBT4N0zi.mjs.map +1 -0
  42. package/fesm2022/rolatech-angular-platform-platform-user.routes-C6OoAsWU.mjs +13 -0
  43. package/fesm2022/rolatech-angular-platform-platform-user.routes-C6OoAsWU.mjs.map +1 -0
  44. package/fesm2022/rolatech-angular-platform-role-permission-page-DslhArZQ.mjs +527 -0
  45. package/fesm2022/rolatech-angular-platform-role-permission-page-DslhArZQ.mjs.map +1 -0
  46. package/fesm2022/rolatech-angular-platform-role-permission-page.routes-IiX17wDW.mjs +11 -0
  47. package/fesm2022/rolatech-angular-platform-role-permission-page.routes-IiX17wDW.mjs.map +1 -0
  48. package/fesm2022/rolatech-angular-platform.mjs +293 -0
  49. package/fesm2022/rolatech-angular-platform.mjs.map +1 -0
  50. package/package.json +33 -0
  51. package/types/rolatech-angular-platform.d.ts +70 -0
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # angular-platform
2
+
3
+ This library was generated with [Nx](https://nx.dev).
@@ -0,0 +1,129 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute, Router } from '@angular/router';
4
+ import { PlatformPageHeader, PlatformDetailPanel, PlatformStickyActionBar } from './rolatech-angular-platform.mjs';
5
+ import { firstValueFrom } from 'rxjs';
6
+ import { ApplicationService } from '@rolatech/angular-services';
7
+
8
+ class ApplicationCreateFacade {
9
+ applicationService = inject(ApplicationService);
10
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : []));
12
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
13
+ id = signal(null, ...(ngDevMode ? [{ debugName: "id" }] : []));
14
+ name = signal('', ...(ngDevMode ? [{ debugName: "name" }] : []));
15
+ code = signal('', ...(ngDevMode ? [{ debugName: "code" }] : []));
16
+ type = signal('', ...(ngDevMode ? [{ debugName: "type" }] : []));
17
+ description = signal('', ...(ngDevMode ? [{ debugName: "description" }] : []));
18
+ active = signal(true, ...(ngDevMode ? [{ debugName: "active" }] : []));
19
+ async load(id) {
20
+ this.loading.set(true);
21
+ this.error.set(null);
22
+ try {
23
+ const item = await firstValueFrom(this.applicationService.findApplicationById(id));
24
+ this.id.set(item.id);
25
+ this.name.set(item.name);
26
+ this.code.set(item.code);
27
+ this.type.set(item.type ?? '');
28
+ this.description.set(item.description ?? '');
29
+ this.active.set(item.active);
30
+ }
31
+ catch (error) {
32
+ console.error(error);
33
+ this.error.set('Unable to load the application.');
34
+ }
35
+ finally {
36
+ this.loading.set(false);
37
+ }
38
+ }
39
+ async save() {
40
+ this.saving.set(true);
41
+ this.error.set(null);
42
+ try {
43
+ const payload = {
44
+ name: this.name(),
45
+ code: this.code(),
46
+ type: this.type() || null,
47
+ description: this.description() || null,
48
+ active: this.active(),
49
+ };
50
+ if (this.id()) {
51
+ await firstValueFrom(this.applicationService.updateApplication(this.id(), payload));
52
+ }
53
+ else {
54
+ const created = await firstValueFrom(this.applicationService.createApplication(payload));
55
+ this.id.set(created.id);
56
+ }
57
+ }
58
+ catch (error) {
59
+ console.error(error);
60
+ this.error.set('Unable to save the application.');
61
+ }
62
+ finally {
63
+ this.saving.set(false);
64
+ }
65
+ }
66
+ setName(value) {
67
+ this.name.set(value);
68
+ }
69
+ setCode(value) {
70
+ this.code.set(value);
71
+ }
72
+ setType(value) {
73
+ this.type.set(value);
74
+ }
75
+ setDescription(value) {
76
+ this.description.set(value);
77
+ }
78
+ setActive(value) {
79
+ this.active.set(value);
80
+ }
81
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationCreateFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
82
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationCreateFacade });
83
+ }
84
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationCreateFacade, decorators: [{
85
+ type: Injectable
86
+ }] });
87
+
88
+ class ApplicationCreate {
89
+ facade = inject(ApplicationCreateFacade);
90
+ route = inject(ActivatedRoute);
91
+ router = inject(Router);
92
+ id = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id');
93
+ get isEdit() {
94
+ return !!this.id;
95
+ }
96
+ ngOnInit() {
97
+ if (this.id) {
98
+ void this.facade.load(this.id);
99
+ }
100
+ }
101
+ onNameInput(event) {
102
+ this.facade.setName(event.target.value);
103
+ }
104
+ onCodeInput(event) {
105
+ this.facade.setCode(event.target.value);
106
+ }
107
+ onTypeInput(event) {
108
+ this.facade.setType(event.target.value);
109
+ }
110
+ onDescriptionInput(event) {
111
+ this.facade.setDescription(event.target.value);
112
+ }
113
+ onActiveChange(event) {
114
+ this.facade.setActive(event.target.checked);
115
+ }
116
+ async save() {
117
+ await this.facade.save();
118
+ await this.router.navigate(['../'], { relativeTo: this.route });
119
+ }
120
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationCreate, deps: [], target: i0.ɵɵFactoryTarget.Component });
121
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ApplicationCreate, isStandalone: true, selector: "rolatech-application-create", providers: [ApplicationCreateFacade], ngImport: i0, template: "<section class=\"flex flex-col gap-6 p-6\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">@if (isEdit) { Edit Application } @else { Create Application }</h1>\n <p class=\"text-sm text-muted-foreground\">\n @if (isEdit) { Update application information. } @else { Create a new application for the platform. }\n </p>\n </div>\n </rolatech-platform-page-header>\n\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else {\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Set core application properties.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Name</span>\n <input\n type=\"text\"\n [value]=\"facade.name()\"\n (input)=\"onNameInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Code</span>\n <input\n type=\"text\"\n [value]=\"facade.code()\"\n (input)=\"onCodeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Type</span>\n <input\n type=\"text\"\n [value]=\"facade.type()\"\n (input)=\"onTypeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex items-center gap-2 pt-8\">\n <input type=\"checkbox\" [checked]=\"facade.active()\" (change)=\"onActiveChange($event)\" />\n <span class=\"text-sm font-medium\">Active</span>\n </label>\n\n <label class=\"md:col-span-2 flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Description</span>\n <textarea\n rows=\"5\"\n [value]=\"facade.description()\"\n (input)=\"onDescriptionInput($event)\"\n class=\"rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm outline-none\"\n ></textarea>\n </label>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-sticky-action-bar>\n <div action-message>@if (isEdit) { Update and save this application. } @else { Save this new application. }</div>\n\n <div action-buttons>\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium\"\n [disabled]=\"facade.saving()\"\n (click)=\"save()\"\n >\n @if (facade.saving()) { Saving... } @else { Save }\n </button>\n </div>\n </rolatech-platform-sticky-action-bar>\n }\n</section>\n", dependencies: [{ kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformDetailPanel, selector: "rolatech-platform-detail-panel" }, { kind: "component", type: PlatformStickyActionBar, selector: "rolatech-platform-sticky-action-bar" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
122
+ }
123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationCreate, decorators: [{
124
+ type: Component,
125
+ args: [{ selector: 'rolatech-application-create', standalone: true, imports: [PlatformPageHeader, PlatformDetailPanel, PlatformStickyActionBar], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ApplicationCreateFacade], template: "<section class=\"flex flex-col gap-6 p-6\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">@if (isEdit) { Edit Application } @else { Create Application }</h1>\n <p class=\"text-sm text-muted-foreground\">\n @if (isEdit) { Update application information. } @else { Create a new application for the platform. }\n </p>\n </div>\n </rolatech-platform-page-header>\n\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else {\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Set core application properties.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Name</span>\n <input\n type=\"text\"\n [value]=\"facade.name()\"\n (input)=\"onNameInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Code</span>\n <input\n type=\"text\"\n [value]=\"facade.code()\"\n (input)=\"onCodeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Type</span>\n <input\n type=\"text\"\n [value]=\"facade.type()\"\n (input)=\"onTypeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex items-center gap-2 pt-8\">\n <input type=\"checkbox\" [checked]=\"facade.active()\" (change)=\"onActiveChange($event)\" />\n <span class=\"text-sm font-medium\">Active</span>\n </label>\n\n <label class=\"md:col-span-2 flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Description</span>\n <textarea\n rows=\"5\"\n [value]=\"facade.description()\"\n (input)=\"onDescriptionInput($event)\"\n class=\"rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm outline-none\"\n ></textarea>\n </label>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-sticky-action-bar>\n <div action-message>@if (isEdit) { Update and save this application. } @else { Save this new application. }</div>\n\n <div action-buttons>\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium\"\n [disabled]=\"facade.saving()\"\n (click)=\"save()\"\n >\n @if (facade.saving()) { Saving... } @else { Save }\n </button>\n </div>\n </rolatech-platform-sticky-action-bar>\n }\n</section>\n" }]
126
+ }] });
127
+
128
+ export { ApplicationCreate };
129
+ //# sourceMappingURL=rolatech-angular-platform-application-create-DqPMquaO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolatech-angular-platform-application-create-DqPMquaO.mjs","sources":["../../../../packages/angular-platform/src/lib/store/application-create.facade.ts","../../../../packages/angular-platform/src/lib/pages/application/application-create/application-create.ts","../../../../packages/angular-platform/src/lib/pages/application/application-create/application-create.html"],"sourcesContent":["import { Injectable, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\nimport { ApplicationService } from '@rolatech/angular-services';\n\n@Injectable()\nexport class ApplicationCreateFacade {\n private readonly applicationService = inject(ApplicationService);\n\n readonly loading = signal(false);\n readonly saving = signal(false);\n readonly error = signal<string | null>(null);\n\n readonly id = signal<string | null>(null);\n\n readonly name = signal('');\n readonly code = signal('');\n readonly type = signal('');\n readonly description = signal('');\n readonly active = signal(true);\n\n async load(id: string): Promise<void> {\n this.loading.set(true);\n this.error.set(null);\n try {\n const item = await firstValueFrom(this.applicationService.findApplicationById(id));\n this.id.set(item.id);\n this.name.set(item.name);\n this.code.set(item.code);\n this.type.set(item.type ?? '');\n this.description.set(item.description ?? '');\n this.active.set(item.active);\n } catch (error) {\n console.error(error);\n this.error.set('Unable to load the application.');\n } finally {\n this.loading.set(false);\n }\n }\n\n async save(): Promise<void> {\n this.saving.set(true);\n this.error.set(null);\n try {\n const payload = {\n name: this.name(),\n code: this.code(),\n type: this.type() || null,\n description: this.description() || null,\n active: this.active(),\n };\n\n if (this.id()) {\n await firstValueFrom(this.applicationService.updateApplication(this.id()!, payload));\n } else {\n const created = await firstValueFrom(this.applicationService.createApplication(payload));\n this.id.set(created.id);\n }\n } catch (error) {\n console.error(error);\n this.error.set('Unable to save the application.');\n } finally {\n this.saving.set(false);\n }\n }\n\n setName(value: string): void {\n this.name.set(value);\n }\n\n setCode(value: string): void {\n this.code.set(value);\n }\n\n setType(value: string): void {\n this.type.set(value);\n }\n\n setDescription(value: string): void {\n this.description.set(value);\n }\n\n setActive(value: boolean): void {\n this.active.set(value);\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { PlatformPageHeader, PlatformDetailPanel, PlatformStickyActionBar } from '../../../shared';\nimport { ApplicationCreateFacade } from '../../../store/application-create.facade';\n\n@Component({\n selector: 'rolatech-application-create',\n standalone: true,\n imports: [PlatformPageHeader, PlatformDetailPanel, PlatformStickyActionBar],\n templateUrl: './application-create.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ApplicationCreateFacade],\n})\nexport class ApplicationCreate implements OnInit {\n readonly facade = inject(ApplicationCreateFacade);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n readonly id = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id');\n\n get isEdit(): boolean {\n return !!this.id;\n }\n\n ngOnInit(): void {\n if (this.id) {\n void this.facade.load(this.id);\n }\n }\n\n onNameInput(event: Event): void {\n this.facade.setName((event.target as HTMLInputElement).value);\n }\n\n onCodeInput(event: Event): void {\n this.facade.setCode((event.target as HTMLInputElement).value);\n }\n\n onTypeInput(event: Event): void {\n this.facade.setType((event.target as HTMLInputElement).value);\n }\n\n onDescriptionInput(event: Event): void {\n this.facade.setDescription((event.target as HTMLTextAreaElement).value);\n }\n\n onActiveChange(event: Event): void {\n this.facade.setActive((event.target as HTMLInputElement).checked);\n }\n\n async save(): Promise<void> {\n await this.facade.save();\n await this.router.navigate(['../'], { relativeTo: this.route });\n }\n}\n","<section class=\"flex flex-col gap-6 p-6\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">@if (isEdit) { Edit Application } @else { Create Application }</h1>\n <p class=\"text-sm text-muted-foreground\">\n @if (isEdit) { Update application information. } @else { Create a new application for the platform. }\n </p>\n </div>\n </rolatech-platform-page-header>\n\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else {\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Set core application properties.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Name</span>\n <input\n type=\"text\"\n [value]=\"facade.name()\"\n (input)=\"onNameInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Code</span>\n <input\n type=\"text\"\n [value]=\"facade.code()\"\n (input)=\"onCodeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Type</span>\n <input\n type=\"text\"\n [value]=\"facade.type()\"\n (input)=\"onTypeInput($event)\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex items-center gap-2 pt-8\">\n <input type=\"checkbox\" [checked]=\"facade.active()\" (change)=\"onActiveChange($event)\" />\n <span class=\"text-sm font-medium\">Active</span>\n </label>\n\n <label class=\"md:col-span-2 flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Description</span>\n <textarea\n rows=\"5\"\n [value]=\"facade.description()\"\n (input)=\"onDescriptionInput($event)\"\n class=\"rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm outline-none\"\n ></textarea>\n </label>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-sticky-action-bar>\n <div action-message>@if (isEdit) { Update and save this application. } @else { Save this new application. }</div>\n\n <div action-buttons>\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium\"\n [disabled]=\"facade.saving()\"\n (click)=\"save()\"\n >\n @if (facade.saving()) { Saving... } @else { Save }\n </button>\n </div>\n </rolatech-platform-sticky-action-bar>\n }\n</section>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute, RouterLink } from '@angular/router';
4
+ import { platformStatusLabel, PlatformPageHeader, PlatformDetailPanel, PlatformStatCard, PlatformTabs, PlatformStatusBadge } from './rolatech-angular-platform.mjs';
5
+ import { firstValueFrom } from 'rxjs';
6
+ import { ApplicationService } from '@rolatech/angular-services';
7
+
8
+ class ApplicationDetailFacade {
9
+ applicationService = inject(ApplicationService);
10
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11
+ item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
12
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
13
+ async load(id) {
14
+ this.loading.set(true);
15
+ this.error.set(null);
16
+ try {
17
+ this.item.set(await firstValueFrom(this.applicationService.findApplicationById(id)));
18
+ }
19
+ catch (error) {
20
+ console.error(error);
21
+ this.item.set(null);
22
+ this.error.set('Unable to load the application.');
23
+ }
24
+ finally {
25
+ this.loading.set(false);
26
+ }
27
+ }
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationDetailFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationDetailFacade });
30
+ }
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationDetailFacade, decorators: [{
32
+ type: Injectable
33
+ }] });
34
+
35
+ class ApplicationDetail {
36
+ facade = inject(ApplicationDetailFacade);
37
+ statusLabel = platformStatusLabel;
38
+ route = inject(ActivatedRoute);
39
+ id = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id') ?? '';
40
+ ngOnInit() {
41
+ if (this.id) {
42
+ void this.facade.load(this.id);
43
+ }
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationDetail, deps: [], target: i0.ɵɵFactoryTarget.Component });
46
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ApplicationDetail, isStandalone: true, selector: "rolatech-application-detail", providers: [ApplicationDetailFacade], ngImport: i0, template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else if (facade.item(); as item) {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-2\">\n <div class=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <a routerLink=\"../\" class=\"hover:underline cursor-pointer\">Applications</a>\n <span>/</span>\n <span>{{ item.name }}</span>\n </div>\n\n <div>\n <h1 class=\"text-2xl font-semibold tracking-tight\">{{ item.name }}</h1>\n <div class=\"mt-1 text-sm text-muted-foreground\">{{ item.code }}</div>\n </div>\n\n @if (item.description) {\n <p class=\"max-w-3xl text-sm text-muted-foreground\">{{ item.description }}</p>\n }\n\n <div class=\"flex flex-wrap gap-2\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n @if (item.type) {\n <span class=\"inline-flex rounded-full border border-(--rt-border-color) px-2 py-1 text-xs\"> {{ item.type }} </span>\n }\n </div>\n </div>\n\n <div header-actions>\n <a routerLink=\"./edit\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Edit Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Organizations</div>\n <div stat-value>{{ item.organizationCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Roles</div>\n <div stat-value>{{ item.roleCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Members</div>\n <div stat-value>{{ item.memberCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Updated</div>\n <div stat-value class=\"text-sm\">{{ item.updatedAt || '-' }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card shadow-sm\">\n <rolatech-platform-tabs>\n <a routerLink=\"./\" class=\"rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\"> Overview </a>\n\n <a routerLink=\"./organizations\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Organizations </a>\n\n <a routerLink=\"./roles\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Roles </a>\n\n <a routerLink=\"./settings\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Settings </a>\n </rolatech-platform-tabs>\n\n <div class=\"grid gap-6 p-4 xl:grid-cols-2\">\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Core application details.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Name</div>\n <div class=\"font-medium\">{{ item.name }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Code</div>\n <div class=\"font-medium\">{{ item.code }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Type</div>\n <div class=\"font-medium\">{{ item.type || '-' }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Status</div>\n <div class=\"font-medium\">{{ statusLabel(item.status) }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-detail-panel>\n <div panel-title>Structure Summary</div>\n <div panel-description>Top-level related resources under this application.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Organizations</div>\n <div class=\"font-medium\">{{ item.organizationCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Roles</div>\n <div class=\"font-medium\">{{ item.roleCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Members</div>\n <div class=\"font-medium\">{{ item.memberCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Created At</div>\n <div class=\"font-medium\">{{ item.createdAt || '-' }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n </div>\n </section>\n }\n</section>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformDetailPanel, selector: "rolatech-platform-detail-panel" }, { kind: "component", type: PlatformStatCard, selector: "rolatech-platform-stat-card" }, { kind: "component", type: PlatformTabs, selector: "rolatech-platform-tabs" }, { kind: "component", type: PlatformStatusBadge, selector: "rolatech-platform-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationDetail, decorators: [{
49
+ type: Component,
50
+ args: [{ selector: 'rolatech-application-detail', standalone: true, imports: [RouterLink, PlatformPageHeader, PlatformDetailPanel, PlatformStatCard, PlatformTabs, PlatformStatusBadge], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ApplicationDetailFacade], template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else if (facade.item(); as item) {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-2\">\n <div class=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <a routerLink=\"../\" class=\"hover:underline cursor-pointer\">Applications</a>\n <span>/</span>\n <span>{{ item.name }}</span>\n </div>\n\n <div>\n <h1 class=\"text-2xl font-semibold tracking-tight\">{{ item.name }}</h1>\n <div class=\"mt-1 text-sm text-muted-foreground\">{{ item.code }}</div>\n </div>\n\n @if (item.description) {\n <p class=\"max-w-3xl text-sm text-muted-foreground\">{{ item.description }}</p>\n }\n\n <div class=\"flex flex-wrap gap-2\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n @if (item.type) {\n <span class=\"inline-flex rounded-full border border-(--rt-border-color) px-2 py-1 text-xs\"> {{ item.type }} </span>\n }\n </div>\n </div>\n\n <div header-actions>\n <a routerLink=\"./edit\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Edit Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Organizations</div>\n <div stat-value>{{ item.organizationCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Roles</div>\n <div stat-value>{{ item.roleCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Members</div>\n <div stat-value>{{ item.memberCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Updated</div>\n <div stat-value class=\"text-sm\">{{ item.updatedAt || '-' }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card shadow-sm\">\n <rolatech-platform-tabs>\n <a routerLink=\"./\" class=\"rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\"> Overview </a>\n\n <a routerLink=\"./organizations\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Organizations </a>\n\n <a routerLink=\"./roles\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Roles </a>\n\n <a routerLink=\"./settings\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Settings </a>\n </rolatech-platform-tabs>\n\n <div class=\"grid gap-6 p-4 xl:grid-cols-2\">\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Core application details.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Name</div>\n <div class=\"font-medium\">{{ item.name }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Code</div>\n <div class=\"font-medium\">{{ item.code }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Type</div>\n <div class=\"font-medium\">{{ item.type || '-' }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Status</div>\n <div class=\"font-medium\">{{ statusLabel(item.status) }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-detail-panel>\n <div panel-title>Structure Summary</div>\n <div panel-description>Top-level related resources under this application.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Organizations</div>\n <div class=\"font-medium\">{{ item.organizationCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Roles</div>\n <div class=\"font-medium\">{{ item.roleCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Members</div>\n <div class=\"font-medium\">{{ item.memberCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Created At</div>\n <div class=\"font-medium\">{{ item.createdAt || '-' }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n </div>\n </section>\n }\n</section>\n" }]
51
+ }] });
52
+
53
+ export { ApplicationDetail };
54
+ //# sourceMappingURL=rolatech-angular-platform-application-detail-BoITs_yE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolatech-angular-platform-application-detail-BoITs_yE.mjs","sources":["../../../../packages/angular-platform/src/lib/store/application-detail.facade.ts","../../../../packages/angular-platform/src/lib/pages/application/application-detail/application-detail.ts","../../../../packages/angular-platform/src/lib/pages/application/application-detail/application-detail.html"],"sourcesContent":["import { Injectable, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\nimport { ApplicationService } from '@rolatech/angular-services';\nimport { ApplicationDetailModel } from '../model/application.models';\n\n@Injectable()\nexport class ApplicationDetailFacade {\n private readonly applicationService = inject(ApplicationService);\n\n readonly loading = signal(false);\n readonly item = signal<ApplicationDetailModel | null>(null);\n readonly error = signal<string | null>(null);\n\n async load(id: string): Promise<void> {\n this.loading.set(true);\n this.error.set(null);\n try {\n this.item.set(await firstValueFrom(this.applicationService.findApplicationById(id)));\n } catch (error) {\n console.error(error);\n this.item.set(null);\n this.error.set('Unable to load the application.');\n } finally {\n this.loading.set(false);\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';\nimport { ActivatedRoute, RouterLink } from '@angular/router';\nimport { PlatformPageHeader, PlatformDetailPanel, PlatformStatCard, PlatformTabs, PlatformStatusBadge } from '../../../shared';\nimport { ApplicationDetailFacade } from '../../../store/application-detail.facade';\nimport { platformStatusLabel } from '../../../ui/platform-label';\n\n@Component({\n selector: 'rolatech-application-detail',\n standalone: true,\n imports: [RouterLink, PlatformPageHeader, PlatformDetailPanel, PlatformStatCard, PlatformTabs, PlatformStatusBadge],\n templateUrl: './application-detail.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ApplicationDetailFacade],\n})\nexport class ApplicationDetail implements OnInit {\n readonly facade = inject(ApplicationDetailFacade);\n readonly statusLabel = platformStatusLabel;\n private readonly route = inject(ActivatedRoute);\n\n readonly id = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id') ?? '';\n\n ngOnInit(): void {\n if (this.id) {\n void this.facade.load(this.id);\n }\n }\n}\n","<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading application...</section>\n } @else if (facade.item(); as item) {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-2\">\n <div class=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <a routerLink=\"../\" class=\"hover:underline cursor-pointer\">Applications</a>\n <span>/</span>\n <span>{{ item.name }}</span>\n </div>\n\n <div>\n <h1 class=\"text-2xl font-semibold tracking-tight\">{{ item.name }}</h1>\n <div class=\"mt-1 text-sm text-muted-foreground\">{{ item.code }}</div>\n </div>\n\n @if (item.description) {\n <p class=\"max-w-3xl text-sm text-muted-foreground\">{{ item.description }}</p>\n }\n\n <div class=\"flex flex-wrap gap-2\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n @if (item.type) {\n <span class=\"inline-flex rounded-full border border-(--rt-border-color) px-2 py-1 text-xs\"> {{ item.type }} </span>\n }\n </div>\n </div>\n\n <div header-actions>\n <a routerLink=\"./edit\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Edit Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Organizations</div>\n <div stat-value>{{ item.organizationCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Roles</div>\n <div stat-value>{{ item.roleCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Members</div>\n <div stat-value>{{ item.memberCount }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Updated</div>\n <div stat-value class=\"text-sm\">{{ item.updatedAt || '-' }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card shadow-sm\">\n <rolatech-platform-tabs>\n <a routerLink=\"./\" class=\"rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\"> Overview </a>\n\n <a routerLink=\"./organizations\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Organizations </a>\n\n <a routerLink=\"./roles\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Roles </a>\n\n <a routerLink=\"./settings\" class=\"rounded-xl px-4 py-2 text-sm font-medium cursor-pointer\"> Settings </a>\n </rolatech-platform-tabs>\n\n <div class=\"grid gap-6 p-4 xl:grid-cols-2\">\n <rolatech-platform-detail-panel>\n <div panel-title>Basic Information</div>\n <div panel-description>Core application details.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Name</div>\n <div class=\"font-medium\">{{ item.name }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Code</div>\n <div class=\"font-medium\">{{ item.code }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Type</div>\n <div class=\"font-medium\">{{ item.type || '-' }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Status</div>\n <div class=\"font-medium\">{{ statusLabel(item.status) }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n\n <rolatech-platform-detail-panel>\n <div panel-title>Structure Summary</div>\n <div panel-description>Top-level related resources under this application.</div>\n\n <div class=\"grid gap-4 md:grid-cols-2\">\n <div>\n <div class=\"text-xs text-muted-foreground\">Organizations</div>\n <div class=\"font-medium\">{{ item.organizationCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Roles</div>\n <div class=\"font-medium\">{{ item.roleCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Members</div>\n <div class=\"font-medium\">{{ item.memberCount }}</div>\n </div>\n\n <div>\n <div class=\"text-xs text-muted-foreground\">Created At</div>\n <div class=\"font-medium\">{{ item.createdAt || '-' }}</div>\n </div>\n </div>\n </rolatech-platform-detail-panel>\n </div>\n </section>\n }\n</section>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
4
+ import { firstValueFrom } from 'rxjs';
5
+ import { ApplicationService } from '@rolatech/angular-services';
6
+ import { PlatformPageHeader, PlatformStatCard, PlatformFilterPanel, PlatformDataTable, PlatformStatusBadge } from './rolatech-angular-platform.mjs';
7
+
8
+ class ApplicationIndexFacade {
9
+ applicationService = inject(ApplicationService);
10
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
12
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
13
+ keyword = signal('', ...(ngDevMode ? [{ debugName: "keyword" }] : []));
14
+ status = signal('ALL', ...(ngDevMode ? [{ debugName: "status" }] : []));
15
+ filteredItems = computed(() => {
16
+ const keyword = this.keyword().trim().toLowerCase();
17
+ const status = this.status();
18
+ return this.items().filter((item) => {
19
+ const matchesKeyword = !keyword || item.name.toLowerCase().includes(keyword) || item.code.toLowerCase().includes(keyword);
20
+ const matchesStatus = status === 'ALL' || item.status === status;
21
+ return matchesKeyword && matchesStatus;
22
+ });
23
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
24
+ total = computed(() => this.items().length, ...(ngDevMode ? [{ debugName: "total" }] : []));
25
+ activeCount = computed(() => this.items().filter((x) => x.active).length, ...(ngDevMode ? [{ debugName: "activeCount" }] : []));
26
+ totalOrganizations = computed(() => this.items().reduce((sum, item) => sum + item.organizationCount, 0), ...(ngDevMode ? [{ debugName: "totalOrganizations" }] : []));
27
+ totalRoles = computed(() => this.items().reduce((sum, item) => sum + item.roleCount, 0), ...(ngDevMode ? [{ debugName: "totalRoles" }] : []));
28
+ async load() {
29
+ this.loading.set(true);
30
+ this.error.set(null);
31
+ try {
32
+ const page = await firstValueFrom(this.applicationService.findApplications());
33
+ this.items.set(page.items ?? []);
34
+ }
35
+ catch (error) {
36
+ console.error(error);
37
+ this.items.set([]);
38
+ this.error.set('Unable to load applications.');
39
+ }
40
+ finally {
41
+ this.loading.set(false);
42
+ }
43
+ }
44
+ setKeyword(value) {
45
+ this.keyword.set(value);
46
+ }
47
+ setStatus(value) {
48
+ this.status.set(value);
49
+ }
50
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationIndexFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
51
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationIndexFacade });
52
+ }
53
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationIndexFacade, decorators: [{
54
+ type: Injectable
55
+ }] });
56
+
57
+ class ApplicationIndex {
58
+ facade = inject(ApplicationIndexFacade);
59
+ route = inject(ActivatedRoute);
60
+ router = inject(Router);
61
+ ngOnInit() {
62
+ void this.facade.load();
63
+ }
64
+ onKeywordInput(event) {
65
+ this.facade.setKeyword(event.target.value);
66
+ }
67
+ onStatusChange(event) {
68
+ this.facade.setStatus(event.target.value);
69
+ }
70
+ openDetail(id) {
71
+ void this.router.navigate([id], { relativeTo: this.route });
72
+ }
73
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
74
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ApplicationIndex, isStandalone: true, selector: "rolatech-application-index", providers: [ApplicationIndexFacade], ngImport: i0, template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Applications</h1>\n <p class=\"text-sm text-muted-foreground\">Manage platform applications and their structure.</p>\n </div>\n\n <div header-actions>\n <a routerLink=\"./new\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Create Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Total Applications</div>\n <div stat-value>{{ facade.total() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Active Applications</div>\n <div stat-value>{{ facade.activeCount() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Organizations</div>\n <div stat-value>{{ facade.totalOrganizations() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Roles</div>\n <div stat-value>{{ facade.totalRoles() }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"grid gap-6 xl:grid-cols-[320px_minmax(0,1fr)]\">\n <rolatech-platform-filter-panel>\n <div filter-title>Filters</div>\n <div filter-description>Refine visible applications.</div>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Search</span>\n <input\n type=\"text\"\n [value]=\"facade.keyword()\"\n (input)=\"onKeywordInput($event)\"\n placeholder=\"Search application name or code\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Status</span>\n <select class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\" (change)=\"onStatusChange($event)\">\n <option value=\"ALL\">All</option>\n <option value=\"ACTIVE\">Active</option>\n <option value=\"INACTIVE\">Inactive</option>\n <option value=\"DRAFT\">Draft</option>\n </select>\n </label>\n </rolatech-platform-filter-panel>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Application List</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.filteredItems().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Type</th>\n <th class=\"px-4 py-3 font-medium\">Organizations</th>\n <th class=\"px-4 py-3 font-medium\">Roles</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Actions</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.loading()) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">Loading applications...</td>\n </tr>\n } @else if (facade.filteredItems().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">No applications matched your filters.</td>\n </tr>\n } @else { @for (item of facade.filteredItems(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">{{ item.type || '-' }}</td>\n <td class=\"px-4 py-3\">{{ item.organizationCount }}</td>\n <td class=\"px-4 py-3\">{{ item.roleCount }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium\"\n (click)=\"openDetail(item.id)\"\n >\n View\n </button>\n </td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n </section>\n</section>\n", dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformStatCard, selector: "rolatech-platform-stat-card" }, { kind: "component", type: PlatformFilterPanel, selector: "rolatech-platform-filter-panel" }, { kind: "component", type: PlatformDataTable, selector: "rolatech-platform-data-table" }, { kind: "component", type: PlatformStatusBadge, selector: "rolatech-platform-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
75
+ }
76
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationIndex, decorators: [{
77
+ type: Component,
78
+ args: [{ selector: 'rolatech-application-index', standalone: true, imports: [RouterLink, PlatformPageHeader, PlatformStatCard, PlatformFilterPanel, PlatformDataTable, PlatformStatusBadge], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ApplicationIndexFacade], template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Applications</h1>\n <p class=\"text-sm text-muted-foreground\">Manage platform applications and their structure.</p>\n </div>\n\n <div header-actions>\n <a routerLink=\"./new\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Create Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Total Applications</div>\n <div stat-value>{{ facade.total() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Active Applications</div>\n <div stat-value>{{ facade.activeCount() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Organizations</div>\n <div stat-value>{{ facade.totalOrganizations() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Roles</div>\n <div stat-value>{{ facade.totalRoles() }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"grid gap-6 xl:grid-cols-[320px_minmax(0,1fr)]\">\n <rolatech-platform-filter-panel>\n <div filter-title>Filters</div>\n <div filter-description>Refine visible applications.</div>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Search</span>\n <input\n type=\"text\"\n [value]=\"facade.keyword()\"\n (input)=\"onKeywordInput($event)\"\n placeholder=\"Search application name or code\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Status</span>\n <select class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\" (change)=\"onStatusChange($event)\">\n <option value=\"ALL\">All</option>\n <option value=\"ACTIVE\">Active</option>\n <option value=\"INACTIVE\">Inactive</option>\n <option value=\"DRAFT\">Draft</option>\n </select>\n </label>\n </rolatech-platform-filter-panel>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Application List</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.filteredItems().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Type</th>\n <th class=\"px-4 py-3 font-medium\">Organizations</th>\n <th class=\"px-4 py-3 font-medium\">Roles</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Actions</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.loading()) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">Loading applications...</td>\n </tr>\n } @else if (facade.filteredItems().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">No applications matched your filters.</td>\n </tr>\n } @else { @for (item of facade.filteredItems(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">{{ item.type || '-' }}</td>\n <td class=\"px-4 py-3\">{{ item.organizationCount }}</td>\n <td class=\"px-4 py-3\">{{ item.roleCount }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium\"\n (click)=\"openDetail(item.id)\"\n >\n View\n </button>\n </td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n </section>\n</section>\n" }]
79
+ }] });
80
+
81
+ export { ApplicationIndex };
82
+ //# sourceMappingURL=rolatech-angular-platform-application-index-BlCbJVDc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolatech-angular-platform-application-index-BlCbJVDc.mjs","sources":["../../../../packages/angular-platform/src/lib/store/application-index.facade.ts","../../../../packages/angular-platform/src/lib/pages/application/application-index/application-index.ts","../../../../packages/angular-platform/src/lib/pages/application/application-index/application-index.html"],"sourcesContent":["import { Injectable, computed, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\nimport { ApplicationService } from '@rolatech/angular-services';\nimport { ApplicationSummary } from '../model/application.models';\n\n@Injectable()\nexport class ApplicationIndexFacade {\n private readonly applicationService = inject(ApplicationService);\n\n readonly loading = signal(false);\n readonly items = signal<ApplicationSummary[]>([]);\n readonly error = signal<string | null>(null);\n\n readonly keyword = signal('');\n readonly status = signal<'ALL' | 'ACTIVE' | 'INACTIVE' | 'DRAFT'>('ALL');\n\n readonly filteredItems = computed(() => {\n const keyword = this.keyword().trim().toLowerCase();\n const status = this.status();\n\n return this.items().filter((item) => {\n const matchesKeyword = !keyword || item.name.toLowerCase().includes(keyword) || item.code.toLowerCase().includes(keyword);\n\n const matchesStatus = status === 'ALL' || item.status === status;\n\n return matchesKeyword && matchesStatus;\n });\n });\n\n readonly total = computed(() => this.items().length);\n readonly activeCount = computed(() => this.items().filter((x) => x.active).length);\n readonly totalOrganizations = computed(() => this.items().reduce((sum, item) => sum + item.organizationCount, 0));\n readonly totalRoles = computed(() => this.items().reduce((sum, item) => sum + item.roleCount, 0));\n\n async load(): Promise<void> {\n this.loading.set(true);\n this.error.set(null);\n try {\n const page = await firstValueFrom(this.applicationService.findApplications());\n this.items.set(page.items ?? []);\n } catch (error) {\n console.error(error);\n this.items.set([]);\n this.error.set('Unable to load applications.');\n } finally {\n this.loading.set(false);\n }\n }\n\n setKeyword(value: string): void {\n this.keyword.set(value);\n }\n\n setStatus(value: 'ALL' | 'ACTIVE' | 'INACTIVE' | 'DRAFT'): void {\n this.status.set(value);\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport { ApplicationIndexFacade } from '../../../store/application-index.facade';\nimport {\n PlatformPageHeader,\n PlatformStatCard,\n PlatformFilterPanel,\n PlatformDataTable,\n PlatformStatusBadge,\n} from '../../../shared';\n\n@Component({\n selector: 'rolatech-application-index',\n standalone: true,\n imports: [RouterLink, PlatformPageHeader, PlatformStatCard, PlatformFilterPanel, PlatformDataTable, PlatformStatusBadge],\n templateUrl: './application-index.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ApplicationIndexFacade],\n})\nexport class ApplicationIndex implements OnInit {\n readonly facade = inject(ApplicationIndexFacade);\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n\n ngOnInit(): void {\n void this.facade.load();\n }\n\n onKeywordInput(event: Event): void {\n this.facade.setKeyword((event.target as HTMLInputElement).value);\n }\n\n onStatusChange(event: Event): void {\n this.facade.setStatus((event.target as HTMLSelectElement).value as 'ALL' | 'ACTIVE' | 'INACTIVE' | 'DRAFT');\n }\n\n openDetail(id: string): void {\n void this.router.navigate([id], { relativeTo: this.route });\n }\n}\n","<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Applications</h1>\n <p class=\"text-sm text-muted-foreground\">Manage platform applications and their structure.</p>\n </div>\n\n <div header-actions>\n <a routerLink=\"./new\" class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-4 py-2 text-sm font-medium cursor-pointer\">\n Create Application\n </a>\n </div>\n </rolatech-platform-page-header>\n\n <section class=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <rolatech-platform-stat-card>\n <div stat-label>Total Applications</div>\n <div stat-value>{{ facade.total() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Active Applications</div>\n <div stat-value>{{ facade.activeCount() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Organizations</div>\n <div stat-value>{{ facade.totalOrganizations() }}</div>\n </rolatech-platform-stat-card>\n\n <rolatech-platform-stat-card>\n <div stat-label>Total Roles</div>\n <div stat-value>{{ facade.totalRoles() }}</div>\n </rolatech-platform-stat-card>\n </section>\n\n <section class=\"grid gap-6 xl:grid-cols-[320px_minmax(0,1fr)]\">\n <rolatech-platform-filter-panel>\n <div filter-title>Filters</div>\n <div filter-description>Refine visible applications.</div>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Search</span>\n <input\n type=\"text\"\n [value]=\"facade.keyword()\"\n (input)=\"onKeywordInput($event)\"\n placeholder=\"Search application name or code\"\n class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\"\n />\n </label>\n\n <label class=\"flex flex-col gap-2\">\n <span class=\"text-sm font-medium\">Status</span>\n <select class=\"h-10 rounded-xl border border-(--rt-border-color) px-3 text-sm outline-none\" (change)=\"onStatusChange($event)\">\n <option value=\"ALL\">All</option>\n <option value=\"ACTIVE\">Active</option>\n <option value=\"INACTIVE\">Inactive</option>\n <option value=\"DRAFT\">Draft</option>\n </select>\n </label>\n </rolatech-platform-filter-panel>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Application List</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.filteredItems().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Type</th>\n <th class=\"px-4 py-3 font-medium\">Organizations</th>\n <th class=\"px-4 py-3 font-medium\">Roles</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Actions</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.loading()) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">Loading applications...</td>\n </tr>\n } @else if (facade.filteredItems().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">No applications matched your filters.</td>\n </tr>\n } @else { @for (item of facade.filteredItems(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">{{ item.type || '-' }}</td>\n <td class=\"px-4 py-3\">{{ item.organizationCount }}</td>\n <td class=\"px-4 py-3\">{{ item.roleCount }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium\"\n (click)=\"openDetail(item.id)\"\n >\n View\n </button>\n </td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n </section>\n</section>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute } from '@angular/router';
4
+ import { PlatformPageHeader, PlatformDataTable, PlatformStatusBadge } from './rolatech-angular-platform.mjs';
5
+ import { firstValueFrom } from 'rxjs';
6
+ import { ApplicationService } from '@rolatech/angular-services';
7
+
8
+ class ApplicationOrganizationIndexFacade {
9
+ applicationService = inject(ApplicationService);
10
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
12
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
13
+ async load(applicationId) {
14
+ this.loading.set(true);
15
+ this.error.set(null);
16
+ try {
17
+ const page = await firstValueFrom(this.applicationService.findApplicationOrganizations(applicationId));
18
+ this.items.set(page.items ?? []);
19
+ }
20
+ catch (error) {
21
+ console.error(error);
22
+ this.items.set([]);
23
+ this.error.set('Unable to load application organizations.');
24
+ }
25
+ finally {
26
+ this.loading.set(false);
27
+ }
28
+ }
29
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationOrganizationIndexFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
30
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationOrganizationIndexFacade });
31
+ }
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationOrganizationIndexFacade, decorators: [{
33
+ type: Injectable
34
+ }] });
35
+
36
+ class ApplicationOrganizationIndex {
37
+ facade = inject(ApplicationOrganizationIndexFacade);
38
+ route = inject(ActivatedRoute);
39
+ applicationId = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id') ?? '';
40
+ ngOnInit() {
41
+ if (this.applicationId) {
42
+ void this.facade.load(this.applicationId);
43
+ }
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationOrganizationIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
46
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ApplicationOrganizationIndex, isStandalone: true, selector: "rolatech-application-organization-index", providers: [ApplicationOrganizationIndexFacade], ngImport: i0, template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">\n Loading organizations...\n </section>\n } @else {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Application Organizations</h1>\n <p class=\"text-sm text-muted-foreground\">Organizations that belong to this application.</p>\n </div>\n </rolatech-platform-page-header>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Organizations</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.items().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Members</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.items().length === 0) {\n <tr>\n <td colspan=\"4\" class=\"px-4 py-10 text-center text-muted-foreground\">No organizations found.</td>\n </tr>\n } @else { @for (item of facade.items(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">{{ item.memberCount }}</td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n }\n</section>\n", dependencies: [{ kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformDataTable, selector: "rolatech-platform-data-table" }, { kind: "component", type: PlatformStatusBadge, selector: "rolatech-platform-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationOrganizationIndex, decorators: [{
49
+ type: Component,
50
+ args: [{ selector: 'rolatech-application-organization-index', standalone: true, imports: [PlatformPageHeader, PlatformDataTable, PlatformStatusBadge], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ApplicationOrganizationIndexFacade], template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">\n Loading organizations...\n </section>\n } @else {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Application Organizations</h1>\n <p class=\"text-sm text-muted-foreground\">Organizations that belong to this application.</p>\n </div>\n </rolatech-platform-page-header>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Organizations</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.items().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Members</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.items().length === 0) {\n <tr>\n <td colspan=\"4\" class=\"px-4 py-10 text-center text-muted-foreground\">No organizations found.</td>\n </tr>\n } @else { @for (item of facade.items(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">{{ item.memberCount }}</td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n }\n</section>\n" }]
51
+ }] });
52
+
53
+ export { ApplicationOrganizationIndex };
54
+ //# sourceMappingURL=rolatech-angular-platform-application-organization-index-D7TJ8CID.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolatech-angular-platform-application-organization-index-D7TJ8CID.mjs","sources":["../../../../packages/angular-platform/src/lib/store/application-organization-index.facade.ts","../../../../packages/angular-platform/src/lib/pages/application/application-organization-index/application-organization-index.ts","../../../../packages/angular-platform/src/lib/pages/application/application-organization-index/application-organization-index.html"],"sourcesContent":["import { Injectable, inject, signal } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\nimport { ApplicationOrganizationResponse, ApplicationService } from '@rolatech/angular-services';\n\nexport type ApplicationOrganizationItem = ApplicationOrganizationResponse;\n\n@Injectable()\nexport class ApplicationOrganizationIndexFacade {\n private readonly applicationService = inject(ApplicationService);\n\n readonly loading = signal(false);\n readonly items = signal<ApplicationOrganizationItem[]>([]);\n readonly error = signal<string | null>(null);\n\n async load(applicationId: string): Promise<void> {\n this.loading.set(true);\n this.error.set(null);\n try {\n const page = await firstValueFrom(this.applicationService.findApplicationOrganizations(applicationId));\n this.items.set(page.items ?? []);\n } catch (error) {\n console.error(error);\n this.items.set([]);\n this.error.set('Unable to load application organizations.');\n } finally {\n this.loading.set(false);\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { PlatformPageHeader, PlatformDataTable, PlatformStatusBadge } from '../../../shared';\nimport { ApplicationOrganizationIndexFacade } from '../../../store/application-organization-index.facade';\n\n@Component({\n selector: 'rolatech-application-organization-index',\n standalone: true,\n imports: [PlatformPageHeader, PlatformDataTable, PlatformStatusBadge],\n templateUrl: './application-organization-index.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [ApplicationOrganizationIndexFacade],\n})\nexport class ApplicationOrganizationIndex implements OnInit {\n readonly facade = inject(ApplicationOrganizationIndexFacade);\n private readonly route = inject(ActivatedRoute);\n\n readonly applicationId = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id') ?? '';\n\n ngOnInit(): void {\n if (this.applicationId) {\n void this.facade.load(this.applicationId);\n }\n }\n}\n","<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">\n Loading organizations...\n </section>\n } @else {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Application Organizations</h1>\n <p class=\"text-sm text-muted-foreground\">Organizations that belong to this application.</p>\n </div>\n </rolatech-platform-page-header>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Organizations</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.items().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Members</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.items().length === 0) {\n <tr>\n <td colspan=\"4\" class=\"px-4 py-10 text-center text-muted-foreground\">No organizations found.</td>\n </tr>\n } @else { @for (item of facade.items(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">{{ item.memberCount }}</td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n }\n</section>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { ActivatedRoute, Router } from '@angular/router';
4
+ import { PlatformPageHeader, PlatformDataTable, PlatformScopeBadge, PlatformStatusBadge } from './rolatech-angular-platform.mjs';
5
+ import { firstValueFrom } from 'rxjs';
6
+ import { RoleService } from '@rolatech/angular-services';
7
+
8
+ class ApplicationRoleIndexFacade {
9
+ roleService = inject(RoleService);
10
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
11
+ items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : []));
12
+ async load(applicationId) {
13
+ if (!applicationId) {
14
+ this.items.set([]);
15
+ return;
16
+ }
17
+ this.loading.set(true);
18
+ try {
19
+ const roles = await firstValueFrom(this.roleService.findApplicationRoles(applicationId));
20
+ this.items.set((roles ?? []).map((role) => this.toRoleItem(role)));
21
+ }
22
+ finally {
23
+ this.loading.set(false);
24
+ }
25
+ }
26
+ toRoleItem(role) {
27
+ return {
28
+ id: role.id,
29
+ name: role.name,
30
+ code: role.code,
31
+ scope: role.scope === 'ORG' ? 'ORG' : 'APP',
32
+ permissionCount: role.permissionIds.length,
33
+ memberCount: 0,
34
+ status: role.enabled ? 'ACTIVE' : 'INACTIVE',
35
+ };
36
+ }
37
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationRoleIndexFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
38
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationRoleIndexFacade });
39
+ }
40
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationRoleIndexFacade, decorators: [{
41
+ type: Injectable
42
+ }] });
43
+
44
+ class ApplicationRoleIndex {
45
+ facade = inject(ApplicationRoleIndexFacade);
46
+ route = inject(ActivatedRoute);
47
+ router = inject(Router);
48
+ applicationId = this.route.snapshot.paramMap.get('appId') ?? this.route.snapshot.paramMap.get('id') ?? '';
49
+ ngOnInit() {
50
+ if (this.applicationId) {
51
+ void this.facade.load(this.applicationId);
52
+ }
53
+ }
54
+ openRole(id) {
55
+ void this.router.navigate([id, 'permissions'], { relativeTo: this.route });
56
+ }
57
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationRoleIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
58
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ApplicationRoleIndex, isStandalone: true, selector: "rolatech-application-role-index", providers: [ApplicationRoleIndexFacade], ngImport: i0, template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading roles...</section>\n } @else {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Application Roles</h1>\n <p class=\"text-sm text-muted-foreground\">Roles defined within this application.</p>\n </div>\n </rolatech-platform-page-header>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Roles</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.items().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Scope</th>\n <th class=\"px-4 py-3 font-medium\">Permissions</th>\n <th class=\"px-4 py-3 font-medium\">Members</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Actions</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.items().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">No roles found.</td>\n </tr>\n } @else { @for (item of facade.items(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-scope-badge [scope]=\"item.scope\" />\n </td>\n <td class=\"px-4 py-3\">{{ item.permissionCount }}</td>\n <td class=\"px-4 py-3\">{{ item.memberCount }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium\"\n (click)=\"openRole(item.id)\"\n >\n View Role\n </button>\n </td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n }\n</section>\n", dependencies: [{ kind: "component", type: PlatformPageHeader, selector: "rolatech-platform-page-header" }, { kind: "component", type: PlatformDataTable, selector: "rolatech-platform-data-table" }, { kind: "component", type: PlatformScopeBadge, selector: "rolatech-platform-scope-badge", inputs: ["scope"] }, { kind: "component", type: PlatformStatusBadge, selector: "rolatech-platform-status-badge", inputs: ["status"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
59
+ }
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ApplicationRoleIndex, decorators: [{
61
+ type: Component,
62
+ args: [{ selector: 'rolatech-application-role-index', standalone: true, imports: [PlatformPageHeader, PlatformDataTable, PlatformScopeBadge, PlatformStatusBadge], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ApplicationRoleIndexFacade], template: "<section class=\"rt-platform-theme flex flex-col gap-6 bg-(--rt-base-background) p-6 text-(--rt-text-primary)\">\n @if (facade.loading()) {\n <section class=\"rounded-2xl border border-(--rt-border-color) bg-card p-10 text-center text-muted-foreground shadow-sm\">Loading roles...</section>\n } @else {\n <rolatech-platform-page-header>\n <div header-left class=\"space-y-1\">\n <h1 class=\"text-2xl font-semibold tracking-tight\">Application Roles</h1>\n <p class=\"text-sm text-muted-foreground\">Roles defined within this application.</p>\n </div>\n </rolatech-platform-page-header>\n\n <rolatech-platform-data-table>\n <div table-toolbar class=\"flex items-center justify-between gap-3\">\n <h2 class=\"text-base font-semibold\">Roles</h2>\n <div class=\"text-sm text-muted-foreground\">{{ facade.items().length }} items</div>\n </div>\n\n <thead class=\"bg-muted/40\">\n <tr class=\"text-left\">\n <th class=\"px-4 py-3 font-medium\">Name</th>\n <th class=\"px-4 py-3 font-medium\">Code</th>\n <th class=\"px-4 py-3 font-medium\">Scope</th>\n <th class=\"px-4 py-3 font-medium\">Permissions</th>\n <th class=\"px-4 py-3 font-medium\">Members</th>\n <th class=\"px-4 py-3 font-medium\">Status</th>\n <th class=\"px-4 py-3 font-medium\">Actions</th>\n </tr>\n </thead>\n\n <tbody>\n @if (facade.items().length === 0) {\n <tr>\n <td colspan=\"7\" class=\"px-4 py-10 text-center text-muted-foreground\">No roles found.</td>\n </tr>\n } @else { @for (item of facade.items(); track item.id) {\n <tr class=\"border-t border-(--rt-border-color)\">\n <td class=\"px-4 py-3 font-medium\">{{ item.name }}</td>\n <td class=\"px-4 py-3 text-muted-foreground\">{{ item.code }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-scope-badge [scope]=\"item.scope\" />\n </td>\n <td class=\"px-4 py-3\">{{ item.permissionCount }}</td>\n <td class=\"px-4 py-3\">{{ item.memberCount }}</td>\n <td class=\"px-4 py-3\">\n <rolatech-platform-status-badge [status]=\"item.status\" />\n </td>\n <td class=\"px-4 py-3\">\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-xl border border-(--rt-border-color) px-3 py-2 text-sm font-medium\"\n (click)=\"openRole(item.id)\"\n >\n View Role\n </button>\n </td>\n </tr>\n } }\n </tbody>\n </rolatech-platform-data-table>\n }\n</section>\n" }]
63
+ }] });
64
+
65
+ export { ApplicationRoleIndex };
66
+ //# sourceMappingURL=rolatech-angular-platform-application-role-index-9_XVRBgD.mjs.map