wcz-layout 6.7.2 → 8.3.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 (269) hide show
  1. package/dist/Approval-BTJTexDo.js +143 -0
  2. package/dist/Approval-BTJTexDo.js.map +1 -0
  3. package/dist/DialogsContext-DLqA8RJ_.js +7 -0
  4. package/dist/DialogsContext-DLqA8RJ_.js.map +1 -0
  5. package/dist/Email-C9qwj7GD.js +20 -0
  6. package/dist/Email-C9qwj7GD.js.map +1 -0
  7. package/dist/FileMeta-DDqUju1Y.js +19 -0
  8. package/dist/FileMeta-DDqUju1Y.js.map +1 -0
  9. package/dist/FileMeta-ILLTOjaM.d.ts +20 -0
  10. package/dist/NotificationContext-CgwUOeW0.js +7 -0
  11. package/dist/NotificationContext-CgwUOeW0.js.map +1 -0
  12. package/dist/RouterListItemButton-owZVvuC_.js +78 -0
  13. package/dist/RouterListItemButton-owZVvuC_.js.map +1 -0
  14. package/dist/User-CT_IDGuG.d.ts +15 -0
  15. package/dist/apiMiddleware-CtY4rOFU.js +23 -0
  16. package/dist/apiMiddleware-CtY4rOFU.js.map +1 -0
  17. package/dist/components.d.ts +118 -0
  18. package/dist/components.js +1554 -0
  19. package/dist/components.js.map +1 -0
  20. package/dist/data/client.d.ts +3111 -0
  21. package/dist/data/client.js +188 -0
  22. package/dist/data/client.js.map +1 -0
  23. package/dist/data/server.d.ts +19 -0
  24. package/dist/data/server.js +16 -0
  25. package/dist/data/server.js.map +1 -0
  26. package/dist/data.d.ts +7 -0
  27. package/dist/data.js +2 -0
  28. package/dist/env-ON-cyE3N.js +31 -0
  29. package/dist/env-ON-cyE3N.js.map +1 -0
  30. package/dist/file-BUdLb7H1.js +148 -0
  31. package/dist/file-BUdLb7H1.js.map +1 -0
  32. package/dist/file-Dsht7yOP.js +100 -0
  33. package/dist/file-Dsht7yOP.js.map +1 -0
  34. package/dist/hooks.d.ts +226 -0
  35. package/dist/hooks.js +1180 -0
  36. package/dist/hooks.js.map +1 -0
  37. package/dist/index.d.ts +50 -0
  38. package/dist/index.js +2106 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/middleware.d.ts +47 -0
  41. package/dist/middleware.js +80 -0
  42. package/dist/middleware.js.map +1 -0
  43. package/dist/models.d.ts +474 -0
  44. package/dist/models.js +74 -0
  45. package/dist/models.js.map +1 -0
  46. package/dist/msalClient-CYiQAFnY.d.ts +15 -0
  47. package/dist/msalServer-B9sVqpQ2.js +47 -0
  48. package/dist/msalServer-B9sVqpQ2.js.map +1 -0
  49. package/dist/peoplesoft-BCjRje6b.js +240 -0
  50. package/dist/peoplesoft-BCjRje6b.js.map +1 -0
  51. package/dist/peoplesoft-Cze2ngGd.d.ts +1150 -0
  52. package/dist/queryClient-D64McLhZ.js +7 -0
  53. package/dist/queryClient-D64McLhZ.js.map +1 -0
  54. package/dist/useDialogs-BJVhBr8S.js +248 -0
  55. package/dist/useDialogs-BJVhBr8S.js.map +1 -0
  56. package/dist/utils-BMUmv2ws.js +191 -0
  57. package/dist/utils-BMUmv2ws.js.map +1 -0
  58. package/dist/utils-CvvyM8Xw.d.ts +56 -0
  59. package/dist/utils.d.ts +21 -0
  60. package/dist/utils.js +6 -0
  61. package/dist/vite.d.ts +7 -0
  62. package/dist/vite.js +147 -0
  63. package/dist/vite.js.map +1 -0
  64. package/package.json +158 -62
  65. package/skills/client-db/SKILL.md +107 -0
  66. package/skills/data-grid/SKILL.md +147 -0
  67. package/skills/db-schema/SKILL.md +68 -0
  68. package/skills/dialogs/SKILL.md +79 -0
  69. package/skills/forms/SKILL.md +82 -0
  70. package/skills/general/SKILL.md +17 -0
  71. package/skills/notifications/SKILL.md +43 -0
  72. package/skills/routing/SKILL.md +123 -0
  73. package/skills/server-functions/SKILL.md +109 -0
  74. package/skills/services/SKILL.md +28 -0
  75. package/skills/services/docs/approval.md +204 -0
  76. package/skills/services/docs/email.md +32 -0
  77. package/skills/services/docs/file.md +85 -0
  78. package/skills/services/docs/peoplesoft.md +110 -0
  79. package/skills/start/SKILL.md +46 -0
  80. package/skills/start/steps/01-git-setup.md +10 -0
  81. package/skills/start/steps/02-project-name-setup.md +14 -0
  82. package/skills/start/steps/03-apm-setup.md +208 -0
  83. package/skills/start/steps/04-database-setup.md +37 -0
  84. package/skills/start/steps/05-entra-setup.md +59 -0
  85. package/skills/start/steps/06-vault-setup.md +53 -0
  86. package/skills/start/steps/07-generate-favicon.md +10 -0
  87. package/skills/start/steps/08-commit.md +15 -0
  88. package/dist/src/components/Layout.d.ts +0 -16
  89. package/dist/src/components/Layout.js +0 -122
  90. package/dist/src/components/Layout.js.map +0 -1
  91. package/dist/src/components/dataGrid/ChipInputCell.d.ts +0 -9
  92. package/dist/src/components/dataGrid/ChipInputCell.js +0 -17
  93. package/dist/src/components/dataGrid/ChipInputCell.js.map +0 -1
  94. package/dist/src/components/dataGrid/EditableColumnHeader.d.ts +0 -2
  95. package/dist/src/components/dataGrid/EditableColumnHeader.js +0 -7
  96. package/dist/src/components/dataGrid/EditableColumnHeader.js.map +0 -1
  97. package/dist/src/components/dataGrid/GridToolbar.d.ts +0 -8
  98. package/dist/src/components/dataGrid/GridToolbar.js +0 -40
  99. package/dist/src/components/dataGrid/GridToolbar.js.map +0 -1
  100. package/dist/src/components/dataGrid/TableContainer.d.ts +0 -3
  101. package/dist/src/components/dataGrid/TableContainer.js +0 -32
  102. package/dist/src/components/dataGrid/TableContainer.js.map +0 -1
  103. package/dist/src/components/form/FormAutocomplete.d.ts +0 -7
  104. package/dist/src/components/form/FormAutocomplete.js +0 -10
  105. package/dist/src/components/form/FormAutocomplete.js.map +0 -1
  106. package/dist/src/components/form/FormCheckbox.d.ts +0 -7
  107. package/dist/src/components/form/FormCheckbox.js +0 -11
  108. package/dist/src/components/form/FormCheckbox.js.map +0 -1
  109. package/dist/src/components/form/FormDatePicker.d.ts +0 -9
  110. package/dist/src/components/form/FormDatePicker.js +0 -19
  111. package/dist/src/components/form/FormDatePicker.js.map +0 -1
  112. package/dist/src/components/form/FormDateTimePicker.d.ts +0 -9
  113. package/dist/src/components/form/FormDateTimePicker.js +0 -19
  114. package/dist/src/components/form/FormDateTimePicker.js.map +0 -1
  115. package/dist/src/components/form/FormNumberField.d.ts +0 -12
  116. package/dist/src/components/form/FormNumberField.js +0 -12
  117. package/dist/src/components/form/FormNumberField.js.map +0 -1
  118. package/dist/src/components/form/FormRadioGroup.d.ts +0 -13
  119. package/dist/src/components/form/FormRadioGroup.js +0 -11
  120. package/dist/src/components/form/FormRadioGroup.js.map +0 -1
  121. package/dist/src/components/form/FormSlider.d.ts +0 -7
  122. package/dist/src/components/form/FormSlider.js +0 -11
  123. package/dist/src/components/form/FormSlider.js.map +0 -1
  124. package/dist/src/components/form/FormSubmitButton.d.ts +0 -5
  125. package/dist/src/components/form/FormSubmitButton.js +0 -13
  126. package/dist/src/components/form/FormSubmitButton.js.map +0 -1
  127. package/dist/src/components/form/FormSwitch.d.ts +0 -7
  128. package/dist/src/components/form/FormSwitch.js +0 -11
  129. package/dist/src/components/form/FormSwitch.js.map +0 -1
  130. package/dist/src/components/form/FormTextField.d.ts +0 -7
  131. package/dist/src/components/form/FormTextField.js +0 -11
  132. package/dist/src/components/form/FormTextField.js.map +0 -1
  133. package/dist/src/components/layout/AccountMenu.d.ts +0 -9
  134. package/dist/src/components/layout/AccountMenu.js +0 -44
  135. package/dist/src/components/layout/AccountMenu.js.map +0 -1
  136. package/dist/src/components/layout/DevelopmentBanner.d.ts +0 -7
  137. package/dist/src/components/layout/DevelopmentBanner.js +0 -29
  138. package/dist/src/components/layout/DevelopmentBanner.js.map +0 -1
  139. package/dist/src/components/layout/ErrorPage.d.ts +0 -2
  140. package/dist/src/components/layout/ErrorPage.js +0 -25
  141. package/dist/src/components/layout/ErrorPage.js.map +0 -1
  142. package/dist/src/components/layout/LayoutDialog.d.ts +0 -12
  143. package/dist/src/components/layout/LayoutDialog.js +0 -12
  144. package/dist/src/components/layout/LayoutDialog.js.map +0 -1
  145. package/dist/src/components/layout/LayoutSnackbar.d.ts +0 -8
  146. package/dist/src/components/layout/LayoutSnackbar.js +0 -25
  147. package/dist/src/components/layout/LayoutSnackbar.js.map +0 -1
  148. package/dist/src/components/layout/NavigationDrawer.d.ts +0 -11
  149. package/dist/src/components/layout/NavigationDrawer.js +0 -70
  150. package/dist/src/components/layout/NavigationDrawer.js.map +0 -1
  151. package/dist/src/components/layout/NotificationMenu.d.ts +0 -8
  152. package/dist/src/components/layout/NotificationMenu.js +0 -26
  153. package/dist/src/components/layout/NotificationMenu.js.map +0 -1
  154. package/dist/src/components/layout/TypographyWithIcon.d.ts +0 -7
  155. package/dist/src/components/layout/TypographyWithIcon.js +0 -22
  156. package/dist/src/components/layout/TypographyWithIcon.js.map +0 -1
  157. package/dist/src/components/layout/Unauthorized.d.ts +0 -2
  158. package/dist/src/components/layout/Unauthorized.js +0 -26
  159. package/dist/src/components/layout/Unauthorized.js.map +0 -1
  160. package/dist/src/contexts/LayoutContext.d.ts +0 -40
  161. package/dist/src/contexts/LayoutContext.js +0 -60
  162. package/dist/src/contexts/LayoutContext.js.map +0 -1
  163. package/dist/src/contexts/UserContext.d.ts +0 -24
  164. package/dist/src/contexts/UserContext.js +0 -55
  165. package/dist/src/contexts/UserContext.js.map +0 -1
  166. package/dist/src/hooks/FormHooks.d.ts +0 -46
  167. package/dist/src/hooks/FormHooks.js +0 -31
  168. package/dist/src/hooks/FormHooks.js.map +0 -1
  169. package/dist/src/hooks/UseSnackbar.d.ts +0 -10
  170. package/dist/src/hooks/UseSnackbar.js +0 -23
  171. package/dist/src/hooks/UseSnackbar.js.map +0 -1
  172. package/dist/src/hooks/UseUser.d.ts +0 -10
  173. package/dist/src/hooks/UseUser.js +0 -25
  174. package/dist/src/hooks/UseUser.js.map +0 -1
  175. package/dist/src/index.d.ts +0 -20
  176. package/dist/src/index.js +0 -15
  177. package/dist/src/index.js.map +0 -1
  178. package/dist/src/models/Error.d.ts +0 -6
  179. package/dist/src/models/Error.js +0 -2
  180. package/dist/src/models/Error.js.map +0 -1
  181. package/dist/src/models/KeycloakSettings.d.ts +0 -8
  182. package/dist/src/models/KeycloakSettings.js +0 -2
  183. package/dist/src/models/KeycloakSettings.js.map +0 -1
  184. package/dist/src/models/LayoutPaletteColorOptions.d.ts +0 -6
  185. package/dist/src/models/LayoutPaletteColorOptions.js +0 -2
  186. package/dist/src/models/LayoutPaletteColorOptions.js.map +0 -1
  187. package/dist/src/models/LayoutRoute.d.ts +0 -14
  188. package/dist/src/models/LayoutRoute.js +0 -2
  189. package/dist/src/models/LayoutRoute.js.map +0 -1
  190. package/dist/src/models/Notification.d.ts +0 -9
  191. package/dist/src/models/Notification.js +0 -2
  192. package/dist/src/models/Notification.js.map +0 -1
  193. package/dist/src/models/PeoplesoftDepartment.d.ts +0 -14
  194. package/dist/src/models/PeoplesoftDepartment.js +0 -2
  195. package/dist/src/models/PeoplesoftDepartment.js.map +0 -1
  196. package/dist/src/models/PeoplesoftEmployee.d.ts +0 -34
  197. package/dist/src/models/PeoplesoftEmployee.js +0 -2
  198. package/dist/src/models/PeoplesoftEmployee.js.map +0 -1
  199. package/dist/src/models/Snackbar.d.ts +0 -15
  200. package/dist/src/models/Snackbar.js +0 -2
  201. package/dist/src/models/Snackbar.js.map +0 -1
  202. package/dist/src/models/User.d.ts +0 -27
  203. package/dist/src/models/User.js +0 -11
  204. package/dist/src/models/User.js.map +0 -1
  205. package/dist/src/models/types/EmployeeCategoryGroup.d.ts +0 -1
  206. package/dist/src/models/types/EmployeeCategoryGroup.js +0 -2
  207. package/dist/src/models/types/EmployeeCategoryGroup.js.map +0 -1
  208. package/dist/src/models/types/EmployeeStatus.d.ts +0 -1
  209. package/dist/src/models/types/EmployeeStatus.js +0 -2
  210. package/dist/src/models/types/EmployeeStatus.js.map +0 -1
  211. package/dist/src/utils/Auth.d.ts +0 -12
  212. package/dist/src/utils/Auth.js +0 -49
  213. package/dist/src/utils/Auth.js.map +0 -1
  214. package/dist/src/utils/Fetches.d.ts +0 -5
  215. package/dist/src/utils/Fetches.js +0 -66
  216. package/dist/src/utils/Fetches.js.map +0 -1
  217. package/dist/src/utils/FormUtils.d.ts +0 -7
  218. package/dist/src/utils/FormUtils.js +0 -9
  219. package/dist/src/utils/FormUtils.js.map +0 -1
  220. package/dist/src/utils/Helpers.d.ts +0 -11
  221. package/dist/src/utils/Helpers.js +0 -26
  222. package/dist/src/utils/Helpers.js.map +0 -1
  223. package/dist/tsconfig.tsbuildinfo +0 -1
  224. package/src/components/Layout.tsx +0 -183
  225. package/src/components/dataGrid/ChipInputCell.tsx +0 -31
  226. package/src/components/dataGrid/EditableColumnHeader.tsx +0 -7
  227. package/src/components/dataGrid/GridToolbar.tsx +0 -63
  228. package/src/components/dataGrid/TableContainer.tsx +0 -39
  229. package/src/components/form/FormAutocomplete.tsx +0 -34
  230. package/src/components/form/FormCheckbox.tsx +0 -32
  231. package/src/components/form/FormDatePicker.tsx +0 -34
  232. package/src/components/form/FormDateTimePicker.tsx +0 -34
  233. package/src/components/form/FormNumberField.tsx +0 -33
  234. package/src/components/form/FormRadioGroup.tsx +0 -43
  235. package/src/components/form/FormSlider.tsx +0 -28
  236. package/src/components/form/FormSubmitButton.tsx +0 -29
  237. package/src/components/form/FormSwitch.tsx +0 -32
  238. package/src/components/form/FormTextField.tsx +0 -26
  239. package/src/components/layout/AccountMenu.tsx +0 -160
  240. package/src/components/layout/DevelopmentBanner.tsx +0 -54
  241. package/src/components/layout/ErrorPage.tsx +0 -34
  242. package/src/components/layout/LayoutDialog.tsx +0 -50
  243. package/src/components/layout/LayoutSnackbar.tsx +0 -44
  244. package/src/components/layout/NavigationDrawer.tsx +0 -131
  245. package/src/components/layout/NotificationMenu.tsx +0 -76
  246. package/src/components/layout/TypographyWithIcon.tsx +0 -35
  247. package/src/components/layout/Unauthorized.tsx +0 -37
  248. package/src/contexts/LayoutContext.tsx +0 -127
  249. package/src/contexts/UserContext.tsx +0 -88
  250. package/src/hooks/FormHooks.ts +0 -33
  251. package/src/hooks/UseSnackbar.tsx +0 -28
  252. package/src/hooks/UseUser.tsx +0 -29
  253. package/src/index.ts +0 -27
  254. package/src/models/Error.tsx +0 -6
  255. package/src/models/KeycloakSettings.ts +0 -8
  256. package/src/models/LayoutPaletteColorOptions.tsx +0 -7
  257. package/src/models/LayoutRoute.ts +0 -15
  258. package/src/models/Notification.ts +0 -10
  259. package/src/models/PeoplesoftDepartment.ts +0 -15
  260. package/src/models/PeoplesoftEmployee.ts +0 -35
  261. package/src/models/Snackbar.ts +0 -16
  262. package/src/models/User.ts +0 -13
  263. package/src/models/types/EmployeeCategoryGroup.ts +0 -1
  264. package/src/models/types/EmployeeStatus.ts +0 -1
  265. package/src/utils/Auth.ts +0 -58
  266. package/src/utils/Fetches.ts +0 -83
  267. package/src/utils/FormUtils.ts +0 -22
  268. package/src/utils/Helpers.ts +0 -27
  269. package/tsconfig.json +0 -29
