ldap-rest 0.0.1

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 (296) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +48 -0
  3. package/bin/cleanup-external-users.mjs +219 -0
  4. package/bin/index.mjs +54 -0
  5. package/bin/sync-james.mjs +190 -0
  6. package/dist/abstract/ldapFlat.js +1 -0
  7. package/dist/abstract/plugin.js +1 -0
  8. package/dist/abstract/twakePlugin.js +1 -0
  9. package/dist/bin/index.js +1 -0
  10. package/dist/config/args.js +1 -0
  11. package/dist/lib/auth/base.js +1 -0
  12. package/dist/lib/authz/base.js +1 -0
  13. package/dist/lib/expressFormatedResponses.js +1 -0
  14. package/dist/lib/ldapActions.js +1 -0
  15. package/dist/lib/parseConfig.js +1 -0
  16. package/dist/lib/utils.js +1 -0
  17. package/dist/logger/winston.js +1 -0
  18. package/dist/plugins/auth/authzLinid1.js +1 -0
  19. package/dist/plugins/auth/authzPerBranch.js +1 -0
  20. package/dist/plugins/auth/crowdsec.js +1 -0
  21. package/dist/plugins/auth/llng.js +1 -0
  22. package/dist/plugins/auth/openidconnect.js +1 -0
  23. package/dist/plugins/auth/rateLimit.js +1 -0
  24. package/dist/plugins/auth/token.js +1 -0
  25. package/dist/plugins/configApi.js +1 -0
  26. package/dist/plugins/demo/helloworld.js +1 -0
  27. package/dist/plugins/ldap/bulkImport.js +1 -0
  28. package/dist/plugins/ldap/departmentSync.js +1 -0
  29. package/dist/plugins/ldap/externalUsersInGroups.js +1 -0
  30. package/dist/plugins/ldap/flatGeneric.js +1 -0
  31. package/dist/plugins/ldap/groups.js +1 -0
  32. package/dist/plugins/ldap/onChange.js +1 -0
  33. package/dist/plugins/ldap/organization.js +1 -0
  34. package/dist/plugins/ldap/trash.js +1 -0
  35. package/dist/plugins/priority.json.js +1 -0
  36. package/dist/plugins/static.js +1 -0
  37. package/dist/plugins/twake/calendarResources.js +1 -0
  38. package/dist/plugins/twake/james.js +1 -0
  39. package/dist/plugins/weblogs.js +1 -0
  40. package/dist/src/abstract/ldapFlat.d.ts +94 -0
  41. package/dist/src/abstract/plugin.d.ts +43 -0
  42. package/dist/src/abstract/twakePlugin.d.ts +90 -0
  43. package/dist/src/bin/index.d.ts +43 -0
  44. package/dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts +31 -0
  45. package/dist/src/browser/ldap-group-editor/api/GroupApiClient.d.ts +23 -0
  46. package/dist/src/browser/ldap-group-editor/components/CreateGroupModal.d.ts +19 -0
  47. package/dist/src/browser/ldap-group-editor/components/GroupPropertyEditor.d.ts +30 -0
  48. package/dist/src/browser/ldap-group-editor/components/GroupTree.d.ts +17 -0
  49. package/dist/src/browser/ldap-group-editor/components/MoveGroupModal.d.ts +20 -0
  50. package/dist/src/browser/ldap-group-editor/index.d.ts +6 -0
  51. package/dist/src/browser/ldap-group-editor/types.d.ts +58 -0
  52. package/dist/src/browser/ldap-resource-editor/api/ResourceApiClient.d.ts +53 -0
  53. package/dist/src/browser/ldap-resource-editor/cache/CacheManager.d.ts +65 -0
  54. package/dist/src/browser/ldap-resource-editor/index.d.ts +6 -0
  55. package/dist/src/browser/ldap-resource-editor/types.d.ts +78 -0
  56. package/dist/src/browser/ldap-tree-viewer/LdapTreeViewer.d.ts +26 -0
  57. package/dist/src/browser/ldap-tree-viewer/api/LdapApiClient.d.ts +30 -0
  58. package/dist/src/browser/ldap-tree-viewer/components/TreeNode.d.ts +17 -0
  59. package/dist/src/browser/ldap-tree-viewer/components/TreeRoot.d.ts +14 -0
  60. package/dist/src/browser/ldap-tree-viewer/index.d.ts +7 -0
  61. package/dist/src/browser/ldap-tree-viewer/store/Store.d.ts +18 -0
  62. package/dist/src/browser/ldap-tree-viewer/store/actions.d.ts +28 -0
  63. package/dist/src/browser/ldap-tree-viewer/store/reducers.d.ts +7 -0
  64. package/dist/src/browser/ldap-tree-viewer/types.d.ts +34 -0
  65. package/dist/src/browser/ldap-unit-editor/LdapUnitEditor.d.ts +27 -0
  66. package/dist/src/browser/ldap-unit-editor/api/UnitApiClient.d.ts +24 -0
  67. package/dist/src/browser/ldap-unit-editor/components/MoveUnitModal.d.ts +28 -0
  68. package/dist/src/browser/ldap-unit-editor/components/UnitPropertyEditor.d.ts +28 -0
  69. package/dist/src/browser/ldap-unit-editor/components/UnitTree.d.ts +18 -0
  70. package/dist/src/browser/ldap-unit-editor/index.d.ts +6 -0
  71. package/dist/src/browser/ldap-unit-editor/types.d.ts +55 -0
  72. package/dist/src/browser/ldap-user-editor/LdapUserEditor.d.ts +32 -0
  73. package/dist/src/browser/ldap-user-editor/api/UserApiClient.d.ts +55 -0
  74. package/dist/src/browser/ldap-user-editor/cache/CacheManager.d.ts +65 -0
  75. package/dist/src/browser/ldap-user-editor/components/MoveUserModal.d.ts +28 -0
  76. package/dist/src/browser/ldap-user-editor/components/PointerField.d.ts +22 -0
  77. package/dist/src/browser/ldap-user-editor/components/UserEditor.d.ts +46 -0
  78. package/dist/src/browser/ldap-user-editor/components/UserList.d.ts +24 -0
  79. package/dist/src/browser/ldap-user-editor/components/UserTree.d.ts +24 -0
  80. package/dist/src/browser/ldap-user-editor/index.d.ts +7 -0
  81. package/dist/src/browser/ldap-user-editor/types.d.ts +67 -0
  82. package/dist/src/browser/shared/components/Modal.d.ts +38 -0
  83. package/dist/src/browser/shared/components/StatusMessage.d.ts +48 -0
  84. package/dist/src/browser/shared/index.d.ts +10 -0
  85. package/dist/src/browser/shared/types/index.d.ts +65 -0
  86. package/dist/src/browser/shared/utils/dom.d.ts +33 -0
  87. package/dist/src/browser/shared/utils/form.d.ts +28 -0
  88. package/dist/src/browser/shared/utils/schema.d.ts +29 -0
  89. package/dist/src/config/args.d.ts +128 -0
  90. package/dist/src/config/schema.d.ts +18 -0
  91. package/dist/src/hooks.d.ts +76 -0
  92. package/dist/src/lib/auth/base.d.ts +9 -0
  93. package/dist/src/lib/authz/base.d.ts +63 -0
  94. package/dist/src/lib/expressFormatedResponses.d.ts +26 -0
  95. package/dist/src/lib/ldapActions.d.ts +91 -0
  96. package/dist/src/lib/parseConfig.d.ts +23 -0
  97. package/dist/src/lib/utils.d.ts +73 -0
  98. package/dist/src/logger/winston.d.ts +3 -0
  99. package/dist/src/plugins/auth/authzLinid1.d.ts +46 -0
  100. package/dist/src/plugins/auth/authzPerBranch.d.ts +59 -0
  101. package/dist/src/plugins/auth/crowdsec.d.ts +29 -0
  102. package/dist/src/plugins/auth/llng.d.ts +8 -0
  103. package/dist/src/plugins/auth/openidconnect.d.ts +11 -0
  104. package/dist/src/plugins/auth/rateLimit.d.ts +24 -0
  105. package/dist/src/plugins/auth/token.d.ts +17 -0
  106. package/dist/src/plugins/configApi.d.ts +24 -0
  107. package/dist/src/plugins/demo/helloworld.d.ts +12 -0
  108. package/dist/src/plugins/ldap/bulkImport.d.ts +48 -0
  109. package/dist/src/plugins/ldap/departmentSync.d.ts +35 -0
  110. package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +21 -0
  111. package/dist/src/plugins/ldap/flatGeneric.d.ts +31 -0
  112. package/dist/src/plugins/ldap/groups.d.ts +95 -0
  113. package/dist/src/plugins/ldap/onChange.d.ts +32 -0
  114. package/dist/src/plugins/ldap/organization.d.ts +65 -0
  115. package/dist/src/plugins/ldap/trash.d.ts +52 -0
  116. package/dist/src/plugins/static.d.ts +7 -0
  117. package/dist/src/plugins/twake/calendarResources.d.ts +31 -0
  118. package/dist/src/plugins/twake/james.d.ts +83 -0
  119. package/dist/src/plugins/weblogs.d.ts +8 -0
  120. package/docs/DEVELOPER_GUIDE.md +298 -0
  121. package/docs/OPENAPI.md +440 -0
  122. package/docs/PLUGIN_DEPENDENCIES.md +612 -0
  123. package/docs/README.md +466 -0
  124. package/docs/api/REFERENCE.md +983 -0
  125. package/docs/api/REST_API.md +1237 -0
  126. package/docs/authentication.md +469 -0
  127. package/docs/authzLinid1.md +521 -0
  128. package/docs/authzPerBranch.md +596 -0
  129. package/docs/browser/LIBRARIES.md +1196 -0
  130. package/docs/examples/EXAMPLES.md +1659 -0
  131. package/docs/examples/twake-mailbox-type-nomenclature.ldif +37 -0
  132. package/docs/examples/twake-mailbox-type-schema-amendment.ldif +30 -0
  133. package/docs/jamesTeamMailboxes.md +343 -0
  134. package/docs/ldapBulkImport.md +722 -0
  135. package/docs/ldapExternalUsersInGroups.md +325 -0
  136. package/docs/ldapFlatGeneric.md +444 -0
  137. package/docs/ldapGroups.md +589 -0
  138. package/docs/ldapOrganizations.md +659 -0
  139. package/docs/ldapTrash.md +260 -0
  140. package/docs/linagora.png +0 -0
  141. package/docs/onChange.md +318 -0
  142. package/docs/plugins/DEVELOPMENT.md +1219 -0
  143. package/docs/presenterm-fr.md +721 -0
  144. package/docs/presenterm.md +721 -0
  145. package/docs/schemas/SCHEMAS.md +1212 -0
  146. package/docs/static.md +410 -0
  147. package/docs/twakeCalendarResources.md +148 -0
  148. package/docs/twakeJames.md +661 -0
  149. package/docs/weblogs.md +399 -0
  150. package/examples/web/ldap-group-editor.html +113 -0
  151. package/examples/web/ldap-tree-viewer.html +368 -0
  152. package/examples/web/ldap-unit-editor.html +108 -0
  153. package/examples/web/ldap-user-editor.html +412 -0
  154. package/package.json +458 -0
  155. package/static/browser/common-demo.css +450 -0
  156. package/static/browser/ldap-group-editor/LdapGroupEditor.js +207 -0
  157. package/static/browser/ldap-group-editor/LdapGroupEditor.js.map +1 -0
  158. package/static/browser/ldap-group-editor/api/GroupApiClient.js +112 -0
  159. package/static/browser/ldap-group-editor/api/GroupApiClient.js.map +1 -0
  160. package/static/browser/ldap-group-editor/components/CreateGroupModal.js +212 -0
  161. package/static/browser/ldap-group-editor/components/CreateGroupModal.js.map +1 -0
  162. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js +497 -0
  163. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js.map +1 -0
  164. package/static/browser/ldap-group-editor/components/GroupTree.js +153 -0
  165. package/static/browser/ldap-group-editor/components/GroupTree.js.map +1 -0
  166. package/static/browser/ldap-group-editor/components/MoveGroupModal.js +235 -0
  167. package/static/browser/ldap-group-editor/components/MoveGroupModal.js.map +1 -0
  168. package/static/browser/ldap-group-editor/index.js +2 -0
  169. package/static/browser/ldap-group-editor/index.js.map +1 -0
  170. package/static/browser/ldap-group-editor/types.js +2 -0
  171. package/static/browser/ldap-group-editor/types.js.map +1 -0
  172. package/static/browser/ldap-group-editor.esm.js +1399 -0
  173. package/static/browser/ldap-group-editor.esm.js.map +1 -0
  174. package/static/browser/ldap-group-editor.js +1407 -0
  175. package/static/browser/ldap-group-editor.js.map +1 -0
  176. package/static/browser/ldap-group-editor.min.js +2 -0
  177. package/static/browser/ldap-group-editor.min.js.map +1 -0
  178. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +226 -0
  179. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -0
  180. package/static/browser/ldap-resource-editor/cache/CacheManager.js +123 -0
  181. package/static/browser/ldap-resource-editor/cache/CacheManager.js.map +1 -0
  182. package/static/browser/ldap-resource-editor/index.js +2 -0
  183. package/static/browser/ldap-resource-editor/index.js.map +1 -0
  184. package/static/browser/ldap-resource-editor/types.js +2 -0
  185. package/static/browser/ldap-resource-editor/types.js.map +1 -0
  186. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js +187 -0
  187. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js.map +1 -0
  188. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js +50 -0
  189. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js.map +1 -0
  190. package/static/browser/ldap-tree-viewer/components/TreeNode.js +140 -0
  191. package/static/browser/ldap-tree-viewer/components/TreeNode.js.map +1 -0
  192. package/static/browser/ldap-tree-viewer/components/TreeRoot.js +98 -0
  193. package/static/browser/ldap-tree-viewer/components/TreeRoot.js.map +1 -0
  194. package/static/browser/ldap-tree-viewer/index.js +2 -0
  195. package/static/browser/ldap-tree-viewer/index.js.map +1 -0
  196. package/static/browser/ldap-tree-viewer/store/Store.js +29 -0
  197. package/static/browser/ldap-tree-viewer/store/Store.js.map +1 -0
  198. package/static/browser/ldap-tree-viewer/store/actions.js +53 -0
  199. package/static/browser/ldap-tree-viewer/store/actions.js.map +1 -0
  200. package/static/browser/ldap-tree-viewer/store/reducers.js +79 -0
  201. package/static/browser/ldap-tree-viewer/store/reducers.js.map +1 -0
  202. package/static/browser/ldap-tree-viewer/types.js +2 -0
  203. package/static/browser/ldap-tree-viewer/types.js.map +1 -0
  204. package/static/browser/ldap-tree-viewer.css +2 -0
  205. package/static/browser/ldap-tree-viewer.css.map +1 -0
  206. package/static/browser/ldap-tree-viewer.esm.js +606 -0
  207. package/static/browser/ldap-tree-viewer.esm.js.map +1 -0
  208. package/static/browser/ldap-tree-viewer.js +614 -0
  209. package/static/browser/ldap-tree-viewer.js.map +1 -0
  210. package/static/browser/ldap-tree-viewer.min.js +2 -0
  211. package/static/browser/ldap-tree-viewer.min.js.map +1 -0
  212. package/static/browser/ldap-unit-editor/LdapUnitEditor.js +119 -0
  213. package/static/browser/ldap-unit-editor/LdapUnitEditor.js.map +1 -0
  214. package/static/browser/ldap-unit-editor/api/UnitApiClient.js +95 -0
  215. package/static/browser/ldap-unit-editor/api/UnitApiClient.js.map +1 -0
  216. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js +295 -0
  217. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js.map +1 -0
  218. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js +321 -0
  219. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js.map +1 -0
  220. package/static/browser/ldap-unit-editor/components/UnitTree.js +197 -0
  221. package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -0
  222. package/static/browser/ldap-unit-editor/index.js +2 -0
  223. package/static/browser/ldap-unit-editor/index.js.map +1 -0
  224. package/static/browser/ldap-unit-editor/types.js +2 -0
  225. package/static/browser/ldap-unit-editor/types.js.map +1 -0
  226. package/static/browser/ldap-unit-editor.esm.js +1013 -0
  227. package/static/browser/ldap-unit-editor.esm.js.map +1 -0
  228. package/static/browser/ldap-unit-editor.js +1021 -0
  229. package/static/browser/ldap-unit-editor.js.map +1 -0
  230. package/static/browser/ldap-unit-editor.min.js +2 -0
  231. package/static/browser/ldap-unit-editor.min.js.map +1 -0
  232. package/static/browser/ldap-user-editor/LdapUserEditor.js +184 -0
  233. package/static/browser/ldap-user-editor/LdapUserEditor.js.map +1 -0
  234. package/static/browser/ldap-user-editor/api/UserApiClient.js +209 -0
  235. package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -0
  236. package/static/browser/ldap-user-editor/cache/CacheManager.js +123 -0
  237. package/static/browser/ldap-user-editor/cache/CacheManager.js.map +1 -0
  238. package/static/browser/ldap-user-editor/components/MoveUserModal.js +302 -0
  239. package/static/browser/ldap-user-editor/components/MoveUserModal.js.map +1 -0
  240. package/static/browser/ldap-user-editor/components/PointerField.js +152 -0
  241. package/static/browser/ldap-user-editor/components/PointerField.js.map +1 -0
  242. package/static/browser/ldap-user-editor/components/UserEditor.js +608 -0
  243. package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -0
  244. package/static/browser/ldap-user-editor/components/UserList.js +181 -0
  245. package/static/browser/ldap-user-editor/components/UserList.js.map +1 -0
  246. package/static/browser/ldap-user-editor/components/UserTree.js +164 -0
  247. package/static/browser/ldap-user-editor/components/UserTree.js.map +1 -0
  248. package/static/browser/ldap-user-editor/index.js +2 -0
  249. package/static/browser/ldap-user-editor/index.js.map +1 -0
  250. package/static/browser/ldap-user-editor/types.js +2 -0
  251. package/static/browser/ldap-user-editor/types.js.map +1 -0
  252. package/static/browser/ldap-user-editor.css +2 -0
  253. package/static/browser/ldap-user-editor.css.map +1 -0
  254. package/static/browser/ldap-user-editor.esm.js +1897 -0
  255. package/static/browser/ldap-user-editor.esm.js.map +1 -0
  256. package/static/browser/ldap-user-editor.js +1905 -0
  257. package/static/browser/ldap-user-editor.js.map +1 -0
  258. package/static/browser/ldap-user-editor.min.js +2 -0
  259. package/static/browser/ldap-user-editor.min.js.map +1 -0
  260. package/static/browser/shared/components/Modal.js +121 -0
  261. package/static/browser/shared/components/Modal.js.map +1 -0
  262. package/static/browser/shared/components/StatusMessage.js +119 -0
  263. package/static/browser/shared/components/StatusMessage.js.map +1 -0
  264. package/static/browser/shared/index.js +7 -0
  265. package/static/browser/shared/index.js.map +1 -0
  266. package/static/browser/shared/types/index.js +37 -0
  267. package/static/browser/shared/types/index.js.map +1 -0
  268. package/static/browser/shared/utils/dom.js +78 -0
  269. package/static/browser/shared/utils/dom.js.map +1 -0
  270. package/static/browser/shared/utils/form.js +234 -0
  271. package/static/browser/shared/utils/form.js.map +1 -0
  272. package/static/browser/shared/utils/schema.js +121 -0
  273. package/static/browser/shared/utils/schema.js.map +1 -0
  274. package/static/browser/shared.esm.js +694 -0
  275. package/static/browser/shared.esm.js.map +1 -0
  276. package/static/browser/shared.js +723 -0
  277. package/static/browser/shared.js.map +1 -0
  278. package/static/browser/shared.min.js +2 -0
  279. package/static/browser/shared.min.js.map +1 -0
  280. package/static/schemas/ad/computers.json +92 -0
  281. package/static/schemas/ad/groups.json +55 -0
  282. package/static/schemas/ad/organizations.json +66 -0
  283. package/static/schemas/ad/users.json +116 -0
  284. package/static/schemas/standard/devices.json +72 -0
  285. package/static/schemas/standard/groups.json +54 -0
  286. package/static/schemas/standard/organizations.json +49 -0
  287. package/static/schemas/standard/users.json +86 -0
  288. package/static/schemas/twake/groups.json +75 -0
  289. package/static/schemas/twake/nomenclature/twakeAccountStatus.json +31 -0
  290. package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +31 -0
  291. package/static/schemas/twake/nomenclature/twakeListType.json +31 -0
  292. package/static/schemas/twake/nomenclature/twakeMailboxType.json +31 -0
  293. package/static/schemas/twake/nomenclature/twakeTitle.json +31 -0
  294. package/static/schemas/twake/organizations.json +52 -0
  295. package/static/schemas/twake/positions.json +32 -0
  296. package/static/schemas/twake/users.json +112 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * LDAP User Editor - User List Component
