@simplysm/sd-cli 14.0.95 → 14.0.96

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 (42) hide show
  1. package/dist/commands/init/generators/client.d.ts.map +1 -1
  2. package/dist/commands/init/generators/client.js +9 -0
  3. package/dist/commands/init/generators/client.js.map +1 -1
  4. package/dist/commands/init/generators/server.d.ts.map +1 -1
  5. package/dist/commands/init/generators/server.js +1 -0
  6. package/dist/commands/init/generators/server.js.map +1 -1
  7. package/package.json +5 -5
  8. package/src/commands/init/generators/client.ts +45 -0
  9. package/src/commands/init/generators/server.ts +5 -0
  10. package/src/commands/init/templates/client/src/app/home/home.view.ts.hbs +1 -1
  11. package/src/commands/init/templates/client/src/app/home/master/role-permission/role-permission.detail.ts.hbs +221 -0
  12. package/src/commands/init/templates/client/src/app/home/master/role-permission/role-permission.view.ts.hbs +106 -0
  13. package/src/commands/init/templates/client/src/app/home/master/role-permission/role.detail.ts.hbs +277 -0
  14. package/src/commands/init/templates/client/src/app/home/master/role-permission/role.list.ts.hbs +537 -0
  15. package/src/commands/init/templates/client/src/app/home/master/user.detail.ts.hbs +337 -0
  16. package/src/commands/init/templates/client/src/app/home/master/user.list.ts.hbs +540 -0
  17. package/src/commands/init/templates/client/src/app/home/my-info/my-info.detail.ts.hbs +4 -6
  18. package/src/commands/init/templates/client/src/app/home/system/data-log/data-log.list.ts.hbs +355 -0
  19. package/src/commands/init/templates/client/src/app/home/system/system-log/system-log.list.ts.hbs +382 -0
  20. package/src/commands/init/templates/client/src/app/login/login.view.ts.hbs +3 -4
  21. package/src/commands/init/templates/client/src/app.root.ts.hbs +9 -3
  22. package/src/commands/init/templates/client/src/index.html.hbs +1 -0
  23. package/src/commands/init/templates/client/src/main.ts.hbs +23 -18
  24. package/src/commands/init/templates/client/src/modals/text-view.modal.ts.hbs +30 -0
  25. package/src/commands/init/templates/client/src/routes.ts.hbs +22 -0
  26. package/src/commands/init/templates/client-common/src/index.ts.hbs +6 -4
  27. package/src/commands/init/templates/client-common/src/providers/app-auth.provider.ts.hbs +3 -3
  28. package/src/commands/init/templates/client-common/src/providers/app-orm.provider.ts.hbs +0 -11
  29. package/src/commands/init/templates/client-common/src/providers/app-service.provider.ts.hbs +24 -10
  30. package/src/commands/init/templates/client-common/src/providers/app-shared-data.provider.ts.hbs +2 -2
  31. package/src/commands/init/templates/common/package.json.hbs +2 -1
  32. package/src/commands/init/templates/common/src/app-structure.ts.hbs +7 -2
  33. package/src/commands/init/templates/common/src/auth-info-changed.event.ts.hbs +3 -1
  34. package/src/commands/init/templates/common/src/db/db-context.ts.hbs +2 -2
  35. package/src/commands/init/templates/common/src/db/tables/master/user.ts.hbs +2 -2
  36. package/src/commands/init/templates/common/src/db/tables/system/role.ts.hbs +1 -0
  37. package/src/commands/init/templates/common/src/index.ts.hbs +1 -1
  38. package/src/commands/init/templates/server/src/index.ts.hbs +3 -0
  39. package/src/commands/init/templates/server/src/main.ts.hbs +15 -1
  40. package/src/commands/init/templates/server/src/services/auth.service.ts.hbs +28 -22
  41. package/src/commands/init/templates/server/src/services/dev.service.ts.hbs +5 -5
  42. package/src/commands/init/templates/server/src/services/user.service.ts.hbs +191 -0
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/generators/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvD,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CA4Df"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/generators/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvD,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAyGf"}
@@ -27,6 +27,15 @@ export async function generateClient(cwd, base, client) {
27
27
  await renderToFile(path.join(TPL, "src/app/home/home.view.ts.hbs"), path.join(out, "src/app/home/home.view.ts"), data);
28
28
  await renderToFile(path.join(TPL, "src/app/home/main/main.view.ts.hbs"), path.join(out, "src/app/home/main/main.view.ts"), data);
29
29
  await renderToFile(path.join(TPL, "src/app/home/my-info/my-info.detail.ts.hbs"), path.join(out, "src/app/home/my-info/my-info.detail.ts"), data);
30
+ await renderToFile(path.join(TPL, "src/app/home/master/user.list.ts.hbs"), path.join(out, `src/app/home/master/${data.userEntityKebab}/${data.userEntityKebab}.list.ts`), data);
31
+ await renderToFile(path.join(TPL, "src/app/home/master/user.detail.ts.hbs"), path.join(out, `src/app/home/master/${data.userEntityKebab}/${data.userEntityKebab}.detail.ts`), data);
32
+ await renderToFile(path.join(TPL, "src/app/home/master/role-permission/role.list.ts.hbs"), path.join(out, "src/app/home/master/role-permission/role.list.ts"), data);
33
+ await renderToFile(path.join(TPL, "src/app/home/master/role-permission/role.detail.ts.hbs"), path.join(out, "src/app/home/master/role-permission/role.detail.ts"), data);
34
+ await renderToFile(path.join(TPL, "src/app/home/master/role-permission/role-permission.view.ts.hbs"), path.join(out, "src/app/home/master/role-permission/role-permission.view.ts"), data);
35
+ await renderToFile(path.join(TPL, "src/app/home/master/role-permission/role-permission.detail.ts.hbs"), path.join(out, "src/app/home/master/role-permission/role-permission.detail.ts"), data);
36
+ await renderToFile(path.join(TPL, "src/app/home/system/data-log/data-log.list.ts.hbs"), path.join(out, "src/app/home/system/data-log/data-log.list.ts"), data);
37
+ await renderToFile(path.join(TPL, "src/app/home/system/system-log/system-log.list.ts.hbs"), path.join(out, "src/app/home/system/system-log/system-log.list.ts"), data);
38
+ await renderToFile(path.join(TPL, "src/modals/text-view.modal.ts.hbs"), path.join(out, "src/modals/text-view.modal.ts"), data);
30
39
  await copyFixed(path.join(TPL, "login-public/assets/logo.png"), path.join(out, "public/assets/logo.png"));
31
40
  await copyFixed(path.join(TPL, "login-public/assets/logo-landscape.png"), path.join(out, "public/assets/logo-landscape.png"));
32
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/commands/init/generators/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/commands/init/generators/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/generators/server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCjF"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/generators/server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CjF"}
@@ -14,6 +14,7 @@ export async function generateServer(cwd, data) {
14
14
  }
