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,1196 @@
1
+ # Browser Libraries - LDAP-Rest
2
+
3
+ This guide covers LDAP-Rest's browser libraries for building LDAP management interfaces in web applications.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [LdapTreeViewer](#ldaptreeviewer)
9
+ - [Installation](#ldaptreeviewer-installation)
10
+ - [Basic Usage](#ldaptreeviewer-basic-usage)
11
+ - [Configuration Options](#ldaptreeviewer-configuration-options)
12
+ - [Public Methods](#ldaptreeviewer-public-methods)
13
+ - [TreeNode Structure](#treenode-structure)
14
+ - [Advanced Examples](#ldaptreeviewer-advanced-examples)
15
+ - [LdapUserEditor](#ldapusereditor)
16
+ - [Installation](#ldapusereditor-installation)
17
+ - [Basic Usage](#ldapusereditor-basic-usage)
18
+ - [Configuration Options](#ldapusereditor-configuration-options)
19
+ - [Public Methods](#ldapusereditor-public-methods)
20
+ - [Features](#ldapusereditor-features)
21
+ - [CSS Customization](#ldapusereditor-css-customization)
22
+ - [LdapUnitEditor](#ldapuniteditor)
23
+ - [Installation](#ldapuniteditor-installation)
24
+ - [Basic Usage](#ldapuniteditor-basic-usage)
25
+ - [Features](#ldapuniteditor-features)
26
+
27
+ ---
28
+
29
+ ## Overview
30
+
31
+ LDAP-Rest provides three ready-to-use browser libraries for building LDAP management interfaces:
32
+
33
+ - **LdapTreeViewer** - Interactive hierarchical tree view of LDAP organizations
34
+ - **LdapUserEditor** - Complete user management interface with organization tree, user list, and edit form
35
+ - **LdapUnitEditor** - Organization management interface with create, move, edit, and delete operations
36
+
37
+ All libraries are:
38
+
39
+ - **Framework-agnostic** - Work with vanilla JavaScript or any framework
40
+ - **TypeScript-first** - Full type definitions included
41
+ - **Material Design** - Clean, modern UI following Material Design principles
42
+ - **Customizable** - CSS variables and configuration options
43
+
44
+ ### Usage Modes
45
+
46
+ LDAP-Rest browser libraries can be used in two ways:
47
+
48
+ #### 1. ES Module Imports (Recommended for bundlers)
49
+
50
+ When using a bundler (Webpack, Vite, Rollup, etc.) or in modern Node.js applications, import the libraries using the package exports:
51
+
52
+ ```typescript
53
+ // LDAP Tree Viewer - Main component
54
+ import LdapTreeViewer from 'ldap-rest/browser-ldap-tree-viewer-index';
55
+
56
+ // LDAP User Editor - Main component
57
+ import LdapUserEditor from 'ldap-rest/browser-ldap-user-editor-index';
58
+
59
+ // Individual components (if needed)
60
+ import LdapApiClient from 'ldap-rest/browser-ldap-tree-viewer-api-ldapapiclient';
61
+ import TreeNode from 'ldap-rest/browser-ldap-tree-viewer-components-treenode';
62
+ import UserApiClient from 'ldap-rest/browser-ldap-user-editor-api-userapiclient';
63
+ ```
64
+
65
+ **Available exports:**
66
+
67
+ - **LdapTreeViewer:**
68
+ - `browser-ldap-tree-viewer-index` - Main entry point
69
+ - `browser-ldap-tree-viewer-ldaptreeviewer` - LdapTreeViewer class
70
+ - `browser-ldap-tree-viewer-api-ldapapiclient` - API client
71
+ - `browser-ldap-tree-viewer-components-treenode` - TreeNode component
72
+ - `browser-ldap-tree-viewer-components-treeroot` - TreeRoot component
73
+ - `browser-ldap-tree-viewer-store-store` - State store
74
+ - `browser-ldap-tree-viewer-store-actions` - Store actions
75
+ - `browser-ldap-tree-viewer-store-reducers` - Store reducers
76
+ - `browser-ldap-tree-viewer-types` - TypeScript types
77
+
78
+ - **LdapUserEditor:**
79
+ - `browser-ldap-user-editor-index` - Main entry point
80
+ - `browser-ldap-user-editor-ldapusereditor` - LdapUserEditor class
81
+ - `browser-ldap-user-editor-api-userapiclient` - API client
82
+ - `browser-ldap-user-editor-components-usereditor` - UserEditor component
83
+ - `browser-ldap-user-editor-components-userlist` - UserList component
84
+ - `browser-ldap-user-editor-components-usertree` - UserTree component
85
+ - `browser-ldap-user-editor-components-pointerfield` - PointerField component
86
+ - `browser-ldap-user-editor-types` - TypeScript types
87
+
88
+ #### 2. UMD/Direct Browser Usage
89
+
90
+ For direct browser usage without a bundler, include the files via `<script>` tags (see installation sections below).
91
+
92
+ ---
93
+
94
+ ## LdapTreeViewer
95
+
96
+ An interactive tree component for displaying and navigating LDAP organizational structures.
97
+
98
+ <a name="ldaptreeviewer-installation"></a>
99
+
100
+ ### Installation
101
+
102
+ #### With a Bundler (Webpack, Vite, Rollup, etc.)
103
+
104
+ ```bash
105
+ npm install ldap-rest
106
+ ```
107
+
108
+ ```typescript
109
+ import LdapTreeViewer from 'ldap-rest/browser-ldap-tree-viewer-index';
110
+ // Don't forget to include Material Icons in your HTML
111
+ ```
112
+
113
+ #### Direct Browser Usage
114
+
115
+ Include the required files in your HTML:
116
+
117
+ ```html
118
+ <!DOCTYPE html>
119
+ <html>
120
+ <head>
121
+ <!-- Material Icons (required for icons) -->
122
+ <link
123
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
124
+ rel="stylesheet"
125
+ />
126
+
127
+ <!-- LdapTreeViewer CSS -->
128
+ <link
129
+ rel="stylesheet"
130
+ href="/static/browser/ldap-tree-viewer/LdapTreeViewer.css"
131
+ />
132
+ </head>
133
+ <body>
134
+ <div id="tree-container"></div>
135
+
136
+ <!-- LdapTreeViewer JavaScript -->
137
+ <script src="/static/browser/ldap-tree-viewer/LdapTreeViewer.js"></script>
138
+ </body>
139
+ </html>
140
+ ```
141
+
142
+ <a name="ldaptreeviewer-basic-usage"></a>
143
+
144
+ ### Basic Usage
145
+
146
+ #### With ES Modules
147
+
148
+ ```typescript
149
+ import LdapTreeViewer from 'ldap-rest/browser-ldap-tree-viewer-index';
150
+
151
+ // Create and initialize the tree viewer
152
+ const viewer = new LdapTreeViewer({
153
+ containerId: 'tree-container',
154
+ apiBaseUrl: 'http://localhost:8081',
155
+ onNodeClick: node => {
156
+ console.log('Node clicked:', node.dn);
157
+ },
158
+ onNodeExpand: node => {
159
+ console.log('Node expanded:', node.dn);
160
+ },
161
+ });
162
+
163
+ // Initialize the viewer
164
+ await viewer.init();
165
+ ```
166
+
167
+ #### With UMD (Direct Browser)
168
+
169
+ ```javascript
170
+ // Access the library from window
171
+ const { LdapTreeViewer } = window.LdapTreeViewer;
172
+
173
+ // Create and initialize the tree viewer
174
+ const viewer = new LdapTreeViewer({
175
+ containerId: 'tree-container',
176
+ apiBaseUrl: 'http://localhost:8081',
177
+ onNodeClick: node => {
178
+ console.log('Node clicked:', node.dn);
179
+ },
180
+ onNodeExpand: node => {
181
+ console.log('Node expanded:', node.dn);
182
+ },
183
+ });
184
+
185
+ // Initialize the viewer
186
+ await viewer.init();
187
+ ```
188
+
189
+ <a name="ldaptreeviewer-configuration-options"></a>
190
+
191
+ ### Configuration Options
192
+
193
+ The `ViewerOptions` interface defines all available configuration options:
194
+
195
+ ```typescript
196
+ interface ViewerOptions {
197
+ // Required: ID of the HTML container element
198
+ containerId: string;
199
+
200
+ // Required: Base URL of the LDAP-Rest API
201
+ apiBaseUrl: string;
202
+
203
+ // Optional: Authentication token for API requests
204
+ authToken?: string;
205
+
206
+ // Optional: Root DN to start from (defaults to top organization)
207
+ rootDn?: string;
208
+
209
+ // Optional: Theme ('light' | 'dark')
210
+ theme?: 'light' | 'dark';
211
+
212
+ // Optional: Callback when a node is clicked
213
+ onNodeClick?: (node: TreeNode) => void;
214
+
215
+ // Optional: Callback when a node is expanded
216
+ onNodeExpand?: (node: TreeNode) => void;
217
+ }
218
+ ```
219
+
220
+ **Example with all options:**
221
+
222
+ ```javascript
223
+ const viewer = new LdapTreeViewer({
224
+ containerId: 'tree-container',
225
+ apiBaseUrl: 'http://localhost:8081',
226
+ authToken: 'Bearer your-token-here',
227
+ rootDn: 'ou=divisions,dc=example,dc=com',
228
+ theme: 'dark',
229
+ onNodeClick: node => {
230
+ document.getElementById('selected-dn').textContent = node.dn;
231
+ },
232
+ onNodeExpand: async node => {
233
+ console.log(
234
+ `Expanded ${node.displayName} with ${node.childrenDns.length} children`
235
+ );
236
+ },
237
+ });
238
+ ```
239
+
240
+ <a name="ldaptreeviewer-public-methods"></a>
241
+
242
+ ### Public Methods
243
+
244
+ #### `async init(): Promise<void>`
245
+
246
+ Initializes the tree viewer and loads the root organization.
247
+
248
+ ```javascript
249
+ const viewer = new LdapTreeViewer({
250
+ containerId: 'tree',
251
+ apiBaseUrl: 'http://localhost:8081',
252
+ });
253
+ await viewer.init();
254
+ ```
255
+
256
+ #### `async refresh(): Promise<void>`
257
+
258
+ Reloads the entire tree from the API.
259
+
260
+ ```javascript
261
+ await viewer.refresh();
262
+ ```
263
+
264
+ #### `async expandNode(dn: string): Promise<void>`
265
+
266
+ Programmatically expands a node by its DN.
267
+
268
+ ```javascript
269
+ await viewer.expandNode('ou=sales,dc=example,dc=com');
270
+ ```
271
+
272
+ #### `async collapseNode(dn: string): Promise<void>`
273
+
274
+ Programmatically collapses a node by its DN.
275
+
276
+ ```javascript
277
+ await viewer.collapseNode('ou=sales,dc=example,dc=com');
278
+ ```
279
+
280
+ #### `selectNode(dn: string | null): void`
281
+
282
+ Programmatically selects a node (or deselects if `null`).
283
+
284
+ ```javascript
285
+ viewer.selectNode('ou=engineering,dc=example,dc=com');
286
+ ```
287
+
288
+ #### `getState(): TreeState`
289
+
290
+ Returns the current state of the tree.
291
+
292
+ ```javascript
293
+ const state = viewer.getState();
294
+ console.log('Selected node:', state.selectedNode);
295
+ console.log('Expanded nodes:', Array.from(state.expandedNodes));
296
+ console.log('Total nodes:', state.nodes.size);
297
+ ```
298
+
299
+ #### `destroy(): void`
300
+
301
+ Cleans up the viewer and removes it from the DOM.
302
+
303
+ ```javascript
304
+ viewer.destroy();
305
+ ```
306
+
307
+ <a name="treenode-structure"></a>
308
+
309
+ ### TreeNode Structure
310
+
311
+ Each node in the tree follows this TypeScript interface:
312
+
313
+ ```typescript
314
+ interface TreeNode {
315
+ // Distinguished Name (unique identifier)
316
+ dn: string;
317
+
318
+ // Display name shown in the tree
319
+ displayName: string;
320
+
321
+ // Node type: 'organization' | 'user' | 'group' | 'more'
322
+ type: 'organization' | 'user' | 'group' | 'more';
323
+
324
+ // Parent DN (null for root)
325
+ parentDn: string | null;
326
+
327
+ // Array of child DNs
328
+ childrenDns: string[];
329
+
330
+ // Whether children have been loaded from API
331
+ hasLoadedChildren: boolean;
332
+
333
+ // Whether this node can have children
334
+ hasChildren: boolean;
335
+
336
+ // Raw LDAP attributes from the API
337
+ attributes?: Record<string, unknown>;
338
+ }
339
+ ```
340
+
341
+ **Example TreeNode:**
342
+
343
+ ```javascript
344
+ {
345
+ dn: "ou=engineering,dc=example,dc=com",
346
+ displayName: "Engineering",
347
+ type: "organization",
348
+ parentDn: "dc=example,dc=com",
349
+ childrenDns: [
350
+ "ou=backend,ou=engineering,dc=example,dc=com",
351
+ "ou=frontend,ou=engineering,dc=example,dc=com"
352
+ ],
353
+ hasLoadedChildren: true,
354
+ hasChildren: true,
355
+ attributes: {
356
+ ou: "engineering",
357
+ objectClass: ["top", "organizationalUnit"],
358
+ description: "Engineering department"
359
+ }
360
+ }
361
+ ```
362
+
363
+ <a name="ldaptreeviewer-advanced-examples"></a>
364
+
365
+ ### Advanced Examples
366
+
367
+ #### Expand All Nodes Recursively
368
+
369
+ ```javascript
370
+ async function expandAll(viewer) {
371
+ const state = viewer.getState();
372
+ const nodesToExpand = [];
373
+
374
+ // Find all unexpanded nodes with children
375
+ state.nodes.forEach((node, dn) => {
376
+ if (node.hasChildren && !state.expandedNodes.has(dn)) {
377
+ nodesToExpand.push(dn);
378
+ }
379
+ });
380
+
381
+ // Expand each node
382
+ for (const dn of nodesToExpand) {
383
+ await viewer.expandNode(dn);
384
+
385
+ // Recursively expand any new children
386
+ await expandAll(viewer);
387
+ }
388
+ }
389
+
390
+ // Usage
391
+ const viewer = new LdapTreeViewer({
392
+ containerId: 'tree-container',
393
+ apiBaseUrl: 'http://localhost:8081',
394
+ });
395
+
396
+ await viewer.init();
397
+ await expandAll(viewer);
398
+ ```
399
+
400
+ #### Search and Highlight Nodes
401
+
402
+ ```javascript
403
+ function highlightNodes(viewer, searchTerm) {
404
+ const state = viewer.getState();
405
+ const matches = [];
406
+
407
+ state.nodes.forEach((node, dn) => {
408
+ if (node.displayName.toLowerCase().includes(searchTerm.toLowerCase())) {
409
+ matches.push(node);
410
+ }
411
+ });
412
+
413
+ return matches;
414
+ }
415
+
416
+ // Usage
417
+ const viewer = new LdapTreeViewer({
418
+ containerId: 'tree-container',
419
+ apiBaseUrl: 'http://localhost:8081',
420
+ onNodeClick: node => {
421
+ document.getElementById('details').innerHTML = `
422
+ <h3>${node.displayName}</h3>
423
+ <p><strong>DN:</strong> ${node.dn}</p>
424
+ <p><strong>Type:</strong> ${node.type}</p>
425
+ <p><strong>Children:</strong> ${node.childrenDns.length}</p>
426
+ `;
427
+ },
428
+ });
429
+
430
+ await viewer.init();
431
+
432
+ // Search functionality
433
+ document.getElementById('search').addEventListener('input', e => {
434
+ const matches = highlightNodes(viewer, e.target.value);
435
+ console.log(`Found ${matches.length} matches`);
436
+ });
437
+ ```
438
+
439
+ #### Integration with Custom UI
440
+
441
+ ```javascript
442
+ const viewer = new LdapTreeViewer({
443
+ containerId: 'tree-container',
444
+ apiBaseUrl: 'http://localhost:8081',
445
+ onNodeClick: async node => {
446
+ // Show loading state
447
+ document.getElementById('sidebar').classList.add('loading');
448
+
449
+ // Fetch additional data
450
+ const response = await fetch(
451
+ `${viewer.options.apiBaseUrl}/api/v1/ldap/organizations/${encodeURIComponent(node.dn)}`
452
+ );
453
+ const data = await response.json();
454
+
455
+ // Update custom UI
456
+ updateSidebar(data);
457
+
458
+ // Hide loading state
459
+ document.getElementById('sidebar').classList.remove('loading');
460
+ },
461
+ onNodeExpand: node => {
462
+ // Track analytics
463
+ analytics.track('Organization Expanded', {
464
+ dn: node.dn,
465
+ name: node.displayName,
466
+ });
467
+ },
468
+ });
469
+
470
+ await viewer.init();
471
+ ```
472
+
473
+ ---
474
+
475
+ ## LdapUserEditor
476
+
477
+ A complete user management interface with organization tree, user list, and edit form.
478
+
479
+ <a name="ldapusereditor-installation"></a>
480
+
481
+ ### Installation
482
+
483
+ #### With a Bundler (Webpack, Vite, Rollup, etc.)
484
+
485
+ ```bash
486
+ npm install ldap-rest
487
+ ```
488
+
489
+ ```typescript
490
+ import LdapUserEditor from 'ldap-rest/browser-ldap-user-editor-index';
491
+ // Don't forget to include Roboto font and Material Icons in your HTML
492
+ ```
493
+
494
+ #### Direct Browser Usage
495
+
496
+ Include the required dependencies in your HTML:
497
+
498
+ ```html
499
+ <!DOCTYPE html>
500
+ <html>
501
+ <head>
502
+ <!-- Google Fonts - Roboto (required) -->
503
+ <link
504
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
505
+ rel="stylesheet"
506
+ />
507
+
508
+ <!-- Material Icons (required) -->
509
+ <link
510
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
511
+ rel="stylesheet"
512
+ />
513
+
514
+ <!-- LdapUserEditor CSS -->
515
+ <link
516
+ rel="stylesheet"
517
+ href="/static/browser/ldap-user-editor/LdapUserEditor.css"
518
+ />
519
+ </head>
520
+ <body>
521
+ <div id="editor-container"></div>
522
+
523
+ <!-- LdapUserEditor JavaScript -->
524
+ <script src="/static/browser/ldap-user-editor/LdapUserEditor.js"></script>
525
+ </body>
526
+ </html>
527
+ ```
528
+
529
+ <a name="ldapusereditor-basic-usage"></a>
530
+
531
+ ### Basic Usage
532
+
533
+ #### With ES Modules
534
+
535
+ ```typescript
536
+ import LdapUserEditor from 'ldap-rest/browser-ldap-user-editor-index';
537
+
538
+ // Create and initialize the editor
539
+ const editor = new LdapUserEditor({
540
+ containerId: 'editor-container',
541
+ apiBaseUrl: 'http://localhost:8081',
542
+ onUserSaved: userDn => {
543
+ console.log('User saved:', userDn);
544
+ },
545
+ onError: error => {
546
+ console.error('Editor error:', error);
547
+ },
548
+ });
549
+
550
+ // Initialize the editor
551
+ await editor.init();
552
+ ```
553
+
554
+ #### With UMD (Direct Browser)
555
+
556
+ ```javascript
557
+ // Access the library from window
558
+ const { LdapUserEditor } = window.LdapUserEditor;
559
+
560
+ // Create and initialize the editor
561
+ const editor = new LdapUserEditor({
562
+ containerId: 'editor-container',
563
+ apiBaseUrl: 'http://localhost:8081',
564
+ onUserSaved: userDn => {
565
+ console.log('User saved:', userDn);
566
+ },
567
+ onError: error => {
568
+ console.error('Editor error:', error);
569
+ },
570
+ });
571
+
572
+ // Initialize the editor
573
+ await editor.init();
574
+ ```
575
+
576
+ <a name="ldapusereditor-configuration-options"></a>
577
+
578
+ ### Configuration Options
579
+
580
+ The `EditorOptions` interface defines all available configuration options:
581
+
582
+ ```typescript
583
+ interface EditorOptions {
584
+ // Required: ID of the HTML container element
585
+ containerId: string;
586
+
587
+ // Optional: Base URL of the LDAP-Rest API (defaults to current origin)
588
+ apiBaseUrl?: string;
589
+
590
+ // Optional: Callback when a user is saved
591
+ onUserSaved?: (userDn: string) => void;
592
+
593
+ // Optional: Callback for error handling
594
+ onError?: (error: Error) => void;
595
+ }
596
+ ```
597
+
598
+ **Example with all options:**
599
+
600
+ ```javascript
601
+ const editor = new LdapUserEditor({
602
+ containerId: 'editor-container',
603
+ apiBaseUrl: 'http://localhost:8081',
604
+ onUserSaved: userDn => {
605
+ // Show success notification
606
+ showNotification('User saved successfully!', 'success');
607
+
608
+ // Refresh external data
609
+ refreshDashboard();
610
+
611
+ // Log activity
612
+ logActivity('user_updated', userDn);
613
+ },
614
+ onError: error => {
615
+ // Show error notification
616
+ showNotification(`Error: ${error.message}`, 'error');
617
+
618
+ // Log error to monitoring service
619
+ errorTracker.captureException(error);
620
+ },
621
+ });
622
+
623
+ await editor.init();
624
+ ```
625
+
626
+ <a name="ldapusereditor-public-methods"></a>
627
+
628
+ ### Public Methods
629
+
630
+ #### `async init(): Promise<void>`
631
+
632
+ Initializes the editor and loads the organization tree.
633
+
634
+ ```javascript
635
+ const editor = new LdapUserEditor({
636
+ containerId: 'editor-container',
637
+ apiBaseUrl: 'http://localhost:8081',
638
+ });
639
+
640
+ await editor.init();
641
+ ```
642
+
643
+ #### `async refresh(): Promise<void>`
644
+
645
+ Refreshes the organization tree and currently displayed user data.
646
+
647
+ ```javascript
648
+ await editor.refresh();
649
+ ```
650
+
651
+ #### `destroy(): void`
652
+
653
+ Cleans up the editor and removes it from the DOM.
654
+
655
+ ```javascript
656
+ editor.destroy();
657
+ ```
658
+
659
+ <a name="ldapusereditor-features"></a>
660
+
661
+ ### Features
662
+
663
+ The LdapUserEditor provides a complete user management interface with three main components:
664
+
665
+ #### 1. Organization Tree
666
+
667
+ - **Hierarchical navigation** - Browse LDAP organizations in a tree structure
668
+ - **Visual indicators** - Material Icons for different node types
669
+ - **Expand/collapse** - Load children on demand
670
+ - **Selection highlighting** - Visual feedback for selected organization
671
+
672
+ #### 2. User List
673
+
674
+ - **Filtered by organization** - Shows users in the selected organization
675
+ - **User details** - Displays name and email for each user
676
+ - **Click to edit** - Select a user to open the edit form
677
+ - **Material Design** - Clean, modern list interface
678
+
679
+ #### 3. Edit Form
680
+
681
+ - **Schema-driven** - Automatically generated from JSON schema
682
+ - **Field validation** - Required fields, regex patterns, custom validation
683
+ - **Field groups** - Organized sections for better UX
684
+ - **Multiple input types** - Text, email, select, arrays
685
+ - **Save/Cancel actions** - With loading states and error handling
686
+ - **Real-time feedback** - Success/error messages
687
+
688
+ **Complete Example:**
689
+
690
+ ```html
691
+ <!DOCTYPE html>
692
+ <html>
693
+ <head>
694
+ <meta charset="UTF-8" />
695
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
696
+ <title>User Management</title>
697
+
698
+ <link
699
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
700
+ rel="stylesheet"
701
+ />
702
+ <link
703
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
704
+ rel="stylesheet"
705
+ />
706
+ <link
707
+ rel="stylesheet"
708
+ href="/static/browser/ldap-user-editor/LdapUserEditor.css"
709
+ />
710
+
711
+ <style>
712
+ body {
713
+ margin: 0;
714
+ padding: 20px;
715
+ background: #f5f5f5;
716
+ font-family: 'Roboto', sans-serif;
717
+ }
718
+
719
+ .container {
720
+ max-width: 1400px;
721
+ margin: 0 auto;
722
+ }
723
+
724
+ h1 {
725
+ color: #333;
726
+ margin-bottom: 20px;
727
+ }
728
+
729
+ #editor-container {
730
+ background: white;
731
+ border-radius: 8px;
732
+ padding: 24px;
733
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
734
+ }
735
+ </style>
736
+ </head>
737
+ <body>
738
+ <div class="container">
739
+ <h1>User Management System</h1>
740
+ <div id="editor-container"></div>
741
+ </div>
742
+
743
+ <script src="/static/browser/ldap-user-editor/LdapUserEditor.js"></script>
744
+ <script>
745
+ const { LdapUserEditor } = window.LdapUserEditor;
746
+
747
+ const editor = new LdapUserEditor({
748
+ containerId: 'editor-container',
749
+ apiBaseUrl: window.location.origin,
750
+ onUserSaved: userDn => {
751
+ console.log('User saved successfully:', userDn);
752
+ },
753
+ onError: error => {
754
+ console.error('Error:', error.message);
755
+ },
756
+ });
757
+
758
+ editor.init().catch(error => {
759
+ console.error('Failed to initialize editor:', error);
760
+ });
761
+ </script>
762
+ </body>
763
+ </html>
764
+ ```
765
+
766
+ <a name="ldapusereditor-css-customization"></a>
767
+
768
+ ### CSS Customization
769
+
770
+ The LdapUserEditor uses CSS variables for easy customization. Override these variables in your stylesheet:
771
+
772
+ ```css
773
+ :root {
774
+ /* Primary colors */
775
+ --primary-color: #6200ee;
776
+ --primary-dark: #3700b3;
777
+ --success-color: #2e7d32;
778
+ --error-color: #c62828;
779
+
780
+ /* Background colors */
781
+ --bg-color: #f8fafc;
782
+ --surface-color: #ffffff;
783
+
784
+ /* Text colors */
785
+ --text-primary: #1e293b;
786
+ --text-secondary: #64748b;
787
+
788
+ /* Border color */
789
+ --border-color: #e2e8f0;
790
+ }
791
+ ```
792
+
793
+ **Example - Custom Theme:**
794
+
795
+ ```css
796
+ /* Dark theme customization */
797
+ :root {
798
+ --primary-color: #bb86fc;
799
+ --primary-dark: #9965f4;
800
+ --success-color: #4caf50;
801
+ --error-color: #ef5350;
802
+
803
+ --bg-color: #121212;
804
+ --surface-color: #1e1e1e;
805
+
806
+ --text-primary: #ffffff;
807
+ --text-secondary: #b0b0b0;
808
+
809
+ --border-color: #333333;
810
+ }
811
+ ```
812
+
813
+ **Example - Custom Branding:**
814
+
815
+ ```css
816
+ /* Company branding */
817
+ :root {
818
+ --primary-color: #ff6b35; /* Your brand color */
819
+ --primary-dark: #d45426;
820
+ --success-color: #28a745;
821
+ --error-color: #dc3545;
822
+ }
823
+
824
+ /* Custom button styles */
825
+ .btn {
826
+ border-radius: 20px; /* Rounded buttons */
827
+ text-transform: none; /* No uppercase */
828
+ font-weight: 600;
829
+ }
830
+
831
+ /* Custom panel styles */
832
+ .demo-panel {
833
+ border-radius: 12px; /* More rounded */
834
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
835
+ }
836
+
837
+ /* Custom tree node hover */
838
+ .tree-node:hover {
839
+ background: linear-gradient(90deg, var(--bg-color) 0%, transparent 100%);
840
+ }
841
+ ```
842
+
843
+ **Example - Compact Layout:**
844
+
845
+ ```css
846
+ /* Smaller, more compact layout */
847
+ .editor-layout {
848
+ gap: 16px; /* Less spacing */
849
+ }
850
+
851
+ .demo-panel {
852
+ padding: 16px; /* Less padding */
853
+ max-height: 600px; /* Smaller height */
854
+ }
855
+
856
+ .form-row {
857
+ gap: 1rem; /* Tighter form spacing */
858
+ margin-bottom: 1rem;
859
+ }
860
+
861
+ .form-input,
862
+ .form-select {
863
+ padding: 0.5rem 0.625rem; /* Smaller inputs */
864
+ font-size: 0.8125rem;
865
+ }
866
+ ```
867
+
868
+ **Example - Accessibility Enhancements:**
869
+
870
+ ```css
871
+ /* High contrast mode */
872
+ @media (prefers-contrast: high) {
873
+ :root {
874
+ --border-color: #000000;
875
+ --text-primary: #000000;
876
+ --text-secondary: #333333;
877
+ }
878
+
879
+ .form-input:focus,
880
+ .form-select:focus {
881
+ border-width: 2px;
882
+ border-color: #000000;
883
+ }
884
+ }
885
+
886
+ /* Larger text for accessibility */
887
+ .ldap-user-editor {
888
+ font-size: 16px; /* Larger base font */
889
+ }
890
+
891
+ .form-label {
892
+ font-weight: 600; /* Bolder labels */
893
+ }
894
+
895
+ /* Better focus indicators */
896
+ .btn:focus,
897
+ .form-input:focus,
898
+ .form-select:focus {
899
+ outline: 3px solid var(--primary-color);
900
+ outline-offset: 2px;
901
+ }
902
+ ```
903
+
904
+ ---
905
+
906
+ ## LdapUnitEditor
907
+
908
+ A complete organizational unit (OU) management interface with tree navigation, create, move, edit, and delete operations.
909
+
910
+ <a name="ldapuniteditor-installation"></a>
911
+
912
+ ### Installation
913
+
914
+ #### Direct Browser Usage
915
+
916
+ Include the required dependencies in your HTML:
917
+
918
+ ```html
919
+ <!DOCTYPE html>
920
+ <html>
921
+ <head>
922
+ <!-- Google Fonts - Roboto (required) -->
923
+ <link
924
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
925
+ rel="stylesheet"
926
+ />
927
+
928
+ <!-- Material Icons (required) -->
929
+ <link
930
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
931
+ rel="stylesheet"
932
+ />
933
+
934
+ <!-- Shared CSS (required) -->
935
+ <link rel="stylesheet" href="/static/browser/common-demo.css" />
936
+ </head>
937
+ <body>
938
+ <div id="editor-container"></div>
939
+
940
+ <!-- LdapUnitEditor JavaScript -->
941
+ <script src="/static/browser/ldap-unit-editor.js"></script>
942
+ </body>
943
+ </html>
944
+ ```
945
+
946
+ <a name="ldapuniteditor-basic-usage"></a>
947
+
948
+ ### Basic Usage
949
+
950
+ ```html
951
+ <!DOCTYPE html>
952
+ <html>
953
+ <head>
954
+ <meta charset="UTF-8" />
955
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
956
+ <title>Organization Management</title>
957
+
958
+ <link
959
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
960
+ rel="stylesheet"
961
+ />
962
+ <link
963
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
964
+ rel="stylesheet"
965
+ />
966
+ <link rel="stylesheet" href="/static/browser/common-demo.css" />
967
+ </head>
968
+ <body>
969
+ <div class="demo-container">
970
+ <header class="demo-header">
971
+ <h1>Organization Management</h1>
972
+ <p>Create, edit, move, and delete organizational units</p>
973
+ </header>
974
+ <div id="editor-container"></div>
975
+ </div>
976
+
977
+ <script src="/static/browser/ldap-unit-editor.js"></script>
978
+ <script>
979
+ const { LdapUnitEditor } = window.LdapUnitEditor;
980
+
981
+ const editor = new LdapUnitEditor({
982
+ containerId: 'editor-container',
983
+ apiBaseUrl: window.location.origin,
984
+ });
985
+
986
+ editor.init().catch(error => {
987
+ console.error('Failed to initialize editor:', error);
988
+ });
989
+ </script>
990
+ </body>
991
+ </html>
992
+ ```
993
+
994
+ <a name="ldapuniteditor-features"></a>
995
+
996
+ ### Features
997
+
998
+ The LdapUnitEditor provides a complete organization management interface with two main panels:
999
+
1000
+ #### 1. Organization Tree Panel
1001
+
1002
+ - **Hierarchical navigation** - Browse LDAP organizations in an expandable tree structure
1003
+ - **Material Icons** - Visual indicators with business icons
1004
+ - **Create button** - Quickly create new sub-organizations under selected unit
1005
+ - **Click to edit** - Select an organization to view and edit its properties
1006
+ - **Automatic expansion** - Tree expands to show newly created organizations
1007
+
1008
+ **Features:**
1009
+
1010
+ - Create new organizational units under any parent organization
1011
+ - Prompts for OU name with validation
1012
+ - Automatically expands parent after creation
1013
+ - Refreshes tree to show new structure
1014
+
1015
+ #### 2. Property Editor Panel
1016
+
1017
+ - **Schema-driven forms** - Automatically generated from JSON schema
1018
+ - **Field validation** - Required fields, type checking
1019
+ - **Field groups** - Organized into "Basic Information" and "Additional Properties"
1020
+ - **Move operation** - Relocate organizations to different parents with modal tree picker
1021
+ - **Delete protection** - Automatically disables delete button when organization has sub-organizations
1022
+ - **Real-time feedback** - Success/error messages via alerts
1023
+
1024
+ **Features:**
1025
+
1026
+ - **Edit Properties**: Modify OU name, description, and custom attributes
1027
+ - **Move Organization**:
1028
+ - Opens modal with organization tree
1029
+ - Cannot move into itself or descendants (circular reference prevention)
1030
+ - Shows current organization as disabled in the tree
1031
+ - Updates DN automatically after move
1032
+ - **Delete Organization**:
1033
+ - Button disabled when organization contains sub-organizations
1034
+ - Visual indication (grayed out, cursor not-allowed)
1035
+ - Tooltip explaining why deletion is blocked
1036
+ - Confirmation dialog before deletion
1037
+ - **Validation**: All changes validated against configured schema
1038
+
1039
+ #### 3. Move Modal
1040
+
1041
+ When clicking the "Move" button, a modal dialog appears with:
1042
+
1043
+ - **Organization tree picker** - Navigate and select target parent organization
1044
+ - **Visual feedback** - Current organization shown as disabled
1045
+ - **Expand/collapse** - Load children on demand
1046
+ - **Selection highlighting** - Clear visual indication of selected target
1047
+ - **Circular move prevention** - Cannot select current org or its descendants
1048
+ - **Cancel/Move actions** - Confirm or cancel the move operation
1049
+
1050
+ **Example Move Operation:**
1051
+
1052
+ ```
1053
+ Original: ou=Recruitment,ou=HR,dc=example,dc=com
1054
+ Target: ou=Operations,dc=example,dc=com
1055
+ Result: ou=Recruitment,ou=Operations,dc=example,dc=com
1056
+ ```
1057
+
1058
+ All users, groups, and sub-organizations linked to the moved unit automatically update their references.
1059
+
1060
+ ### Usage Example
1061
+
1062
+ ```html
1063
+ <!DOCTYPE html>
1064
+ <html lang="en">
1065
+ <head>
1066
+ <meta charset="UTF-8" />
1067
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1068
+ <title>LDAP Organization Manager</title>
1069
+
1070
+ <!-- Required fonts and icons -->
1071
+ <link
1072
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
1073
+ rel="stylesheet"
1074
+ />
1075
+ <link
1076
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
1077
+ rel="stylesheet"
1078
+ />
1079
+
1080
+ <!-- Shared CSS -->
1081
+ <link rel="stylesheet" href="/static/browser/common-demo.css" />
1082
+
1083
+ <style>
1084
+ body {
1085
+ margin: 0;
1086
+ padding: 0;
1087
+ background: #f5f5f5;
1088
+ font-family: 'Roboto', sans-serif;
1089
+ }
1090
+
1091
+ .demo-container {
1092
+ max-width: 1400px;
1093
+ margin: 0 auto;
1094
+ padding: 20px;
1095
+ }
1096
+
1097
+ .demo-header {
1098
+ background: white;
1099
+ padding: 24px;
1100
+ border-radius: 8px;
1101
+ margin-bottom: 20px;
1102
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1103
+ }
1104
+
1105
+ .demo-header h1 {
1106
+ margin: 0 0 8px 0;
1107
+ color: var(--primary-color, #6200ee);
1108
+ }
1109
+
1110
+ .demo-header p {
1111
+ margin: 0;
1112
+ color: #666;
1113
+ }
1114
+
1115
+ #editor-container {
1116
+ background: white;
1117
+ border-radius: 8px;
1118
+ padding: 24px;
1119
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1120
+ min-height: 600px;
1121
+ }
1122
+ </style>
1123
+ </head>
1124
+ <body>
1125
+ <div class="demo-container">
1126
+ <header class="demo-header">
1127
+ <h1>Organization Management System</h1>
1128
+ <p>
1129
+ Manage your LDAP organizational structure - Create, edit, move, and
1130
+ delete organizational units
1131
+ </p>
1132
+ </header>
1133
+
1134
+ <div id="editor-container"></div>
1135
+ </div>
1136
+
1137
+ <script src="/static/browser/ldap-unit-editor.js"></script>
1138
+ <script>
1139
+ const { LdapUnitEditor } = window.LdapUnitEditor;
1140
+
1141
+ const editor = new LdapUnitEditor({
1142
+ containerId: 'editor-container',
1143
+ apiBaseUrl: window.location.origin,
1144
+ });
1145
+
1146
+ editor.init().catch(error => {
1147
+ console.error('Failed to initialize organization editor:', error);
1148
+ document.getElementById('editor-container').innerHTML = `
1149
+ <div style="color: #c62828; padding: 20px; text-align: center;">
1150
+ <p style="font-size: 18px; margin: 0;">Failed to load editor</p>
1151
+ <p style="margin: 8px 0 0 0;">${error.message}</p>
1152
+ </div>
1153
+ `;
1154
+ });
1155
+ </script>
1156
+ </body>
1157
+ </html>
1158
+ ```
1159
+
1160
+ ### API Requirements
1161
+
1162
+ The LdapUnitEditor requires the following LDAP-Rest API endpoints:
1163
+
1164
+ - `GET /api/v1/config` - Configuration and schema
1165
+ - `GET /api/v1/ldap/organizations/top` - Top organization
1166
+ - `GET /api/v1/ldap/organizations/:dn` - Get organization details
1167
+ - `GET /api/v1/ldap/organizations/:dn/subnodes` - Get child organizations
1168
+ - `POST /api/v1/ldap/organizations` - Create new organization
1169
+ - `PUT /api/v1/ldap/organizations/:dn` - Update organization
1170
+ - `POST /api/v1/ldap/organizations/:dn/move` - Move organization to new parent
1171
+ - `DELETE /api/v1/ldap/organizations/:dn` - Delete organization
1172
+
1173
+ See [LDAP Organizations Plugin Documentation](../ldapOrganizations.md) for API details.
1174
+
1175
+ ---
1176
+
1177
+ ## Next Steps
1178
+
1179
+ - **[REST API Documentation](../api/REST_API.md)** - Learn about the underlying API
1180
+ - **[Integration Examples](../examples/EXAMPLES.md)** - See real-world integration examples
1181
+ - **[JSON Schemas Guide](../schemas/SCHEMAS.md)** - Understand schema-driven architecture
1182
+ - **[LDAP Organizations Plugin](../ldapOrganizations.md)** - Learn about organization management
1183
+
1184
+ ---
1185
+
1186
+ ## Resources
1187
+
1188
+ - [GitHub Repository](https://github.com/linagora/ldap-rest)
1189
+ - [Developer Guide](../DEVELOPER_GUIDE.md)
1190
+ - [API Reference](../api/REFERENCE.md)
1191
+
1192
+ ---
1193
+
1194
+ ## License
1195
+
1196
+ AGPL-3.0 - Copyright 2025-present LINAGORA