3
+ * Shows users in a selected organization
4
+ */
5
+ class UserList {
6
+ constructor(container, api, orgDn, onSelectUser) {
7
+ this.users = [];
8
+ this.searchQuery = '';
9
+ this.schema = null;
10
+ this.config = null;
11
+ this.container = container;
12
+ this.api = api;
13
+ this.orgDn = orgDn;
14
+ this.onSelectUser = onSelectUser;
15
+ }
16
+ async init() {
17
+ // Load config and schema first
18
+ this.config = await this.api.getConfig();
19
+ const usersResource = this.config.features?.ldapFlatGeneric?.flatResources?.find(r => r.pluralName === 'users' || r.name === 'users');
20
+ if (usersResource?.schemaUrl) {
21
+ this.schema = await this.api.getSchema(usersResource.schemaUrl);
22
+ }
23
+ this.render();
24
+ await this.loadUsers();
25
+ }
26
+ render() {
27
+ this.container.innerHTML = `
28
+ <div class="user-list-container">
29
+ <div class="user-list-header">
30
+ <h2>
31
+ <span class="material-icons">people</span>
32
+ Users
33
+ </h2>
34
+ <div class="search-box">
35
+ <span class="material-icons">search</span>
36
+ <input
37
+ type="text"
38
+ placeholder="Search users in this organization..."
39
+ id="user-list-search-input"
40
+ />
41
+ </div>
42
+ </div>
43
+ <div class="user-list" id="user-list-items">
44
+ <div class="loading">
45
+ <div class="spinner"></div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ `;
50
+ const searchInput = this.container.querySelector('#user-list-search-input');
51
+ searchInput?.addEventListener('input', e => {
52
+ this.searchQuery = e.target.value;
53
+ this.renderUserList();
54
+ });
55
+ }
56
+ async loadUsers() {
57
+ const listEl = this.container.querySelector('#user-list-items');
58
+ if (!listEl)
59
+ return;
60
+ try {
61
+ listEl.innerHTML =
62
+ '<div class="loading"><div class="spinner"></div></div>';
63
+ // Use organization subnodes API to get users in this org
64
+ // Filter by the first objectClass from schema to get only users (not groups/OUs)
65
+ const baseUrl = this.api['baseUrl'] || window.location.origin;
66
+ const objectClass = this.schema?.entity?.objectClass?.[1] || 'twakeAccount'; // Use second objectClass (not 'top')
67
+ const res = await fetch(`${baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(this.orgDn)}/subnodes?objectClass=${encodeURIComponent(objectClass)}`);
68
+ if (!res.ok)
69
+ throw new Error('Failed to fetch organization users');
70
+ const items = (await res.json());
71
+ // Filter only user entries using schema objectClass
72
+ // An item is a user if it has ALL the expected objectClasses
73
+ const expectedObjectClasses = this.schema?.entity?.objectClass || [];
74
+ const mainAttribute = this.schema?.entity?.mainAttribute || '';
75
+ this.users = items.filter(item => {
76
+ const objectClass = Array.isArray(item.objectClass)
77
+ ? item.objectClass
78
+ : [item.objectClass];
79
+ // Must have the mainAttribute field (uid, sAMAccountName, etc.)
80
+ if (!item[mainAttribute])
81
+ return false;
82
+ // Check if item has ALL the expected objectClasses
83
+ return expectedObjectClasses.every(expected => objectClass.includes(expected));
84
+ });
85
+ this.renderUserList();
86
+ }
87
+ catch (error) {
88
+ console.error('Failed to load users:', error);
89
+ listEl.innerHTML =
90
+ '<div class="empty-state"><span class="material-icons">error</span><p>Failed to load users</p></div>';
91
+ }
92
+ }
93
+ getFirstValue(value) {
94
+ if (!value)
95
+ return '';
96
+ if (Array.isArray(value))
97
+ return value[0] || '';
98
+ return String(value);
99
+ }
100
+ getFieldNameByRole(role) {
101
+ if (!this.schema)
102
+ return null;
103
+ const field = Object.entries(this.schema.attributes).find(([, attr]) => attr.role === role);
104
+ return field ? field[0] : null;
105
+ }
106
+ getFieldValueByRole(user, role) {
107
+ const fieldName = this.getFieldNameByRole(role);
108
+ if (!fieldName)
109
+ return '';
110
+ return this.getFirstValue(user[fieldName]);
111
+ }
112
+ renderUserList() {
113
+ const listEl = this.container.querySelector('#user-list-items');
114
+ if (!listEl)
115
+ return;
116
+ // Get field names from schema roles
117
+ const displayNameField = this.getFieldNameByRole('displayName');
118
+ const identifierField = this.schema?.entity?.mainAttribute || '';
119
+ const emailField = this.getFieldNameByRole('primaryEmail');
120
+ // Filter users by search query
121
+ const filteredUsers = this.searchQuery
122
+ ? this.users.filter(user => {
123
+ const displayName = displayNameField
124
+ ? this.getFirstValue(user[displayNameField]).toLowerCase()
125
+ : '';
126
+ const identifier = this.getFirstValue(user[identifierField]).toLowerCase();
127
+ const email = emailField
128
+ ? this.getFirstValue(user[emailField]).toLowerCase()
129
+ : '';
130
+ const query = this.searchQuery.toLowerCase();
131
+ return (displayName.includes(query) ||
132
+ identifier.includes(query) ||
133
+ email.includes(query));
134
+ })
135
+ : this.users;
136
+ if (filteredUsers.length === 0) {
137
+ listEl.innerHTML =
138
+ '<div class="empty-state"><span class="material-icons">person_search</span><p>No users found</p></div>';
139
+ return;
140
+ }
141
+ listEl.innerHTML = filteredUsers
142
+ .map(user => {
143
+ const displayName = displayNameField
144
+ ? this.getFirstValue(user[displayNameField])
145
+ : '';
146
+ const identifier = this.getFirstValue(user[identifierField]);
147
+ const email = emailField ? this.getFirstValue(user[emailField]) : '';
148
+ const name = displayName || identifier || 'Unknown';
149
+ return `
150
+ <div
151
+ class="tree-node"
152
+ data-dn="${user.dn}"
153
+ >
154
+ <span class="material-icons">person</span>
155
+ <div class="tree-node-content">
156
+ <div class="tree-node-name">
157
+ ${name}
158
+ </div>
159
+ ${email ? `<div class="tree-node-email">${email}</div>` : ''}
160
+ </div>
161
+ </div>
162
+ `;
163
+ })
164
+ .join('');
165
+ // Add click handlers
166
+ listEl.querySelectorAll('.tree-node').forEach(node => {
167
+ node.addEventListener('click', () => {
168
+ const dn = node.getAttribute('data-dn');
169
+ if (dn) {
170
+ this.onSelectUser(dn);
171
+ }
172
+ });
173
+ });
174
+ }
175
+ async refresh() {
176
+ await this.loadUsers();
177
+ }
178
+ }
179
+
180
+ export { UserList };
181
+ //# sourceMappingURL=UserList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserList.js","sources":["../../../../../src/browser/ldap-user-editor/components/UserList.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ import { CacheManager } from '../cache/CacheManager.js';
2
+
3
+ /**
4
+ * LDAP User Editor - Organization Tree Component
5
+ * Shows only LDAP organization tree (filters out users/groups)
6
+ */
7
+ class UserTree {
8
+ constructor(container, baseUrl, onSelectOrg) {
9
+ this.expandedNodes = new Set();
10
+ this.selectedDn = null;
11
+ this.rootDn = null;
12
+ this.container = container;
13
+ this.baseUrl = baseUrl;
14
+ this.onSelectOrg = onSelectOrg;
15
+ this.cache = new CacheManager();
16
+ // Clean expired entries every 5 minutes
17
+ window.setInterval(() => this.cache.cleanExpired(), 5 * 60 * 1000);
18
+ }
19
+ /**
20
+ * Fetch with cache support
21
+ */
22
+ async cachedFetch(url) {
23
+ const cached = this.cache.get(url);
24
+ if (cached !== null) {
25
+ return cached;
26
+ }
27
+ const res = await fetch(url);
28
+ if (!res.ok) {
29
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
30
+ }
31
+ const data = (await res.json());
32
+ this.cache.set(url, data);
33
+ return data;
34
+ }
35
+ async init() {
36
+ this.container.innerHTML = `
37
+ <div class="sidebar">
38
+ <div class="sidebar-header">
39
+ <h2>
40
+ <span class="material-icons">account_tree</span>
41
+ Organizations
42
+ </h2>
43
+ </div>
44
+ <div id="org-tree-viewer" class="user-tree">
45
+ <div class="loading"><div class="spinner"></div></div>
46
+ </div>
47
+ </div>
48
+ `;
49
+ try {
50
+ // Load top organization
51
+ const topOrg = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/top`);
52
+ this.rootDn = topOrg.dn;
53
+ await this.renderTree();
54
+ }
55
+ catch (error) {
56
+ console.error('Failed to init tree:', error);
57
+ const treeEl = this.container.querySelector('#org-tree-viewer');
58
+ if (treeEl) {
59
+ treeEl.innerHTML =
60
+ '<div class="empty-state"><span class="material-icons">error</span><p>Failed to load organization tree</p></div>';
61
+ }
62
+ }
63
+ }
64
+ async renderTree() {
65
+ const treeEl = this.container.querySelector('#org-tree-viewer');
66
+ if (!treeEl || !this.rootDn)
67
+ return;
68
+ try {
69
+ const html = await this.renderNode(this.rootDn, 0);
70
+ treeEl.innerHTML = html;
71
+ this.attachEventListeners();
72
+ }
73
+ catch (error) {
74
+ console.error('Failed to render tree:', error);
75
+ treeEl.innerHTML =
76
+ '<div class="empty-state"><span class="material-icons">error</span><p>Error rendering tree</p></div>';
77
+ }
78
+ }
79
+ async renderNode(dn, level) {
80
+ const isExpanded = this.expandedNodes.has(dn);
81
+ const isSelected = this.selectedDn === dn;
82
+ const indent = level * 20;
83
+ // Get node info
84
+ const node = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(dn)}`);
85
+ // Extract display name - handle both string and array
86
+ let displayName = dn;
87
+ if (node.ou) {
88
+ displayName = Array.isArray(node.ou) ? node.ou[0] : node.ou;
89
+ }
90
+ else if (node.cn) {
91
+ displayName = Array.isArray(node.cn) ? node.cn[0] : node.cn;
92
+ }
93
+ let html = `
94
+ <div class="tree-node ${isSelected ? 'active' : ''}" style="padding-left: ${indent}px">
95
+ <span class="material-icons tree-node-toggle" data-dn="${dn}">
96
+ ${isExpanded ? 'expand_more' : 'chevron_right'}
97
+ </span>
98
+ <span class="material-icons">business</span>
99
+ <span class="tree-node-label" data-dn="${dn}">${displayName}</span>
100
+ </div>
101
+ `;
102
+ if (isExpanded) {
103
+ try {
104
+ // Load subnodes and filter only organizations
105
+ const subnodes = await this.cachedFetch(`${this.baseUrl}/api/v1/ldap/organizations/${encodeURIComponent(dn)}/subnodes`);
106
+ const orgs = subnodes.filter((n) => {
107
+ const classes = Array.isArray(n.objectClass)
108
+ ? n.objectClass
109
+ : n.objectClass
110
+ ? [n.objectClass]
111
+ : [];
112
+ return (classes.includes('organizationalUnit') ||
113
+ classes.includes('organization'));
114
+ });
115
+ for (const subnode of orgs) {
116
+ html += await this.renderNode(subnode.dn, level + 1);
117
+ }
118
+ }
119
+ catch (error) {
120
+ console.error('Failed to load subnodes for', dn, error);
121
+ }
122
+ }
123
+ return html;
124
+ }
125
+ attachEventListeners() {
126
+ // Toggle expand/collapse
127
+ this.container.querySelectorAll('.tree-node-toggle').forEach(el => {
128
+ el.addEventListener('click', async (e) => {
129
+ e.stopPropagation();
130
+ const dn = el.getAttribute('data-dn');
131
+ if (!dn)
132
+ return;
133
+ if (this.expandedNodes.has(dn)) {
134
+ this.expandedNodes.delete(dn);
135
+ }
136
+ else {
137
+ this.expandedNodes.add(dn);
138
+ }
139
+ await this.renderTree();
140
+ });
141
+ });
142
+ // Select organization
143
+ this.container.querySelectorAll('.tree-node-label').forEach(el => {
144
+ el.addEventListener('click', e => {
145
+ e.stopPropagation();
146
+ const dn = el.getAttribute('data-dn');
147
+ if (!dn)
148
+ return;
149
+ this.selectedDn = dn;
150
+ this.renderTree();
151
+ this.onSelectOrg(dn);
152
+ });
153
+ });
154
+ }
155
+ async refresh() {
156
+ await this.renderTree();
157
+ }
158
+ destroy() {
159
+ this.container.innerHTML = '';
160
+ }
161
+ }
162
+
163
+ export { UserTree };
164
+ //# sourceMappingURL=UserTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserTree.js","sources":["../../../../../src/browser/ldap-user-editor/components/UserTree.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { LdapUserEditor } from './LdapUserEditor.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ :root{--primary-color:#6200ee;--primary-dark:#3700b3;--success-color:#2e7d32;--error-color:#c62828;--bg-color:#f8fafc;--surface-color:#fff;--text-primary:#1e293b;--text-secondary:#64748b;--border-color:#e2e8f0}.ldap-user-editor{color:var(--text-primary);font-family:Roboto,sans-serif;line-height:1.6;min-width:0;width:100%}.editor-layout{display:grid;gap:24px;grid-template-columns:minmax(300px,1fr) minmax(300px,2fr)}@media (max-width:900px){.editor-layout{grid-template-columns:1fr}}.demo-panel{background:#fff;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,.1);max-height:800px;min-width:0;overflow:auto;padding:24px}.demo-panel h2{align-items:center;color:#333;display:flex;font-size:20px;font-weight:500;gap:8px;margin-bottom:16px}.demo-panel h2 .material-icons{color:var(--primary-color)}.sidebar{display:flex;flex-direction:column;height:100%;min-width:0;width:100%}.sidebar-header{border-bottom:1px solid var(--border-color);margin-bottom:1rem;padding-bottom:1rem}.sidebar-header h2{align-items:center;color:var(--text-primary);display:flex;font-size:1rem;font-weight:600;gap:.5rem;margin-bottom:.75rem}.search-box{position:relative}.search-box input{border:1px solid var(--border-color);border-radius:.5rem;font-size:.875rem;padding:.625rem .75rem .625rem 2.5rem;transition:all .2s;width:100%}.search-box input:focus{border-color:var(--primary-color);box-shadow:0 0 0 3px rgba(99,102,241,.1);outline:none}.search-box .material-icons{color:var(--text-secondary);font-size:1.25rem;left:.75rem;position:absolute;top:50%;transform:translateY(-50%)}.user-tree{flex:1;min-width:0;overflow-y:auto;width:100%}.tree-node{align-items:center;border-radius:.375rem;cursor:pointer;display:flex;gap:.5rem;margin:.125rem 0;min-width:0;padding:.5rem;transition:all .15s}.tree-node-toggle{color:var(--text-secondary);cursor:pointer;flex-shrink:0;font-size:1.25rem;height:24px;user-select:none;width:24px}.tree-node-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.user-list-container{display:flex;flex-direction:column;height:100%}.user-list-header{border-bottom:1px solid var(--border-color);margin-bottom:1rem;padding-bottom:1rem}.user-list-header h2{align-items:center;color:var(--text-primary);display:flex;font-size:1rem;font-weight:600;gap:.5rem;margin-bottom:.75rem}.user-list{flex:1;overflow-y:auto}.tree-node:hover{background:var(--bg-color)}.tree-node.active{background:rgba(98,0,238,.1);color:var(--primary-color);font-weight:500}.tree-node .material-icons{color:var(--text-secondary);flex-shrink:0;font-size:1.25rem;height:24px;width:24px}.tree-node.active .material-icons{color:var(--primary-color)}.tree-node-content{display:flex;flex:1;flex-direction:column;min-width:0}.tree-node-name{font-size:.875rem;font-weight:500}.tree-node-email,.tree-node-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tree-node-email{color:var(--text-secondary);font-size:.75rem}.empty-state{align-items:center;color:#999;display:flex;flex-direction:column;justify-content:center;min-height:400px;text-align:center}.empty-state .material-icons{color:#ddd;font-size:48px;margin-bottom:8px}.empty-state p{font-size:1rem;font-style:italic}.editor-container{width:100%}.editor-header{align-items:center;border-bottom:2px solid #f0f0f0;display:flex;gap:12px;margin-bottom:16px;padding-bottom:12px}.editor-header .material-icons{color:#42a5f5;font-size:32px}.editor-title h3{color:#333;font-size:18px;font-weight:500}.editor-title .dn{color:#999;font-size:11px;margin-top:4px}.editor-form{padding:0}.form-section{margin-bottom:2rem}.form-section:last-child{margin-bottom:0}.form-section-title{border-bottom:2px solid var(--border-color);color:var(--text-primary);font-size:1rem;font-weight:600;margin-bottom:1rem;padding-bottom:.5rem}.form-row{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));margin-bottom:1.5rem}.form-group{display:flex;flex-direction:column}.form-label{align-items:center;color:var(--text-primary);display:flex;font-size:.875rem;font-weight:500;gap:.25rem;margin-bottom:.5rem}.form-label .required{color:var(--error-color)}.form-input,.form-select{border:1px solid var(--border-color);border-radius:.5rem;font-family:inherit;font-size:.875rem;padding:.625rem .75rem;transition:all .2s}.form-input:focus,.form-select:focus{border-color:var(--primary-color);box-shadow:0 0 0 3px rgba(98,0,238,.1);outline:none}.form-input:disabled,.form-select:disabled{background:var(--bg-color);color:var(--text-secondary);cursor:not-allowed}.array-field{flex-direction:column}.array-field,.array-item{display:flex;gap:.5rem}.array-item input,.array-item select{flex:1}.btn{align-items:center;background:var(--primary-color);border:none;border-radius:4px;color:#fff;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:.5rem;letter-spacing:.5px;padding:10px 20px;text-transform:uppercase;transition:background .2s}.btn:hover:not(:disabled){background:var(--primary-dark)}.btn-secondary{background:#ccc;color:#333}.btn-secondary:hover:not(:disabled){background:#aaa}.btn:disabled{background:#ccc;cursor:not-allowed}.btn-icon{align-items:center;display:inline-flex;height:2.5rem;justify-content:center;padding:.5rem;width:2.5rem}.btn-icon .material-icons{font-size:1.25rem}.editor-actions{display:flex;gap:.75rem}.alert{align-items:center;border-radius:4px;display:flex;gap:8px;margin-bottom:16px;padding:12px 16px}.alert-success{background:#e8f5e9;color:var(--success-color)}.alert-error{background:#ffebee;color:var(--error-color)}.alert .material-icons{font-size:20px}.loading{color:var(--text-secondary);padding:3rem;text-align:center}.spinner{animation:spin .8s linear infinite;border:3px solid var(--border-color);border-radius:50%;border-top-color:var(--primary-color);display:inline-block;height:2rem;width:2rem}@keyframes spin{to{transform:rotate(1turn)}}.modal-overlay{align-items:center;background-color:rgba(0,0,0,.5);bottom:0;display:none;justify-content:center;left:0;padding:1rem;position:fixed;right:0;top:0;z-index:1000}.modal-overlay.active{display:flex}.modal-container{background:#fff;border-radius:8px;box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);display:flex;flex-direction:column;max-height:90vh;max-width:500px;width:100%}.modal-header{align-items:center;border-bottom:1px solid var(--border-color);display:flex;justify-content:space-between;padding:1.5rem}.modal-header h3{font-size:1.25rem;font-weight:600;margin:0}.modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--text-secondary);cursor:pointer;display:flex;justify-content:center;padding:.5rem;transition:background-color .2s}.modal-close:hover{background-color:var(--bg-color)}.modal-body{flex:1;overflow-y:auto;padding:1.5rem}.modal-footer{border-top:1px solid var(--border-color);display:flex;gap:.75rem;justify-content:flex-end;padding:1rem 1.5rem}
2
+ /*# sourceMappingURL=ldap-user-editor.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["styles.css"],"names":[],"mappings":"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","file":"ldap-user-editor.css","sourcesContent":["/**\n * LDAP User Editor - Styles\n */\n\n:root {\n --primary-color: #6200ee;\n --primary-dark: #3700b3;\n --success-color: #2e7d32;\n --error-color: #c62828;\n --bg-color: #f8fafc;\n --surface-color: #ffffff;\n --text-primary: #1e293b;\n --text-secondary: #64748b;\n --border-color: #e2e8f0;\n}\n\n.ldap-user-editor {\n font-family: 'Roboto', sans-serif;\n color: var(--text-primary);\n line-height: 1.6;\n width: 100%;\n min-width: 0;\n}\n\n.editor-layout {\n display: grid;\n grid-template-columns: minmax(300px, 1fr) minmax(300px, 2fr);\n gap: 24px;\n}\n\n@media (max-width: 900px) {\n .editor-layout {\n grid-template-columns: 1fr;\n }\n}\n\n.demo-panel {\n background: white;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n overflow: auto;\n max-height: 800px;\n min-width: 0;\n}\n\n.demo-panel h2 {\n font-size: 20px;\n font-weight: 500;\n margin-bottom: 16px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.demo-panel h2 .material-icons {\n color: var(--primary-color);\n}\n\n/* Sidebar */\n.sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n min-width: 0;\n}\n\n.sidebar-header {\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border-color);\n margin-bottom: 1rem;\n}\n\n.sidebar-header h2 {\n font-size: 1rem;\n font-weight: 600;\n color: var(--text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.75rem;\n}\n\n.search-box {\n position: relative;\n}\n\n.search-box input {\n width: 100%;\n padding: 0.625rem 0.75rem 0.625rem 2.5rem;\n border: 1px solid var(--border-color);\n border-radius: 0.5rem;\n font-size: 0.875rem;\n transition: all 0.2s;\n}\n\n.search-box input:focus {\n outline: none;\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.search-box .material-icons {\n position: absolute;\n left: 0.75rem;\n top: 50%;\n transform: translateY(-50%);\n font-size: 1.25rem;\n color: var(--text-secondary);\n}\n\n.user-tree {\n flex: 1;\n overflow-y: auto;\n width: 100%;\n min-width: 0;\n}\n\n.tree-node {\n padding: 0.5rem;\n margin: 0.125rem 0;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n}\n\n.tree-node-toggle {\n cursor: pointer;\n font-size: 1.25rem;\n color: var(--text-secondary);\n user-select: none;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n}\n\n.tree-node-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.user-list-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.user-list-header {\n margin-bottom: 1rem;\n padding-bottom: 1rem;\n border-bottom: 1px solid var(--border-color);\n}\n\n.user-list-header h2 {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--text-primary);\n margin-bottom: 0.75rem;\n}\n\n.user-list {\n flex: 1;\n overflow-y: auto;\n}\n\n.tree-node:hover {\n background: var(--bg-color);\n}\n\n.tree-node.active {\n background: rgba(98, 0, 238, 0.1);\n color: var(--primary-color);\n font-weight: 500;\n}\n\n.tree-node .material-icons {\n font-size: 1.25rem;\n color: var(--text-secondary);\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n}\n\n.tree-node.active .material-icons {\n color: var(--primary-color);\n}\n\n.tree-node-content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n}\n\n.tree-node-name {\n font-size: 0.875rem;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tree-node-email {\n font-size: 0.75rem;\n color: var(--text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Empty state */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n color: #999;\n text-align: center;\n}\n\n.empty-state .material-icons {\n font-size: 48px;\n color: #ddd;\n margin-bottom: 8px;\n}\n\n.empty-state p {\n font-size: 1rem;\n font-style: italic;\n}\n\n/* Editor */\n.editor-container {\n width: 100%;\n}\n\n.editor-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n padding-bottom: 12px;\n border-bottom: 2px solid #f0f0f0;\n}\n\n.editor-header .material-icons {\n font-size: 32px;\n color: #42a5f5;\n}\n\n.editor-title h3 {\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n\n.editor-title .dn {\n font-size: 11px;\n color: #999;\n margin-top: 4px;\n}\n\n/* Form */\n.editor-form {\n padding: 0;\n}\n\n.form-section {\n margin-bottom: 2rem;\n}\n\n.form-section:last-child {\n margin-bottom: 0;\n}\n\n.form-section-title {\n font-size: 1rem;\n font-weight: 600;\n margin-bottom: 1rem;\n color: var(--text-primary);\n padding-bottom: 0.5rem;\n border-bottom: 2px solid var(--border-color);\n}\n\n.form-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 1.5rem;\n}\n\n.form-group {\n display: flex;\n flex-direction: column;\n}\n\n.form-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--text-primary);\n margin-bottom: 0.5rem;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.form-label .required {\n color: var(--error-color);\n}\n\n.form-input,\n.form-select {\n padding: 0.625rem 0.75rem;\n border: 1px solid var(--border-color);\n border-radius: 0.5rem;\n font-size: 0.875rem;\n font-family: inherit;\n transition: all 0.2s;\n}\n\n.form-input:focus,\n.form-select:focus {\n outline: none;\n border-color: var(--primary-color);\n box-shadow: 0 0 0 3px rgba(98, 0, 238, 0.1);\n}\n\n.form-input:disabled,\n.form-select:disabled {\n background: var(--bg-color);\n color: var(--text-secondary);\n cursor: not-allowed;\n}\n\n/* Array fields */\n.array-field {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.array-item {\n display: flex;\n gap: 0.5rem;\n}\n\n.array-item input,\n.array-item select {\n flex: 1;\n}\n\n/* Buttons */\n.btn {\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n background: var(--primary-color);\n color: white;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n transition: background 0.2s;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--primary-dark);\n}\n\n.btn-secondary {\n background: #ccc;\n color: #333;\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: #aaa;\n}\n\n.btn:disabled {\n background: #ccc;\n cursor: not-allowed;\n}\n\n.btn-icon {\n padding: 0.5rem;\n width: 2.5rem;\n height: 2.5rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.btn-icon .material-icons {\n font-size: 1.25rem;\n}\n\n.editor-actions {\n display: flex;\n gap: 0.75rem;\n}\n\n/* Alerts */\n.alert {\n padding: 12px 16px;\n border-radius: 4px;\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.alert-success {\n background: #e8f5e9;\n color: var(--success-color);\n}\n\n.alert-error {\n background: #ffebee;\n color: var(--error-color);\n}\n\n.alert .material-icons {\n font-size: 20px;\n}\n\n/* Loading */\n.loading {\n text-align: center;\n padding: 3rem;\n color: var(--text-secondary);\n}\n\n.spinner {\n display: inline-block;\n width: 2rem;\n height: 2rem;\n border: 3px solid var(--border-color);\n border-top-color: var(--primary-color);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Modal */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n display: none; /* Hidden by default */\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n}\n\n.modal-overlay.active {\n display: flex; /* Show when active */\n}\n\n.modal-container {\n background: white;\n border-radius: 8px;\n box-shadow:\n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.modal-header h3 {\n font-size: 1.25rem;\n font-weight: 600;\n margin: 0;\n}\n\n.modal-close {\n background: none;\n border: none;\n padding: 0.5rem;\n cursor: pointer;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color 0.2s;\n}\n\n.modal-close:hover {\n background-color: var(--bg-color);\n}\n\n.modal-body {\n padding: 1.5rem;\n overflow-y: auto;\n flex: 1;\n}\n\n.modal-footer {\n padding: 1rem 1.5rem;\n border-top: 1px solid var(--border-color);\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n}\n"]}