15
15
  if (data.hasAuth) {
16
16
  await renderToFile(path.join(TPL, "src/services/auth.service.ts.hbs"), path.join(out, "src/services/auth.service.ts"), data);
17
+ await renderToFile(path.join(TPL, "src/services/user.service.ts.hbs"), path.join(out, `src/services/${data.userEntityKebab}.service.ts`), data);
17
18
  await copyFixed(path.join(TPL, "public-dev/초기화.xlsx"), path.join(out, "public-dev/초기화.xlsx"));
18
19
  }
19
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/commands/init/generators/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,IAAgB;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAEjD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAElF,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7F,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;IAE3F,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,4BAA4B,CAAC,EAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,wBAAwB,CAAC,EACxC,IAAI,CACL,CAAC;QACF,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iCAAiC,CAAC,EACjD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,EAC7C,IAAI,CACL,CAAC;QACF,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAClC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAC9B,IAAI,CACL,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kCAAkC,CAAC,EAClD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,8BAA8B,CAAC,EAC9C,IAAI,CACL,CAAC;QACF,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,EACrC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CACtC,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/commands/init/generators/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGnD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,IAAgB;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAEjD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAElF,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7F,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;IAE3F,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,4BAA4B,CAAC,EAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,wBAAwB,CAAC,EACxC,IAAI,CACL,CAAC;QACF,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iCAAiC,CAAC,EACjD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,EAC7C,IAAI,CACL,CAAC;QACF,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAClC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAC9B,IAAI,CACL,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kCAAkC,CAAC,EAClD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,8BAA8B,CAAC,EAC9C,IAAI,CACL,CAAC;QACF,MAAM,YAAY,CAChB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kCAAkC,CAAC,EAClD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,IAAI,CAAC,eAAe,aAAa,CAAC,EACjE,IAAI,CACL,CAAC;QACF,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,EACrC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CACtC,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/sd-cli",
3
- "version": "14.0.95",
3
+ "version": "14.0.96",
4
4
  "description": "Simplysm package - CLI tool",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -37,7 +37,7 @@