package/dist/vite.js ADDED
@@ -0,0 +1,147 @@
1
+ import z$1 from "zod";
2
+ import axios from "axios";
3
+ import https from "node:https";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { loadEnv } from "vite";
7
+ //#region src/models/VaultConfig.ts
8
+ const VaultConfigSchema = z$1.object({
9
+ VAULT_ADDRESS: z$1.url(),
10
+ VAULT_USERNAME: z$1.string().min(1),
11
+ VAULT_PASSWORD: z$1.string().min(1),
12
+ VAULT_SECRET_PATH: z$1.string().min(1),
13
+ VAULT_MOUNT_POINT: z$1.string().default("release")
14
+ });
15
+ //#endregion
16
+ //#region src/lib/vite-plugin.ts
17
+ async function fetchVaultSecrets(env) {
18
+ const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } = VaultConfigSchema.parse(env);
19
+ const client = axios.create({
20
+ baseURL: VAULT_ADDRESS,
21
+ httpsAgent: new https.Agent({ rejectUnauthorized: false })
22
+ });
23
+ const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, { password: VAULT_PASSWORD });
24
+ const { data: secretData } = await client.get(`/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`, { headers: { "X-Vault-Token": loginData.auth.client_token } });
25
+ const secrets = secretData?.data?.data;
26
+ if (!secrets) throw new Error("No secrets found");
27
+ return Object.fromEntries(Object.entries(secrets).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)]));
28
+ }
29
+ async function loadVaultSecrets(command) {
30
+ if (command !== "serve") return;
31
+ const env = loadEnv("development", process.cwd(), "");
32
+ if (!env.VAULT_ADDRESS) return;
33
+ try {
34
+ const secrets = await fetchVaultSecrets(env);
35
+ Object.entries(secrets).forEach(([key, value]) => {
36
+ process.env[key] ??= value;
37
+ });
38
+ } catch (e) {
39
+ console.warn("[vite:wcz-layout] Vault failed:", e instanceof Error ? e.message : e);
40
+ }
41
+ }
42
+ function loadLocaleResources(localesPath, addWatchFile) {
43
+ if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true });
44
+ const enPath = path.join(localesPath, "en.json");
45
+ if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({}));
46
+ const files = fs.readdirSync(localesPath);
47
+ const resources = {};
48
+ for (const file of files.filter((f) => f.endsWith(".json"))) {
49
+ const lang = path.basename(file, ".json");
50
+ const filePath = path.join(localesPath, file);
51
+ try {
52
+ resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, "utf-8")) };
53
+ } catch {
54
+ resources[lang] = { translation: {} };
55
+ }
56
+ addWatchFile(filePath);
57
+ }
58
+ return resources;
59
+ }
60
+ function ensurePermissionsFile(permissionsPath, addWatchFile) {
61
+ const dir = path.dirname(permissionsPath);
62
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
63
+ if (!fs.existsSync(permissionsPath)) fs.writeFileSync(permissionsPath, "export const permissions = {\n admin: [\"wcz-developers\"]\n} as const;");
64
+ addWatchFile(permissionsPath);
65
+ }
66
+ function ensureScopesFile(scopesPath, addWatchFile) {
67
+ const dir = path.dirname(scopesPath);
68
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
69
+ if (!fs.existsSync(scopesPath)) fs.writeFileSync(scopesPath, "export const scopes = {\n} as const;");
70
+ addWatchFile(scopesPath);
71
+ }
72
+ function viteWczLayout() {
73
+ const virtualModuleId = "virtual:wcz-layout";
74
+ const resolvedVirtualModuleId = "\0virtual:wcz-layout";
75
+ let localesPath;
76
+ let permissionsPath;
77
+ let scopesPath;
78
+ let envPath;
79
+ return {
80
+ name: "vite:wcz-layout",
81
+ enforce: "pre",
82
+ configResolved(resolvedConfig) {
83
+ localesPath = path.resolve(resolvedConfig.root, "src/lib/locales");
84
+ permissionsPath = path.resolve(resolvedConfig.root, "src/lib/auth/permissions.ts");
85
+ scopesPath = path.resolve(resolvedConfig.root, "src/lib/auth/scopes.ts");
86
+ envPath = path.resolve(resolvedConfig.root, "src/env.ts");
87
+ },
88
+ async config(_, { command }) {
89
+ await loadVaultSecrets(command);
90
+ return { optimizeDeps: {
91
+ exclude: [virtualModuleId],
92
+ include: [
93
+ "prop-types",
94
+ "react-is",
95
+ "hoist-non-react-statics",
96
+ "url-parse",
97
+ "file-saver",
98
+ "attr-accept"
99
+ ]
100
+ } };
101
+ },
102
+ configureServer(server) {
103
+ const refresh = (filePath) => {
104
+ if (filePath.includes(localesPath) || filePath === permissionsPath || filePath === scopesPath || filePath === envPath) {
105
+ const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId);
106
+ if (module) server.moduleGraph.invalidateModule(module);
107
+ server.ws.send({
108
+ type: "full-reload",
109
+ path: "*"
110
+ });
111
+ }
112
+ };
113
+ server.watcher.add([
114
+ localesPath,
115
+ permissionsPath,
116
+ scopesPath,
117
+ envPath
118
+ ]);
119
+ server.watcher.on("add", refresh);
120
+ server.watcher.on("change", refresh);
121
+ server.watcher.on("unlink", refresh);
122
+ },
123
+ resolveId(id) {
124
+ if (id === virtualModuleId) return resolvedVirtualModuleId;
125
+ return null;
126
+ },
127
+ load(id) {
128
+ if (id !== resolvedVirtualModuleId) return null;
129
+ const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this));
130
+ ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this));
131
+ ensureScopesFile(scopesPath, this.addWatchFile.bind(this));
132
+ const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep);
133
+ const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep);
134
+ const normalizedEnvPath = envPath.split(path.sep).join(path.posix.sep);
135
+ return `
136
+ export const resources = ${JSON.stringify(resources)};
137
+ export { permissions } from "${normalizedPermissionsPath}";
138
+ export { scopes } from "${normalizedScopesPath}";
139
+ export { serverEnv } from "${normalizedEnvPath}";
140
+ `;
141
+ }
142
+ };
143
+ }
144
+ //#endregion
145
+ export { viteWczLayout };
146
+
147
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","names":["z","VaultConfigSchema","object","VAULT_ADDRESS","url","VAULT_USERNAME","string","min","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","default","VaultConfig","infer","fs","https","path","axios","loadEnv","VaultConfigSchema","Resource","Plugin","fetchVaultSecrets","env","Record","Promise","config","parse","VAULT_ADDRESS","VAULT_USERNAME","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","client","create","baseURL","httpsAgent","Agent","rejectUnauthorized","data","loginData","post","password","secretData","get","headers","auth","client_token","secrets","Error","Object","fromEntries","entries","map","key","value","JSON","stringify","loadVaultSecrets","command","process","cwd","forEach","e","console","warn","message","loadLocaleResources","localesPath","addWatchFile","existsSync","mkdirSync","recursive","enPath","join","writeFileSync","files","readdirSync","resources","file","filter","f","endsWith","lang","basename","filePath","translation","readFileSync","ensurePermissionsFile","permissionsPath","dir","dirname","ensureScopesFile","scopesPath","viteWczLayout","virtualModuleId","resolvedVirtualModuleId","envPath","name","enforce","configResolved","resolvedConfig","resolve","root","_","optimizeDeps","exclude","include","configureServer","server","refresh","includes","module","moduleGraph","getModuleById","invalidateModule","ws","send","type","watcher","add","on","resolveId","id","load","bind","normalizedPermissionsPath","split","sep","posix","normalizedScopesPath","normalizedEnvPath"],"sources":["../src/models/VaultConfig.ts","../src/lib/vite-plugin.ts"],"sourcesContent":["import z from \"zod\";\n\nexport const VaultConfigSchema = z.object({\n VAULT_ADDRESS: z.url(),\n VAULT_USERNAME: z.string().min(1),\n VAULT_PASSWORD: z.string().min(1),\n VAULT_SECRET_PATH: z.string().min(1),\n VAULT_MOUNT_POINT: z.string().default(\"release\"),\n});\n\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n","import fs from \"node:fs\";\nimport https from \"node:https\";\nimport path from \"node:path\";\nimport axios from \"axios\";\nimport { loadEnv } from \"vite\";\nimport { VaultConfigSchema } from \"../models/VaultConfig\";\nimport type { Resource } from \"i18next\";\nimport type { Plugin } from \"vite\";\n\nasync function fetchVaultSecrets(env: Record<string, string>): Promise<Record<string, string>> {\n const config = VaultConfigSchema.parse(env);\n const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } =\n config;\n\n const client = axios.create({\n baseURL: VAULT_ADDRESS,\n httpsAgent: new https.Agent({ rejectUnauthorized: false }),\n });\n\n const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, {\n password: VAULT_PASSWORD,\n });\n\n const { data: secretData } = await client.get(\n `/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`,\n {\n headers: { \"X-Vault-Token\": loginData.auth.client_token },\n },\n );\n\n const secrets = secretData?.data?.data;\n if (!secrets) throw new Error(\"No secrets found\");\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, value]) => [\n key,\n typeof value === \"string\" ? value : JSON.stringify(value),\n ]),\n );\n}\n\nasync function loadVaultSecrets(command: string): Promise<void> {\n if (command !== \"serve\") return;\n\n const env = loadEnv(\"development\", process.cwd(), \"\");\n if (!env.VAULT_ADDRESS) return;\n\n try {\n const secrets = await fetchVaultSecrets(env);\n Object.entries(secrets).forEach(([key, value]) => {\n process.env[key] ??= value;\n });\n } catch (e) {\n console.warn(\"[vite:wcz-layout] Vault failed:\", e instanceof Error ? e.message : e);\n }\n}\n\nfunction loadLocaleResources(localesPath: string, addWatchFile: (path: string) => void): Resource {\n if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true });\n\n const enPath = path.join(localesPath, \"en.json\");\n if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({}));\n\n const files = fs.readdirSync(localesPath);\n const resources: Resource = {};\n\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const lang = path.basename(file, \".json\");\n const filePath = path.join(localesPath, file);\n try {\n resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, \"utf-8\")) };\n } catch {\n resources[lang] = { translation: {} };\n }\n addWatchFile(filePath);\n }\n\n return resources;\n}\n\nfunction ensurePermissionsFile(\n permissionsPath: string,\n addWatchFile: (path: string) => void,\n): void {\n const dir = path.dirname(permissionsPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(permissionsPath)) {\n fs.writeFileSync(\n permissionsPath,\n 'export const permissions = {\\n admin: [\"wcz-developers\"]\\n} as const;',\n );\n }\n addWatchFile(permissionsPath);\n}\n\nfunction ensureScopesFile(scopesPath: string, addWatchFile: (path: string) => void): void {\n const dir = path.dirname(scopesPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(scopesPath)) {\n fs.writeFileSync(scopesPath, \"export const scopes = {\\n} as const;\");\n }\n addWatchFile(scopesPath);\n}\n\nexport function viteWczLayout(): Plugin {\n const virtualModuleId = \"virtual:wcz-layout\";\n const resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n let localesPath: string;\n let permissionsPath: string;\n let scopesPath: string;\n let envPath: string;\n\n return {\n name: \"vite:wcz-layout\",\n enforce: \"pre\",\n configResolved(resolvedConfig) {\n localesPath = path.resolve(resolvedConfig.root, \"src/lib/locales\");\n permissionsPath = path.resolve(resolvedConfig.root, \"src/lib/auth/permissions.ts\");\n scopesPath = path.resolve(resolvedConfig.root, \"src/lib/auth/scopes.ts\");\n envPath = path.resolve(resolvedConfig.root, \"src/env.ts\");\n },\n async config(_, { command }) {\n await loadVaultSecrets(command);\n\n return {\n optimizeDeps: {\n exclude: [virtualModuleId],\n include: [\n \"prop-types\",\n \"react-is\",\n \"hoist-non-react-statics\",\n \"url-parse\",\n \"file-saver\",\n \"attr-accept\",\n ],\n },\n };\n },\n configureServer(server) {\n const refresh = (filePath: string) => {\n if (\n filePath.includes(localesPath) ||\n filePath === permissionsPath ||\n filePath === scopesPath ||\n filePath === envPath\n ) {\n const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId);\n if (module) server.moduleGraph.invalidateModule(module);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n }\n };\n\n server.watcher.add([localesPath, permissionsPath, scopesPath, envPath]);\n server.watcher.on(\"add\", refresh);\n server.watcher.on(\"change\", refresh);\n server.watcher.on(\"unlink\", refresh);\n },\n resolveId(id) {\n if (id === virtualModuleId) return resolvedVirtualModuleId;\n return null;\n },\n load(id) {\n if (id !== resolvedVirtualModuleId) return null;\n\n const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this));\n ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this));\n ensureScopesFile(scopesPath, this.addWatchFile.bind(this));\n\n const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep);\n const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep);\n const normalizedEnvPath = envPath.split(path.sep).join(path.posix.sep);\n return `\n export const resources = ${JSON.stringify(resources)};\n export { permissions } from \"${normalizedPermissionsPath}\";\n export { scopes } from \"${normalizedScopesPath}\";\n export { serverEnv } from \"${normalizedEnvPath}\";\n `;\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,62 +1,158 @@
1
- {
2
- "name": "wcz-layout",
3
- "license": "MIT",
4
- "author": "Dalibor Homola",
5
- "version": "6.7.2",
6
- "types": "dist/src/index.d.ts",
7
- "main": "dist/src/index.js",
8
- "module": "dist/src/index.js",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/src/index.d.ts",
12
- "import": "./dist/src/index.js",
13
- "default": "./dist/src/index.js"
14
- }
15
- },
16
- "scripts": {
17
- "npm-install": "npm install",
18
- "npm-update": "npm update",
19
- "analyze": "cem analyze --litelement",
20
- "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
21
- "build": "tsc && npm run analyze -- --exclude dist",
22
- "prepublish": "tsc && npm run analyze -- --exclude dist",
23
- "publish": "npm publish --tag legacy"
24
- },
25
- "dependencies": {
26
- "@azure/msal-browser": "^4.27.0",
27
- "@azure/msal-react": "^3.0.23",
28
- "uuidv7": "^1.0.1",
29
- "axios": "^1.13.2",
30
- "i18next": "^24.2.1",
31
- "i18next-browser-languagedetector": "^8.0.2",
32
- "i18next-http-backend": "^3.0.1",
33
- "react-i18next": "^15.0.1",
34
- "react-number-format": "^5.4.4",
35
- "use-local-storage-state": "^19.4.0",
36
- "zod-i18n-map": "^2.27.0"
37
- },
38
- "devDependencies": {
39
- "@custom-elements-manifest/analyzer": "^0.4.17",
40
- "@web/dev-server": "^0.1.28",
41
- "concurrently": "^5.3.0",
42
- "lit": "^2.0.2",
43
- "tslib": "^2.7.0",
44
- "typescript": "^5.5.4"
45
- },
46
- "peerDependencies": {
47
- "@emotion/react": "11.x",
48
- "@emotion/styled": "11.x",
49
- "@mui/icons-material": "6.x",
50
- "@mui/material": "6.x",
51
- "@mui/x-data-grid-premium": "7.x",
52
- "@mui/x-date-pickers-pro": "7.x",
53
- "@tanstack/react-query": "5.x",
54
- "@tanstack/react-form": "1.x",
55
- "moment": "2.x",
56
- "react": "18.x || 19.x",
57
- "react-dom": "18.x || 19.x",
58
- "react-router-dom": "6.x || 7.x",
59
- "zod": "3.x"
60
- },
61
- "customElements": "custom-elements.json"
62
- }
1
+ {
2
+ "name": "wcz-layout",
3
+ "version": "8.3.2",
4
+ "private": false,
5
+ "keywords": [
6
+ "tanstack-intent"
7
+ ],
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://gitlab.wistron.com/wcz/it-developers/layout/tanstack.git"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "skills",
15
+ "!skills/_artifacts"
16
+ ],
17
+ "type": "module",
18
+ "sideEffects": false,
19
+ "types": "./dist/index.d.ts",
20
+ "typesVersions": {
21
+ "*": {
22
+ "components": [
23
+ "./dist/components.d.ts"
24
+ ],
25
+ "hooks": [
26
+ "./dist/hooks.d.ts"
27
+ ],
28
+ "middleware": [
29
+ "./dist/middleware.d.ts"
30
+ ],
31
+ "models": [
32
+ "./dist/models.d.ts"
33
+ ],
34
+ "data": [
35
+ "./dist/data.d.ts"
36
+ ],
37
+ "data/client": [
38
+ "./dist/data/client.d.ts"
39
+ ],
40
+ "data/server": [
41
+ "./dist/data/server.d.ts"
42
+ ],
43
+ "utils": [
44
+ "./dist/utils.d.ts"
45
+ ],
46
+ "vite": [
47
+ "./dist/vite.d.ts"
48
+ ]
49
+ }
50
+ },
51
+ "exports": {
52
+ ".": {
53
+ "types": "./dist/index.d.ts",
54
+ "import": "./dist/index.js"
55
+ },
56
+ "./components": {
57
+ "types": "./dist/components.d.ts",
58
+ "import": "./dist/components.js"
59
+ },
60
+ "./hooks": {
61
+ "types": "./dist/hooks.d.ts",
62
+ "import": "./dist/hooks.js"
63
+ },
64
+ "./middleware": {
65
+ "types": "./dist/middleware.d.ts",
66
+ "import": "./dist/middleware.js"
67
+ },
68
+ "./models": {
69
+ "types": "./dist/models.d.ts",
70
+ "import": "./dist/models.js"
71
+ },
72
+ "./data": {
73
+ "types": "./dist/data.d.ts",
74
+ "import": "./dist/data.js"
75
+ },
76
+ "./data/client": {
77
+ "types": "./dist/data/client.d.ts",
78
+ "import": "./dist/data/client.js"
79
+ },
80
+ "./data/server": {
81
+ "types": "./dist/data/server.d.ts",
82
+ "import": "./dist/data/server.js"
83
+ },
84
+ "./utils": {
85
+ "types": "./dist/utils.d.ts",
86
+ "import": "./dist/utils.js"
87
+ },
88
+ "./vite": {
89
+ "types": "./dist/vite.d.ts",
90
+ "import": "./dist/vite.js"
91
+ }
92
+ },
93
+ "scripts": {
94
+ "dev": "vp dev",
95
+ "vp:install": "vp install",
96
+ "vp:update": "vp update",
97
+ "ncu:install": "npx npm-check-updates -i",
98
+ "lint:package": "publint",
99
+ "build": "vp pack",
100
+ "prepublishOnly": "npm run build"
101
+ },
102
+ "dependencies": {
103
+ "@azure/msal-browser": "^5.11.0",
104
+ "@azure/msal-node": "^5.2.2",
105
+ "@azure/msal-react": "^5.4.2",
106
+ "@t3-oss/env-core": "^0.13.11",
107
+ "file-saver": "^2.0.5",
108
+ "i18next": "^26.3.0",
109
+ "i18next-browser-languagedetector": "^8.2.1",
110
+ "jose": "^6.2.3",
111
+ "react-dropzone": "^15.0.0",
112
+ "react-i18next": "^17.0.8",
113
+ "react-intersection-observer": "^10.0.3",
114
+ "react-number-format": "^5.4.5",
115
+ "tus-js-client": "^4.3.1",
116
+ "uuidv7": "^1.2.1"
117
+ },
118
+ "devDependencies": {
119
+ "@rolldown/plugin-babel": "^0.2.3",
120
+ "@tanstack/intent": "^0.0.41",
121
+ "@types/file-saver": "^2.0.7",
122
+ "@types/node": "^24.10.13",
123
+ "@types/react": "^19.2.16",
124
+ "@types/react-dom": "^19.2.3",
125
+ "@vitejs/plugin-react": "^6.0.2",
126
+ "babel-plugin-react-compiler": "^1.0.0",
127
+ "nitro": "npm:nitro-nightly@latest",
128
+ "publint": "^0.3.21",
129
+ "typescript": "^6.0.3",
130
+ "vite-plugin-checker": "^0.14.1"
131
+ },
132
+ "peerDependencies": {
133
+ "@emotion/react": "11.x",
134
+ "@emotion/styled": "11.x",
135
+ "@mui/icons-material": "9.x",
136
+ "@mui/material": "9.x",
137
+ "@mui/x-data-grid-premium": "9.x",
138
+ "@mui/x-date-pickers-pro": "9.x",
139
+ "@tanstack/query-db-collection": "1.x",
140
+ "@tanstack/react-db": "0.x",
141
+ "@tanstack/react-form": "1.x",
142
+ "@tanstack/react-query": "5.x",
143
+ "@tanstack/react-router": "1.x",
144
+ "@tanstack/react-router-ssr-query": "1.x",
145
+ "@tanstack/react-start": "1.x",
146
+ "axios": "1.x",
147
+ "dayjs": "1.x",
148
+ "react": "19.x",
149
+ "react-dom": "19.x",
150
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest",
151
+ "vite-plus": "latest",
152
+ "zod": "4.x"
153
+ },
154
+ "overrides": {
155
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest"
156
+ },
157
+ "packageManager": "npm@11.16.0"
158
+ }
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: client-db
3
+ description: "Use when: creating or modifying TanStack DB collections, live queries, optimistic collection writes, subset loading, collection preloading."
4
+ ---
5
+
6
+ ## Rules
7
+
8
+ - Use `eager` syncMode for top-level collections, `on-demand` for child/relational data.
9
+ - Use `useLiveQuery` for list/grid pages and `useLiveSuspenseQuery` for detail components wrapped in suspense.
10
+ - For mutations use `createOptimisticAction` — mirror the server mutation in `onMutate`, then call the server function and `collection.utils.refetch()` in `mutationFn`.
11
+ - Use `meta.loadSubsetOptions` for relational subset loading.
12
+ - Use Axios with auth interceptor `getAccessToken` but only for public REST APIs; use default `api` as a scope key.
13
+
14
+ ## File Placement
15
+
16
+ ```
17
+ src/db-collections/ — DB collections
18
+ src/server/actions/ — server functions (select/update/insert/delete)
19
+ src/lib/schemas/ — Zod schemas (shared between client and server)
20
+ src/lib/auth/scopes.ts — API scope keys
21
+ wcz-layout/data — queryClient instance
22
+ wcz-layout/utils — getAccessToken utility function
23
+ ```
24
+
25
+ ## Examples
26
+
27
+ ```ts
28
+ // src/db-collections/<feature>.ts
29
+ export const api = axios.create({
30
+ baseURL: "/api/libraries",
31
+ });
32
+
33
+ api.interceptors.request.use(async (config) => {
34
+ const accessToken = await getAccessToken("api");
35
+ config.headers.set("Authorization", `Bearer ${accessToken}`);
36
+ return config;
37
+ });
38
+
39
+ // src/db-collections/<feature>.ts
40
+ export const librariesCollection = createCollection(
41
+ queryCollectionOptions({
42
+ queryKey: ["libraries"],
43
+ queryFn: () => selectLibraries(),
44
+ getKey: ({ id }) => id,
45
+ schema: LibrarySchema,
46
+ queryClient: queryClient,
47
+ syncMode: "eager",
48
+ }),
49
+ );
50
+
51
+ // src/db-collections/<feature>.ts
52
+ export const bookCollection = createCollection(
53
+ queryCollectionOptions({
54
+ queryKey: ["books"],
55
+ queryFn: ({ meta }) => selectBooks({ data: meta?.loadSubsetOptions }),
56
+ getKey: ({ id }) => id,
57
+ schema: BookSchema,
58
+ queryClient: queryClient,
59
+ syncMode: "on-demand",
60
+ }),
61
+ );
62
+
63
+ // simple query
64
+ const { data, isLoading } = useLiveQuery((q) =>
65
+ q.from({ library: libraryCollection }).orderBy(({ library }) => library.name, "asc"),
66
+ );
67
+
68
+ // advanced query with relational data
69
+ const { data } = useLiveQuery((q) =>
70
+ q
71
+ .from({ library: libraryCollection })
72
+ .where(({ library }) => eq(library.id, id))
73
+ .findOne()
74
+ .select(({ library }) => ({
75
+ ...library,
76
+ books: toArray(
77
+ q
78
+ .from({ book: bookCollection })
79
+ .where(({ book }) => eq(book.libraryId, library.id))
80
+ .orderBy(({ book }) => book.title, "asc")
81
+ .select(({ book }) => ({
82
+ id: book.id,
83
+ title: book.title,
84
+ })),
85
+ ),
86
+ })),
87
+ );
88
+
89
+ // form submission handler
90
+ const handleOnSubmit = createOptimisticAction<Library>({
91
+ onMutate: (formValues) => {
92
+ libraryCollection.update(id, (prev) => Object.assign(prev, formValues));
93
+ },
94
+ mutationFn: async (formValues) => {
95
+ await updateLibrary({ data: formValues });
96
+ await libraryCollection.utils.refetch();
97
+ },
98
+ });
99
+
100
+ // calling the handler
101
+ try {
102
+ const transaction = handleOnSubmit(formValues);
103
+ await transaction.isPersisted.promise;
104
+ } catch (error) {
105
+ if (error instanceof Error) alert(error.message);
106
+ }
107
+ ```
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: data-grid
3
+ description: "Use when: building or configuring MUI X DataGrid tables, editable columns, toolbar actions, row selection, or TanStack DB-backed grids."
4
+ ---
5
+
6
+ ## Rules
7
+
8
+ - Wrap DataGrid in `Fullscreen` when it is the only content on the page.
9
+ - Type columns as `Array<GridColDef<RowType>>` with the row interface.
10
+ - Use translation for all `headerName` values.
11
+ - Use `rows`, `columns`, `showToolbar`, `loading`, `ignoreDiacritics`, `cellSelection`, and `disableRowSelectionOnClick` on grids.
12
+ - For enums use `type: "singleSelect"` with `{ value, label }` options array used from enumObject.
13
+ - For editable columns, pair `editable: true` with `renderHeader: EditableColumnHeader`.
14
+ - Use `ChipInputCell`, `EditableColumnHeader`, and router button/grid action components from `wcz-layout/components` when they fit.
15
+
16
+ ## File Placement
17
+
18
+ ```
19
+ @mui/x-data-grid-premium — GridColDef, DataGridPremium
20
+ src/db-collections/ - TanStack DB collections to get data
21
+ @tanstack/react-db - useLiveQuery, useLiveSuspenseQuery
22
+ src/server/actions/ - server functions and enums
23
+ wcz-layout/components - ChipInputCell, EditableColumnHeader, Fullscreen
24
+ wcz-layout/hooks - useTranslation
25
+ ```
26
+
27
+ ## Examples
28
+
29
+ ```tsx
30
+ // src/routes/<feature>s/index.tsx
31
+ const { t } = useTranslation();
32
+ const { confirm, alert } = useDialogs();
33
+ const navigate = useNavigate();
34
+ const [cellSelectionModel, setCellSelectionModel] = useState<GridCellSelectionModel>({});
35
+
36
+ const { data, isLoading } = useLiveQuery((q) =>
37
+ q.from({ feature: featureCollection }).orderBy(({ feature }) => feature.name, "asc"),
38
+ );
39
+
40
+ const columns: Array<GridColDef<Feature>> = [
41
+ {
42
+ field: "name",
43
+ headerName: t("Feature.Name"),
44
+ width: 200,
45
+ editable: true,
46
+ renderHeader: EditableColumnHeader,
47
+ },
48
+ {
49
+ field: "tags",
50
+ headerName: t("Feature.Tags"),
51
+ width: 200,
52
+ renderCell: (params) => <ChipInputCell params={params} />,
53
+ },
54
+ {
55
+ field: "status",
56
+ headerName: t("Feature.Status"),
57
+ width: 200,
58
+ type: "singleSelect",
59
+ valueOptions: featureStatusEnum.enumValues.map((status) => ({
60
+ value: status,
61
+ label: t(`FeatureStatus.${status}`),
62
+ })),
63
+ },
64
+ ];
65
+
66
+ const handleOnDelete = createOptimisticAction<Array<string>>({
67
+ onMutate: (ids) => {
68
+ ids.forEach((id) => {
69
+ featureCollection.delete(id);
70
+ });
71
+ },
72
+ mutationFn: async (ids) => {
73
+ deleteFeatures({ data: ids });
74
+ await featureCollection.utils.refetch();
75
+ },
76
+ });
77
+
78
+ return (
79
+ <Fullscreen>
80
+ <DataGridPremium
81
+ rows={data}
82
+ columns={columns}
83
+ showToolbar
84
+ loading={isLoading}
85
+ ignoreDiacritics
86
+ onRowDoubleClick={({ row }) => navigate({ to: "/features/$id", params: { id: row.id } })}
87
+ cellSelection
88
+ disableRowSelectionOnClick
89
+ cellSelectionModel={cellSelectionModel}
90
+ onCellSelectionModelChange={(newModel) => setCellSelectionModel(newModel)}
91
+ slots={{ toolbar: DataGridToolbar }}
92
+ slotProps={{
93
+ toolbar: {
94
+ title: t("Feature.Features"),
95
+ actions: [
96
+ <Tooltip key="create" title={t("Create")}>
97
+ <RouterIconButton to="/features/create">
98
+ <Add fontSize="small" />
99
+ </RouterIconButton>
100
+ </Tooltip>,
101
+ Object.keys(cellSelectionModel).length === 1 && (
102
+ <Tooltip key="edit" title={t("Edit")}>
103
+ <RouterIconButton
104
+ to="/features/edit/$id"
105
+ params={{ id: Object.keys(cellSelectionModel)[0].toString() }}
106
+ >
107
+ <Edit fontSize="small" />
108
+ </RouterIconButton>
109
+ </Tooltip>
110
+ ),
111
+ Object.keys(cellSelectionModel).length > 0 && (
112
+ <Tooltip key="delete" title={t("Delete")}>
113
+ <IconButton
114
+ onClick={async () => {
115
+ const confirmed = await confirm(
116
+ t("DeleteConfirmation", { count: Object.keys(cellSelectionModel).length }),
117
+ );
118
+ if (confirmed) {
119
+ try {
120
+ const transaction = handleOnDelete(
121
+ Object.keys(cellSelectionModel).map((id) => id.toString()),
122
+ );
123
+ await transaction.isPersisted.promise;
124
+ setCellSelectionModel({});
125
+ } catch (error) {
126
+ if (error instanceof Error) await alert(error.message);
127
+ }
128
+ }
129
+ }}
130
+ >
131
+ <Badge
132
+ badgeContent={Object.keys(cellSelectionModel).length}
133
+ invisible={Object.keys(cellSelectionModel).length <= 1}
134
+ color="error"
135
+ >
136
+ <Delete fontSize="small" />
137
+ </Badge>
138
+ </IconButton>
139
+ </Tooltip>
140
+ ),
141
+ ],
142
+ },
143
+ }}
144
+ />
145
+ </Fullscreen>
146
+ );
147
+ ```