37
37
  "mime": "^4.1.0",
38
38
  "postcss": "^8.5.15",
39
39
  "sass": "^1.100.0",
40
- "semver": "^7.8.2",
40
+ "semver": "^7.8.3",
41
41
  "sharp": "^0.34.5",
42
42
  "smol-toml": "^1.6.1",
43
43
  "ssh2": "^1.17.0",
@@ -45,9 +45,9 @@
45
45
  "ws": "^8.21.0",
46
46
  "yaml": "^2.9.0",
47
47
  "yargs": "^18.0.0",
48
- "@simplysm/core-common": "14.0.95",
49
- "@simplysm/core-node": "14.0.95",
50
- "@simplysm/storage": "14.0.95"
48
+ "@simplysm/core-common": "14.0.96",
49
+ "@simplysm/core-node": "14.0.96",
50
+ "@simplysm/storage": "14.0.96"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/semver": "^7.7.1",
@@ -60,6 +60,51 @@ export async function generateClient(
60
60
  path.join(out, "src/app/home/my-info/my-info.detail.ts"),
61
61
  data,
62
62
  );
63
+ await renderToFile(
64
+ path.join(TPL, "src/app/home/master/user.list.ts.hbs"),
65
+ path.join(out, `src/app/home/master/${data.userEntityKebab}/${data.userEntityKebab}.list.ts`),
66
+ data,
67
+ );
68
+ await renderToFile(
69
+ path.join(TPL, "src/app/home/master/user.detail.ts.hbs"),
70
+ path.join(out, `src/app/home/master/${data.userEntityKebab}/${data.userEntityKebab}.detail.ts`),
71
+ data,
72
+ );
73
+ await renderToFile(
74
+ path.join(TPL, "src/app/home/master/role-permission/role.list.ts.hbs"),
75
+ path.join(out, "src/app/home/master/role-permission/role.list.ts"),
76
+ data,
77
+ );
78
+ await renderToFile(
79
+ path.join(TPL, "src/app/home/master/role-permission/role.detail.ts.hbs"),
80
+ path.join(out, "src/app/home/master/role-permission/role.detail.ts"),
81
+ data,
82
+ );
83
+ await renderToFile(
84
+ path.join(TPL, "src/app/home/master/role-permission/role-permission.view.ts.hbs"),
85
+ path.join(out, "src/app/home/master/role-permission/role-permission.view.ts"),
86
+ data,
87
+ );
88
+ await renderToFile(
89
+ path.join(TPL, "src/app/home/master/role-permission/role-permission.detail.ts.hbs"),
90
+ path.join(out, "src/app/home/master/role-permission/role-permission.detail.ts"),
91
+ data,
92
+ );
93
+ await renderToFile(
94
+ path.join(TPL, "src/app/home/system/data-log/data-log.list.ts.hbs"),
95
+ path.join(out, "src/app/home/system/data-log/data-log.list.ts"),
96
+ data,
97
+ );
98
+ await renderToFile(
99
+ path.join(TPL, "src/app/home/system/system-log/system-log.list.ts.hbs"),
100
+ path.join(out, "src/app/home/system/system-log/system-log.list.ts"),
101
+ data,
102
+ );
103
+ await renderToFile(
104
+ path.join(TPL, "src/modals/text-view.modal.ts.hbs"),
105
+ path.join(out, "src/modals/text-view.modal.ts"),
106
+ data,
107
+ );
63
108
  await copyFixed(
64
109
  path.join(TPL, "login-public/assets/logo.png"),
65
110
  path.join(out, "public/assets/logo.png"),
@@ -37,6 +37,11 @@ export async function generateServer(cwd: string, data: RenderData): Promise<voi
37
37
  path.join(out, "src/services/auth.service.ts"),
38
38
  data,
39
39
  );
40
+ await renderToFile(
41
+ path.join(TPL, "src/services/user.service.ts.hbs"),
42
+ path.join(out, `src/services/${data.userEntityKebab}.service.ts`),
43
+ data,
44
+ );
40
45
  await copyFixed(
41
46
  path.join(TPL, "public-dev/초기화.xlsx"),
42
47
  path.join(out, "public-dev/초기화.xlsx"),
@@ -46,7 +46,7 @@ import { tablerUserCircle } from "@ng-icons/tabler-icons";
46
46
  <sd-sidebar class="flex-column">
47
47
  <div>
48
48
  <div
49
- class="p-default-xl sh-topbar"
49
+ class="p-sm-lg sh-topbar"
50
50
  style="cursor: pointer;"
51
51
  [sdRouterLink]="{ link: '/home/main' }"
52
52
  >
@@ -0,0 +1,221 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ computed,
5
+ effect,
6
+ inject,
7
+ input,
8
+ signal,
9
+ untracked,
10
+ ViewEncapsulation,
11
+ } from "@angular/core";
12
+ import { json, obj } from "@simplysm/core-common";
13
+ import {
14
+ injectPermsSignal,
15
+ injectViewTypeSignal,
16
+ SdAppStructureProvider,
17
+ SdButton,
18
+ SdCrudDetail,
19
+ SdItemOfTemplate,
20
+ SdPermissionTable,
21
+ SdSharedDataSelect,
22
+ SdToastProvider,
23
+ } from "@simplysm/angular";
24
+ import { expr } from "@simplysm/orm-common";
25
+ import {
26
+ AppAuthProvider,
27
+ AppOrmProvider,
28
+ AppServiceProvider,
29
+ useSharedSignal,
30
+ } from "@{{workspaceName}}/client-common";
31
+ import { RoleList } from "./role.list";
32
+
33
+ @Component({
34
+ selector: "app-role-permission-detail",
35
+ changeDetection: ChangeDetectionStrategy.OnPush,
36
+ encapsulation: ViewEncapsulation.None,
37
+ standalone: true,
38
+ imports: [SdCrudDetail, SdPermissionTable, SdSharedDataSelect, SdItemOfTemplate, SdButton],
39
+ template: `
40
+ <sd-crud-detail
41
+ [(ready)]="ready"
42
+ [initialized]="initialized()"
43
+ [(busyCount)]="busyCount"
44
+ [viewType]="viewType()"
45
+ [restricted]="!perms().includes('use')"
46
+ [readonly]="!perms().includes('edit')"
47
+ (submit)="onSubmit()"
48
+ >
49
+ <ng-template #contentTpl>
50
+ <div class="flex-column">
51
+ @if (perms().includes("edit")) {
52
+ <div class="flex-row gap-sm p-sm-default">
53
+ <sd-shared-data-select
54
+ [size]="'sm'"
55
+ [items]="sharedRoles.items()"
56
+ [(value)]="copySourceRoleId"
57
+ [modal]="{ type: RoleList, title: '역할', inputs: { readonly: true } }"
58
+ >
59
+ <ng-template [itemOf]="sharedRoles.items()" let-item="item">
60
+ \{{ item.name }}
61
+ </ng-template>
62
+ </sd-shared-data-select>
63
+ <sd-button
64
+ [size]="'sm'"
65
+ [inline]="true"
66
+ [disabled]="copySourceRoleId() == null"
67
+ (click)="onImport()"
68
+ >
69
+ 가져오기
70
+ </sd-button>
71
+ </div>
72
+ }
73
+ <sd-permission-table
74
+ [items]="permItems()"
75
+ [(value)]="data"
76
+ [disabled]="!perms().includes('edit')"
77
+ />
78
+ </div>
79
+ </ng-template>
80
+ </sd-crud-detail>
81
+ `,
82
+ })
83
+ export class RolePermissionDetail {
84
+ private readonly _sdToast = inject(SdToastProvider);
85
+ private readonly _appOrm = inject(AppOrmProvider);
86
+ private readonly _appService = inject(AppServiceProvider);
87
+ private readonly _appAuth = inject(AppAuthProvider);
88
+ private readonly _sdAppStructure = inject(SdAppStructureProvider);
89
+
90
+ roleId = input.required<number>();
91
+
92
+ perms = injectPermsSignal(["master.role-permission"], ["use", "edit"]);
93
+ viewType = injectViewTypeSignal();
94
+
95
+ ready = signal(false);
96
+ initialized = signal(false);
97
+ busyCount = signal(0);
98
+
99
+ sharedRoles = useSharedSignal("역할");
100
+ copySourceRoleId = signal<number | undefined>(undefined);
101
+
102
+ permItems = computed(() =>
103
+ this._sdAppStructure.getPermissionsByStructure(this._sdAppStructure.items()),
104
+ );
105
+
106
+ data = signal<Record<string, boolean>>({});
107
+ private _orgData?: Record<string, boolean>;
108
+
109
+ constructor() {
110
+ effect(() => {
111
+ this.roleId();
112
+
113
+ if (!this.perms().includes("use") || !this.ready()) {
114
+ this.initialized.set(true);
115
+ return;
116
+ }
117
+
118
+ void untracked(async () => {
119
+ this.busyCount.update((v) => v + 1);
120
+ await this._sdToast.try(async () => {
121
+ await this._refresh();
122
+ });
123
+ this.busyCount.update((v) => v - 1);
124
+ this.initialized.set(true);
125
+ });
126
+ });
127
+ }
128
+
129
+ async onImport(): Promise<void> {
130
+ if (this.busyCount() > 0) return;
131
+ if (!this.perms().includes("edit")) return;
132
+
133
+ const sourceId = this.copySourceRoleId();
134
+ if (sourceId == null) return;
135
+
136
+ this.busyCount.update((v) => v + 1);
137
+ await this._sdToast.try(async () => {
138
+ const record = await this._loadPermissions(sourceId);
139
+ this.data.set(record);
140
+ });
141
+ this.busyCount.update((v) => v - 1);
142
+ }
143
+
144
+ async onSubmit(): Promise<void> {
145
+ if (this.busyCount() > 0) return;
146
+ if (!this.perms().includes("edit")) return;
147
+
148
+ const data = this.data();
149
+ if (this._orgData != null && obj.equal(data, this._orgData)) {
150
+ this._sdToast.info("변경사항이 없습니다.");
151
+ return;
152
+ }
153
+
154
+ this.busyCount.update((v) => v + 1);
155
+ await this._sdToast.try(async () => {
156
+ const roleId = this.roleId();
157
+ const {{userEntityCamel}}Id = this._appAuth.authInfo()?.{{userEntityCamel}}Id;
158
+
159
+ // 권한 동기화: 기존 전체 삭제 후 부여된 권한만 재적재
160
+ await this._appOrm.connectAsync(async (db) => {
161
+ await db
162
+ .rolePermission()
163
+ .where((c) => [expr.eq(c.roleId, roleId)])
164
+ .delete();
165
+
166
+ const entries = Object.entries(data).filter(([, v]) => v);
167
+ if (entries.length > 0) {
168
+ await db.rolePermission().insert(
169
+ entries.map(([code, value]) => ({
170
+ roleId,
171
+ code,
172
+ valueJson: json.stringify(value),
173
+ })),
174
+ );
175
+ }
176
+
177
+ // 권한 집합 변경 이력은 부모 Role 모델에 단일 적재 (itemId=roleId)
178
+ await db.role().insertDataLog({ action: "수정(권한)", itemId: roleId, {{userEntityCamel}}Id });
179
+ });
180
+
181
+ // 해당 역할 세션에 인증정보 변경 통지 → 권한 재로드 (roleId 로 직접 타겟, {{userEntityLabel}} 조회 불필요)
182
+ await this._appService.authInfoChangedEvent.emit((info) => info.roleId === roleId, undefined);
183
+
184
+ this._sdToast.success("저장되었습니다.");
185
+ await this._refresh();
186
+ });
187
+ this.busyCount.update((v) => v - 1);
188
+ }
189
+
190
+ checkIgnoreChanges(): boolean {
191
+ return (
192
+ this._orgData == null ||
193
+ obj.equal(this.data(), this._orgData) ||
194
+ confirm("변경사항이 있습니다. 무시하고 진행하시겠습니까?")
195
+ );
196
+ }
197
+
198
+ private async _refresh(): Promise<void> {
199
+ const record = await this._loadPermissions(this.roleId());
200
+ this.data.set(record);
201
+ this._orgData = obj.clone(record);
202
+ }
203
+
204
+ private async _loadPermissions(roleId: number): Promise<Record<string, boolean>> {
205
+ return this._appOrm.connectAsync(async (db) => {
206
+ const rows = await db
207
+ .rolePermission()
208
+ .where((c) => [expr.eq(c.roleId, roleId)])
209
+ .select((c) => ({ code: c.code, valueJson: c.valueJson }))
210
+ .execute();
211
+
212
+ const record: Record<string, boolean> = {};
213
+ for (const row of rows) {
214
+ record[row.code] = json.parse(row.valueJson);
215
+ }
216
+ return record;
217
+ });
218
+ }
219
+
220
+ protected readonly RoleList = RoleList;
221
+ }
@@ -0,0 +1,106 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ effect,
5
+ signal,
6
+ untracked,
7
+ viewChild,
8
+ ViewEncapsulation,
9
+ } from "@angular/core";
10
+ import {
11
+ injectViewTypeSignal,
12
+ SdBaseContainer,
13
+ SdItemOfTemplate,
14
+ SdSharedDataSelectList,
15
+ setupCanDeactivate,
16
+ } from "@simplysm/angular";
17
+ import { NgIcon } from "@ng-icons/core";
18
+ import { tablerArrowLeft } from "@ng-icons/tabler-icons";
19
+ import { type ISharedRole, useSharedSignal } from "@{{workspaceName}}/client-common";
20
+ import { RolePermissionDetail } from "./role-permission.detail";
21
+ import { RoleList } from "./role.list";
22
+
23
+ @Component({
24
+ selector: "app-role-permission-view",
25
+ changeDetection: ChangeDetectionStrategy.OnPush,
26
+ encapsulation: ViewEncapsulation.None,
27
+ standalone: true,
28
+ imports: [
29
+ SdBaseContainer,
30
+ SdSharedDataSelectList,
31
+ SdItemOfTemplate,
32
+ RolePermissionDetail,
33
+ NgIcon,
34
+ ],
35
+ template: `
36
+ <sd-base-container
37
+ [(ready)]="ready"
38
+ [initialized]="initialized()"
39
+ [(busyCount)]="busyCount"
40
+ [viewType]="viewType()"
41
+ >
42
+ <ng-template #contentTpl>
43
+ <div class="flex-row fill">
44
+ <!-- min-width: 좌측 역할 목록이 너무 좁아져 가독성이 떨어지는 것을 막는 의도적 고정 폭 (사용자 지시) -->
45
+ <sd-shared-data-select-list
46
+ class="flex-min bdr bdr-color-lighter"
47
+ style="min-width: 12rem;"
48
+ [items]="sharedRoles.items()"
49
+ [(selectedItem)]="selectedRole"
50
+ [canChangeFn]="checkCanLeave"
51
+ [header]="'역할'"
52
+ [modal]="{ type: RoleList, title: '역할', inputs: {} }"
53
+ >
54
+ <ng-template [itemOf]="sharedRoles.items()" let-item="item">
55
+ \{{ item.name }}
56
+ </ng-template>
57
+ </sd-shared-data-select-list>
58
+
59
+ @let _selectedRole = selectedRole();
60
+ @if (_selectedRole == null) {
61
+ <div
62
+ class="flex-fill tx-theme-gray-default p-xxl"
63
+ style="font-size: 48px; line-height: 1.5em"
64
+ >
65
+ <ng-icon [svg]="tablerArrowLeft" />
66
+ 역할을 선택하세요.
67
+ </div>
68
+ } @else {
69
+ <app-role-permission-detail class="flex-fill" [roleId]="_selectedRole.id" />
70
+ }
71
+ </div>
72
+ </ng-template>
73
+ </sd-base-container>
74
+ `,
75
+ })
76
+ export class RolePermissionView {
77
+ viewType = injectViewTypeSignal();
78
+
79
+ ready = signal(false);
80
+ initialized = signal(false);
81
+ busyCount = signal(0);
82
+
83
+ sharedRoles = useSharedSignal("역할");
84
+ selectedRole = signal<ISharedRole | undefined>(undefined);
85
+
86
+ detail = viewChild(RolePermissionDetail);
87
+
88
+ // 미저장 권한 변경 보호: 페이지 이탈·역할 전환 전에 자식 detail 의 변경 가드 확인
89
+ protected readonly checkCanLeave = (): boolean => {
90
+ const detail = this.detail();
91
+ return detail == null || detail.checkIgnoreChanges();
92
+ };
93
+
94
+ constructor() {
95
+ effect(() => {
96
+ if (this.ready()) {
97
+ untracked(() => this.initialized.set(true));
98
+ }
99
+ });
100
+
101
+ setupCanDeactivate(this.checkCanLeave);
102
+ }
103
+
104
+ protected readonly RoleList = RoleList;
105
+ protected readonly tablerArrowLeft = tablerArrowLeft;
106
+ }