@profoundlogic/coderflow-server 0.7.6 → 0.7.8

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 (188) hide show
  1. package/dist/base-image/agent-wrapper.sh +3 -1
  2. package/dist/coder-server.js +1 -1
  3. package/dist/config.js +1 -1
  4. package/dist/lib/agent-keepalive.js +1 -1
  5. package/dist/lib/agent-models.js +1 -1
  6. package/dist/lib/api-keys.js +1 -1
  7. package/dist/lib/apiKeys.js +1 -1
  8. package/dist/lib/app-server-ports.js +1 -1
  9. package/dist/lib/auto-judge.js +1 -1
  10. package/dist/lib/automation-service.js +1 -1
  11. package/dist/lib/basic-auth.js +1 -1
  12. package/dist/lib/bindings.js +1 -1
  13. package/dist/lib/build-history.js +1 -1
  14. package/dist/lib/build-output-service.js +1 -1
  15. package/dist/lib/build-scheduler.js +1 -1
  16. package/dist/lib/build-service.js +1 -1
  17. package/dist/lib/ca-certificates.js +1 -1
  18. package/dist/lib/claude-oauth-refresh.js +1 -1
  19. package/dist/lib/cli/build.js +1 -1
  20. package/dist/lib/cli/cleanup-users.js +1 -1
  21. package/dist/lib/cli/config-command.js +1 -1
  22. package/dist/lib/cli/config.js +1 -1
  23. package/dist/lib/cli/create-user.js +1 -1
  24. package/dist/lib/cli/grant-admin.js +1 -1
  25. package/dist/lib/cli/init.js +1 -1
  26. package/dist/lib/cli/jira.js +1 -1
  27. package/dist/lib/cli/license.js +1 -1
  28. package/dist/lib/cli/list-roles.js +1 -1
  29. package/dist/lib/cli/list-users.js +1 -1
  30. package/dist/lib/cli/server-manager.js +1 -1
  31. package/dist/lib/cli/set-password.js +1 -1
  32. package/dist/lib/compression-filter.js +1 -0
  33. package/dist/lib/config-migration.js +1 -1
  34. package/dist/lib/container-credential-sync.js +1 -1
  35. package/dist/lib/container-tokens.js +1 -1
  36. package/dist/lib/data-dir.js +1 -1
  37. package/dist/lib/deployment-history.js +1 -1
  38. package/dist/lib/deployment-service.js +1 -1
  39. package/dist/lib/docker-utils.js +1 -1
  40. package/dist/lib/email.js +1 -1
  41. package/dist/lib/emailTemplates.js +1 -1
  42. package/dist/lib/entitlement.js +1 -1
  43. package/dist/lib/external-connections.js +1 -1
  44. package/dist/lib/fetch-utils.js +1 -1
  45. package/dist/lib/git-commit-details-route.js +1 -1
  46. package/dist/lib/git-history-diff-guardrails.js +1 -1
  47. package/dist/lib/git-provider-service.js +1 -1
  48. package/dist/lib/git-provider-setup/github-setup-handler.js +1 -1
  49. package/dist/lib/git-provider-setup/index.js +1 -1
  50. package/dist/lib/git-provider-setup/setup-factory.js +1 -1
  51. package/dist/lib/git-provider-setup/setup-interface.js +1 -1
  52. package/dist/lib/git-providers/azure-devops-provider.js +1 -1
  53. package/dist/lib/git-providers/github-app-provider.js +1 -1
  54. package/dist/lib/git-providers/index.js +1 -1
  55. package/dist/lib/git-providers/provider-factory.js +1 -1
  56. package/dist/lib/git-providers/provider-interface.js +1 -1
  57. package/dist/lib/github-urls.js +1 -1
  58. package/dist/lib/group-objective-linking.js +1 -1
  59. package/dist/lib/ibmi-sync.js +1 -1
  60. package/dist/lib/jira-client.js +1 -1
  61. package/dist/lib/judge-blinding.js +1 -1
  62. package/dist/lib/logger.js +1 -1
  63. package/dist/lib/memory-utils.js +1 -1
  64. package/dist/lib/migration-to-scoped-rbac.js +1 -1
  65. package/dist/lib/model-fetcher.js +1 -1
  66. package/dist/lib/notifications.js +1 -1
  67. package/dist/lib/objective-context.js +1 -1
  68. package/dist/lib/oidc-auth.js +1 -1
  69. package/dist/lib/oidc-device-flow.js +1 -1
  70. package/dist/lib/passwordTokens.js +1 -1
  71. package/dist/lib/permission-resolver.js +1 -1
  72. package/dist/lib/pin-cascade.js +1 -1
  73. package/dist/lib/provider-accounts.js +1 -1
  74. package/dist/lib/provider-oauth.js +1 -1
  75. package/dist/lib/provider-profile.js +1 -1
  76. package/dist/lib/provider-token-refresh.js +1 -1
  77. package/dist/lib/rbac-user-state.js +1 -1
  78. package/dist/lib/request-url.js +1 -1
  79. package/dist/lib/rewind.js +1 -1
  80. package/dist/lib/role-definitions.js +1 -1
  81. package/dist/lib/roles.js +1 -1
  82. package/dist/lib/secrets.js +1 -1
  83. package/dist/lib/setup-repo-git-auth.js +1 -1
  84. package/dist/lib/state-capture.js +1 -1
  85. package/dist/lib/static-files.js +1 -1
  86. package/dist/lib/task-aliases.js +1 -1
  87. package/dist/lib/task-name-format.js +1 -1
  88. package/dist/lib/task-name-generator.js +1 -1
  89. package/dist/lib/task-source-metadata.js +1 -1
  90. package/dist/lib/teams.js +1 -1
  91. package/dist/lib/user-git-oauth.js +1 -1
  92. package/dist/lib/user-git-tokens.js +1 -1
  93. package/dist/lib/users.js +1 -1
  94. package/dist/middleware/requireAuth.js +1 -1
  95. package/dist/middleware/requireInit.js +1 -1
  96. package/dist/middleware/requirePermission.js +1 -1
  97. package/dist/package.json +1 -1
  98. package/dist/playwright.config.js +1 -1
  99. package/dist/playwright.task-terminal.config.js +1 -1
  100. package/dist/routes/apiKeys.js +1 -1
  101. package/dist/routes/auth-oidc.js +1 -1
  102. package/dist/routes/auth.js +1 -1
  103. package/dist/routes/automations.js +1 -1
  104. package/dist/routes/bindings.js +1 -1
  105. package/dist/routes/build.js +1 -1
  106. package/dist/routes/containers.js +1 -1
  107. package/dist/routes/deploy-task.js +1 -1
  108. package/dist/routes/environment-management.js +1 -1
  109. package/dist/routes/environments.js +1 -1
  110. package/dist/routes/external-skills.js +1 -1
  111. package/dist/routes/git-credentials.js +1 -1
  112. package/dist/routes/git-oauth.js +1 -1
  113. package/dist/routes/git-provider-setup.js +1 -1
  114. package/dist/routes/health.js +1 -1
  115. package/dist/routes/jira.js +1 -1
  116. package/dist/routes/logs.js +1 -0
  117. package/dist/routes/objective-management.js +1 -1
  118. package/dist/routes/password.js +1 -1
  119. package/dist/routes/prompt.js +1 -1
  120. package/dist/routes/provider-auth.js +1 -1
  121. package/dist/routes/qa.js +1 -1
  122. package/dist/routes/roles.js +1 -1
  123. package/dist/routes/settings.js +1 -1
  124. package/dist/routes/skill-management.js +1 -1
  125. package/dist/routes/skills.js +1 -1
  126. package/dist/routes/stats.js +1 -0
  127. package/dist/routes/tasks.js +1 -1
  128. package/dist/routes/teams.js +1 -1
  129. package/dist/routes/templates.js +1 -1
  130. package/dist/routes/test-task.js +1 -1
  131. package/dist/routes/test.js +1 -1
  132. package/dist/routes/users.js +1 -1
  133. package/dist/routes/visualizations.js +1 -1
  134. package/dist/scripts/create-user.js +1 -1
  135. package/dist/scripts/migrate-config-to-data-dir.js +1 -1
  136. package/dist/start.js +1 -1
  137. package/dist/web-ui/public/activity-detail-modal.js +1 -1
  138. package/dist/web-ui/public/activity-feed.js +1 -1
  139. package/dist/web-ui/public/activity-formatters.js +1 -1
  140. package/dist/web-ui/public/admin.css +575 -0
  141. package/dist/web-ui/public/admin.html +636 -0
  142. package/dist/web-ui/public/admin.js +1 -0
  143. package/dist/web-ui/public/agent-event-parser.js +1 -1
  144. package/dist/web-ui/public/app.js +1 -1
  145. package/dist/web-ui/public/approve-dialog.js +1 -1
  146. package/dist/web-ui/public/automation-links.js +1 -1
  147. package/dist/web-ui/public/automation-schedule.js +1 -1
  148. package/dist/web-ui/public/comments-widget.js +1 -1
  149. package/dist/web-ui/public/diff-utils.js +1 -1
  150. package/dist/web-ui/public/environments.html +2 -2
  151. package/dist/web-ui/public/environments.js +1 -1
  152. package/dist/web-ui/public/feedback-widget.js +1 -1
  153. package/dist/web-ui/public/file-selection-tree.js +1 -1
  154. package/dist/web-ui/public/git-history-lazy-utils.js +1 -1
  155. package/dist/web-ui/public/git-history.html +2 -2
  156. package/dist/web-ui/public/git-history.js +1 -1
  157. package/dist/web-ui/public/git-status.js +1 -1
  158. package/dist/web-ui/public/ibmi-file-filter.js +1 -1
  159. package/dist/web-ui/public/index.html +2 -170
  160. package/dist/web-ui/public/index.js +1 -1
  161. package/dist/web-ui/public/login.js +1 -1
  162. package/dist/web-ui/public/markdown-editor.js +1 -1
  163. package/dist/web-ui/public/markdown-file-editor.js +1 -1
  164. package/dist/web-ui/public/modal-maximize.js +1 -1
  165. package/dist/web-ui/public/notifications.js +1 -1
  166. package/dist/web-ui/public/permissions.js +1 -1
  167. package/dist/web-ui/public/pr-dialog.js +1 -1
  168. package/dist/web-ui/public/roles.html +2 -2
  169. package/dist/web-ui/public/roles.js +1 -1
  170. package/dist/web-ui/public/settings.html +66 -4
  171. package/dist/web-ui/public/settings.js +1 -1
  172. package/dist/web-ui/public/setup-password.js +1 -1
  173. package/dist/web-ui/public/skills.html +2 -2
  174. package/dist/web-ui/public/skills.js +1 -1
  175. package/dist/web-ui/public/sse-client.js +1 -1
  176. package/dist/web-ui/public/sse-shared-worker.js +1 -1
  177. package/dist/web-ui/public/styles.css +1 -1
  178. package/dist/web-ui/public/task-judging-helpers.js +1 -1
  179. package/dist/web-ui/public/task.js +1 -1
  180. package/dist/web-ui/public/teams.html +2 -2
  181. package/dist/web-ui/public/teams.js +1 -1
  182. package/dist/web-ui/public/terminal.js +1 -1
  183. package/dist/web-ui/public/theme.js +1 -1
  184. package/dist/web-ui/public/users.html +2 -2
  185. package/dist/web-ui/public/users.js +1 -1
  186. package/dist/web-ui/public/variant-grouping.js +1 -1
  187. package/package.json +1 -1
  188. package/dist/web-ui/public/server-health.js +0 -1
@@ -95,11 +95,11 @@
95
95
  </svg>
96
96
  <span class="option-text">Server Settings</span>
97
97
  </button>
98
- <button type="button" class="dropdown-item admin-menu-item" id="server-health-btn">
98
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='admin.html'">
99
99
  <svg class="option-icon icon-health" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
100
100
  <path d="M22 12h-4l-3 9L9 3l-3 9H2"></path>
101
101
  </svg>
102
- <span class="option-text">Server Health</span>
102
+ <span class="option-text">Server Administration</span>
103
103
  </button>
104
104
  <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='git-history.html'">
105
105
  <svg class="option-icon icon-git-history" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -1 +1 @@
1
- import{API,Utils,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const state={'teams':[],'users':[],'roles':[],'environments':[],'teamBindings':[],'currentUser':null,'editingTeamId':null,'bindingsTeamId':null,'deletingTeamId':null,'modalSnapshot':null};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle();try{state['currentUser']=await API['getCurrentUser']();}catch{window['location']['href']='login.html';return;}await initializeAdminMenu(state['currentUser']);const _0x588e0f=state['currentUser'];if(!Permissions['hasServerPermission'](_0x588e0f,'teams:view')&&!Permissions['hasTeamPermission'](_0x588e0f,'teams:manage')){Utils['showToast']('Access\x20denied:\x20You\x20do\x20not\x20have\x20permission\x20to\x20view\x20teams','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}(Permissions['hasServerPermission'](_0x588e0f,'*')||Permissions['hasTeamPermission'](_0x588e0f,'teams:manage'))&&(document['getElementById']('create-team-btn')['hidden']=![]),bindEventListeners(),await Promise['all']([loadTeams(),loadUsers(),loadRoles(),loadEnvironments()]),renderTeams();});async function loadTeams(){const _0x4354fc=document['getElementById']('teams-loading'),_0x660b2=document['getElementById']('teams-error'),_0x543872=document['getElementById']('teams-content');try{_0x4354fc['hidden']=![],_0x660b2['hidden']=!![],_0x543872['hidden']=!![];const {teams:_0x154b45}=await API['getTeams']();state['teams']=_0x154b45||[],renderTeams(),_0x4354fc['hidden']=!![],_0x543872['hidden']=![];}catch(_0x3c8fc7){_0x4354fc['hidden']=!![],_0x660b2['hidden']=![],document['getElementById']('teams-error-message')['textContent']=_0x3c8fc7['message'];}}async function loadUsers(){try{const {users:_0x4378bd}=await API['getUsers']();state['users']=_0x4378bd||[];}catch{state['users']=[];}}async function loadRoles(){try{const {roles:_0x4675da}=await API['getRoleDefinitions']();state['roles']=_0x4675da||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x2828ec=await API['getEnvironments']();state['environments']=_0x2828ec['environments']||[];}catch{state['environments']=[];}}function renderTeams(){const _0x48e64d=document['getElementById']('teams-table-body'),_0x5ea677=document['getElementById']('team-count');if(!_0x48e64d)return;_0x5ea677&&(_0x5ea677['textContent']=state['teams']['length']+'\x20team'+(state['teams']['length']===0x1?'':'s'));if(state['teams']['length']===0x0){_0x48e64d['innerHTML']='\x0a\x20\x20\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td\x20colspan=\x223\x22\x20style=\x22text-align:\x20center;\x20color:\x20var(--color-text-secondary);\x20padding:\x202rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20No\x20teams\x20yet.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage')?'Click\x20<strong>Create\x20Team</strong>\x20to\x20get\x20started.':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20</tr>';return;}const _0x258f9d=Permissions['hasServerPermission'](state['currentUser'],'*');_0x48e64d['innerHTML']=state['teams']['map'](_0x236cb8=>{const _0x16fb16=_0x258f9d||_0x236cb8['canManageTeam'],_0x20913d=_0x258f9d||_0x236cb8['canManageMembers'],_0x3a9f75=_0x16fb16||_0x20913d,_0xcd5438=(_0x236cb8['members']||[])['length'];return'\x0a\x20\x20\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-weight:\x20600;\x22>'+Utils['escapeHtml'](_0x236cb8['name'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x236cb8['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x236cb8['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0xcd5438+'</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-actions\x22\x20style=\x22display:\x20flex;\x20gap:\x200.25rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x3a9f75?'<button\x20class=\x22btn-icon\x22\x20title=\x22Edit\x20team\x22\x20onclick=\x22window.openTeamModal(\x27'+_0x236cb8['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M11\x204H4a2\x202\x200\x200\x200-2\x202v14a2\x202\x200\x200\x200\x202\x202h14a2\x202\x200\x200\x200\x202-2v-7\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M18.5\x202.5a2.121\x202.121\x200\x200\x201\x203\x203L12\x2015l-4\x201\x201-4\x209.5-9.5z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x16fb16?'<button\x20class=\x22btn-icon\x22\x20title=\x22Access\x20bindings\x22\x20onclick=\x22window.openBindingsModal(\x27'+_0x236cb8['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M12\x2022s8-4\x208-10V5l-8-3-8\x203v7c0\x206\x208\x2010\x208\x2010z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x16fb16?'<button\x20class=\x22btn-icon\x20btn-danger\x22\x20title=\x22Delete\x20team\x22\x20onclick=\x22window.deleteTeam(\x27'+_0x236cb8['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<polyline\x20points=\x223\x206\x205\x206\x2021\x206\x22></polyline>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M19\x206v14a2\x202\x200\x200\x201-2\x202H7a2\x202\x200\x200\x201-2-2V6m3\x200V4a2\x202\x200\x200\x201\x202-2h4a2\x202\x200\x200\x201\x202\x202v2\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20</tr>';})['join']('');}function bindEventListeners(){document['getElementById']('create-team-btn')?.['addEventListener']('click',showCreateTeamModal),document['getElementById']('retry-teams-btn')?.['addEventListener']('click',loadTeams),document['getElementById']('close-team-modal')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('cancel-team')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('save-team')?.['addEventListener']('click',saveTeam),document['querySelector']('#team-modal\x20.modal-overlay')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('add-member-btn')?.['addEventListener']('click',addMember),document['getElementById']('close-bindings-modal')?.['addEventListener']('click',hideBindingsModal),document['querySelector']('#bindings-modal\x20.modal-overlay')?.['addEventListener']('click',hideBindingsModal),document['getElementById']('add-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-binding-form')['hidden']=![],document['getElementById']('add-binding-btn')['hidden']=!![],populateBindingForm();}),document['getElementById']('cancel-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![];}),document['getElementById']('save-binding-btn')?.['addEventListener']('click',saveBinding),document['getElementById']('binding-resource-type')?.['addEventListener']('change',onBindingResourceTypeChange),document['getElementById']('close-delete-team-modal')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('cancel-delete-team')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('confirm-delete-team')?.['addEventListener']('click',confirmDeleteTeam),document['querySelector']('#delete-team-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteModal);}function showCreateTeamModal(){state['editingTeamId']=null,state['modalSnapshot']={'name':'','description':''},document['getElementById']('team-modal-title')['textContent']='Create\x20Team',document['getElementById']('team-name')['value']='',document['getElementById']('team-name')['disabled']=![],document['getElementById']('team-description')['value']='',document['getElementById']('team-description')['disabled']=![],document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=!![],document['getElementById']('save-team')['hidden']=![],document['getElementById']('team-modal-footer')['hidden']=![],document['getElementById']('team-modal')['hidden']=![],setTimeout(()=>document['getElementById']('team-name')['focus'](),0x64);}window['openTeamModal']=function(_0x3ed370){const _0x2ba4d8=state['teams']['find'](_0xf0da12=>_0xf0da12['id']===_0x3ed370);if(!_0x2ba4d8)return;state['editingTeamId']=_0x3ed370;const _0x3077ec=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x431967=_0x3077ec||_0x2ba4d8['canManageTeam'],_0x4c30ca=_0x3077ec||_0x2ba4d8['canManageMembers'],_0x26a962=_0x431967,_0x16f351=_0x431967||_0x4c30ca,_0x463ad9=_0x2ba4d8['name'],_0x10c5fa=_0x2ba4d8['description']||'';state['modalSnapshot']={'name':_0x463ad9,'description':_0x10c5fa},document['getElementById']('team-modal-title')['textContent']=_0x463ad9,document['getElementById']('team-name')['value']=_0x463ad9,document['getElementById']('team-name')['disabled']=!_0x26a962,document['getElementById']('team-description')['value']=_0x10c5fa,document['getElementById']('team-description')['disabled']=!_0x26a962,document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=![],document['getElementById']('save-team')['hidden']=!_0x26a962,renderMembersList(_0x2ba4d8),updateMemberSelect(_0x2ba4d8),document['getElementById']('team-modal')['hidden']=![];};function isTeamModalDirty(){if(!state['modalSnapshot'])return![];const _0x608891=document['getElementById']('team-name')['value']['trim'](),_0x3bdd75=document['getElementById']('team-description')['value']['trim']();return _0x608891!==state['modalSnapshot']['name']||_0x3bdd75!==state['modalSnapshot']['description'];}function requestHideTeamModal(){if(isTeamModalDirty()){if(!confirm('You\x20have\x20unsaved\x20changes.\x20Discard\x20them?'))return;}hideTeamModal();}function hideTeamModal(){document['getElementById']('team-modal')['hidden']=!![],document['getElementById']('team-name')['disabled']=![],document['getElementById']('team-description')['disabled']=![],state['editingTeamId']=null,state['modalSnapshot']=null;}window['openBindingsModal']=function(_0x4c9408){const _0x3da254=state['teams']['find'](_0x3ffa53=>_0x3ffa53['id']===_0x4c9408);if(!_0x3da254)return;state['bindingsTeamId']=_0x4c9408,document['getElementById']('bindings-modal-title')['textContent']='Access\x20Bindings\x20—\x20'+_0x3da254['name'],document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('bindings-modal')['hidden']=![],loadTeamBindings(_0x4c9408);};function hideBindingsModal(){document['getElementById']('bindings-modal')['hidden']=!![],state['bindingsTeamId']=null;}function renderMembersList(_0x31b0a4){const _0x553318=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x12d233=_0x553318||_0x31b0a4['canManageMembers']||_0x31b0a4['canManageTeam'],_0x526604=_0x31b0a4['members']||[],_0x753e4d=document['getElementById']('members-list');if(_0x526604['length']===0x0){_0x753e4d['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x20margin:\x200.25rem\x200;\x22>No\x20members\x20yet</p>';return;}_0x753e4d['innerHTML']=_0x526604['map'](_0x416969=>{const _0x9e59=state['users']['find'](_0x15142f=>_0x15142f['id']===_0x416969),_0x5e804e=_0x9e59?''+Utils['escapeHtml'](_0x9e59['username'])+(_0x9e59['name']?'\x20<span\x20style=\x22color:\x20var(--color-text-secondary);\x20font-size:\x200.85em;\x22>('+Utils['escapeHtml'](_0x9e59['name'])+')</span>':''):Utils['escapeHtml'](_0x416969);return'\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20align-items:\x20center;\x20justify-content:\x20space-between;\x20padding:\x200.35rem\x200;\x20border-bottom:\x201px\x20solid\x20var(--color-border);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.875rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x5e804e+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x12d233?'<button\x20type=\x22button\x22\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.removeMemberClick(\x27'+_0x416969+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x20padding:\x200.15rem\x200.4rem;\x20font-size:\x200.8rem;\x22>Remove</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20</div>';})['join']('');const _0xdf91c9=document['getElementById']('add-member-row');if(_0xdf91c9)_0xdf91c9['style']['display']=_0x12d233?'flex':'none';}function updateMemberSelect(_0x2bbcb2){const _0x26dbe0=document['getElementById']('add-member-select');if(!_0x26dbe0)return;const _0x4944d0=new Set(_0x2bbcb2['members']||[]),_0x341df7=state['users']['filter'](_0xb44c5a=>!_0x4944d0['has'](_0xb44c5a['id']));_0x26dbe0['innerHTML']='<option\x20value=\x22\x22>Add\x20a\x20member…</option>'+_0x341df7['map'](_0x15707c=>'<option\x20value=\x22'+_0x15707c['id']+'\x22>'+Utils['escapeHtml'](_0x15707c['username'])+(_0x15707c['name']?'\x20('+Utils['escapeHtml'](_0x15707c['name'])+')':'')+'</option>')['join']('');}async function addMember(){const _0x4c02c5=document['getElementById']('add-member-select'),_0x8597d1=_0x4c02c5['value'];if(!_0x8597d1||!state['editingTeamId'])return;try{const {team:_0x33f163}=await API['addTeamMember'](state['editingTeamId'],_0x8597d1);syncTeamInState(_0x33f163),renderMembersList(_0x33f163),updateMemberSelect(_0x33f163),_0x4c02c5['value']='',Utils['showToast']('Member\x20added','success');}catch(_0x4f6b15){Utils['showToast'](_0x4f6b15['message'],'error');}}window['removeMemberClick']=async function(_0x384ad8){if(!state['editingTeamId'])return;try{const {team:_0x245652}=await API['removeTeamMember'](state['editingTeamId'],_0x384ad8);syncTeamInState(_0x245652),renderMembersList(_0x245652),updateMemberSelect(_0x245652),Utils['showToast']('Member\x20removed','success');}catch(_0x58852d){Utils['showToast'](_0x58852d['message'],'error');}};async function loadTeamBindings(_0x1614f0){const _0x227f0b=document['getElementById']('bindings-loading'),_0x2d1e47=document['getElementById']('bindings-empty'),_0x1f6f9e=document['getElementById']('bindings-list-container'),_0x3aee38=document['getElementById']('add-binding-btn');_0x227f0b['hidden']=![],_0x2d1e47['hidden']=!![],_0x1f6f9e['style']['display']='none',_0x3aee38['hidden']=!![],document['getElementById']('add-binding-form')['hidden']=!![];try{const {bindings:_0x3b71ea}=await API['getBindings']({'subject_type':'team','subject_id':_0x1614f0});state['teamBindings']=_0x3b71ea||[],_0x227f0b['hidden']=!![],state['teamBindings']['length']===0x0?_0x2d1e47['hidden']=![]:(_0x1f6f9e['style']['display']='',renderBindingsTable()),(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage'))&&(_0x3aee38['hidden']=![]);}catch(_0x4c49cb){_0x227f0b['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x4c49cb['message'],'error');}}function renderBindingsTable(){const _0x414c46=document['getElementById']('bindings-table-body');if(!_0x414c46)return;const _0x4b1d8a=Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage');_0x414c46['innerHTML']=state['teamBindings']['map'](_0x1aacf4=>{const _0x4f7611=_0x1aacf4['resource_type']==='server'?'Server':_0x1aacf4['resource_id']==='*'?'All\x20'+_0x1aacf4['resource_type']+'s':Utils['escapeHtml'](_0x1aacf4['resource_name']||_0x1aacf4['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x4f7611+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x1aacf4['role_name']||_0x1aacf4['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4b1d8a?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteBindingClick(\x27'+_0x1aacf4['id']+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x22>Remove</button>':'—')+'\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>';})['join']('');}function populateBindingForm(){const _0x140784=document['getElementById']('binding-resource-type');_0x140784['value']='environment',updateBindingFormForResourceType('environment');}function onBindingResourceTypeChange(){const _0x442905=document['getElementById']('binding-resource-type')['value'];updateBindingFormForResourceType(_0x442905);}function updateBindingFormForResourceType(_0x39a862){const _0x48a43a=document['getElementById']('binding-resource-container'),_0x4566c5=document['getElementById']('binding-resource'),_0x5c5470=document['getElementById']('binding-role');if(_0x39a862==='server')_0x48a43a['style']['display']='none';else{_0x48a43a['style']['display']='';if(_0x39a862==='environment'){const _0x42618e=new Set(state['teamBindings']['filter'](_0x28119f=>_0x28119f['resource_type']==='environment')['map'](_0x4ff8c0=>_0x4ff8c0['resource_id'])),_0x23025b=state['environments']['filter'](_0x48016f=>!_0x42618e['has'](_0x48016f['name']));_0x4566c5['innerHTML']=_0x23025b['length']?_0x23025b['map'](_0x489bd7=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x489bd7['name'])+'\x22>'+Utils['escapeHtml'](_0x489bd7['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x39a862==='team'){const _0x398d76=new Set(state['teamBindings']['filter'](_0x2a3aa1=>_0x2a3aa1['resource_type']==='team')['map'](_0x218dca=>_0x218dca['resource_id'])),_0x24c726=state['teams']['filter'](_0x1a9e94=>!_0x398d76['has'](_0x1a9e94['id']));_0x4566c5['innerHTML']=_0x24c726['length']?_0x24c726['map'](_0x3391a7=>'<option\x20value=\x22'+_0x3391a7['id']+'\x22>'+Utils['escapeHtml'](_0x3391a7['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x2211ec=state['roles']['filter'](_0x21aa57=>_0x21aa57['resource_type']===_0x39a862);_0x5c5470['innerHTML']=_0x2211ec['length']?_0x2211ec['filter'](_0x1c853e=>{const _0x4e9865=_0x39a862==='server'?undefined:_0x4566c5['value'];return!state['teamBindings']['some'](_0x484d31=>_0x484d31['resource_type']===_0x39a862&&_0x484d31['role_id']===_0x1c853e['id']&&(_0x39a862==='server'||_0x484d31['resource_id']===_0x4e9865));})['map'](_0x4afbfe=>'<option\x20value=\x22'+_0x4afbfe['id']+'\x22>'+Utils['escapeHtml'](_0x4afbfe['name'])+'</option>')['join']('')||'<option\x20value=\x22\x22>No\x20available\x20roles</option>':'<option\x20value=\x22\x22>No\x20roles\x20for\x20this\x20resource\x20type</option>';}async function saveBinding(){const _0x34398e=document['getElementById']('binding-resource-type')['value'],_0x419af5=document['getElementById']('binding-role')['value'];if(!_0x419af5||!state['bindingsTeamId'])return;const _0x44442c=_0x34398e==='server'?undefined:document['getElementById']('binding-resource')['value'];if(_0x34398e!=='server'&&!_0x44442c)return;const _0x4d41ef=document['getElementById']('save-binding-btn');_0x4d41ef['disabled']=!![],_0x4d41ef['textContent']='Adding…';try{const _0x36427b={'subject_type':'team','subject_id':state['bindingsTeamId'],'role_id':_0x419af5,'resource_type':_0x34398e};if(_0x44442c)_0x36427b['resource_id']=_0x44442c;await API['createBinding'](_0x36427b),Utils['showToast']('Binding\x20added','success'),document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![],await loadTeamBindings(state['bindingsTeamId']);}catch(_0x3bc3a2){Utils['showToast'](_0x3bc3a2['message'],'error');}finally{_0x4d41ef['disabled']=![],_0x4d41ef['textContent']='Add\x20Binding';}}window['deleteBindingClick']=async function(_0x8147a4){try{await API['deleteBinding'](_0x8147a4),Utils['showToast']('Binding\x20removed','success'),await loadTeamBindings(state['bindingsTeamId']);}catch(_0x2173f0){Utils['showToast'](_0x2173f0['message'],'error');}};async function saveTeam(){const _0x5421f2=document['getElementById']('team-name')['value']['trim'](),_0xb952c9=document['getElementById']('team-description')['value']['trim'](),_0x189a29=document['getElementById']('team-form-error'),_0x2fb9ad=document['getElementById']('save-team');if(!_0x5421f2){_0x189a29['textContent']='Team\x20name\x20is\x20required',_0x189a29['hidden']=![];return;}_0x189a29['hidden']=!![];const _0x11a667=_0x2fb9ad['textContent'];_0x2fb9ad['disabled']=!![],_0x2fb9ad['textContent']=state['editingTeamId']?'Saving…':'Creating…';try{if(state['editingTeamId']){const {team:_0x2c7903}=await API['updateTeam'](state['editingTeamId'],{'name':_0x5421f2,'description':_0xb952c9});syncTeamInState(_0x2c7903),document['getElementById']('team-modal-title')['textContent']=_0x2c7903['name'],Utils['showToast']('Team\x20updated','success');}else await API['createTeam']({'name':_0x5421f2,'description':_0xb952c9}),Utils['showToast']('Team\x20created','success');_0x2fb9ad['disabled']=![],_0x2fb9ad['textContent']=_0x11a667,hideTeamModal(),await loadTeams();}catch(_0x5ea79a){_0x189a29['textContent']=_0x5ea79a['message'],_0x189a29['hidden']=![],_0x2fb9ad['disabled']=![],_0x2fb9ad['textContent']=_0x11a667;}}window['deleteTeam']=function(_0x2d6fdd){const _0x4d7682=state['teams']['find'](_0x13f095=>_0x13f095['id']===_0x2d6fdd);if(!_0x4d7682)return;state['deletingTeamId']=_0x2d6fdd,document['getElementById']('delete-team-name')['textContent']=_0x4d7682['name'],document['getElementById']('delete-team-modal')['hidden']=![];};function hideDeleteModal(){document['getElementById']('delete-team-modal')['hidden']=!![],state['deletingTeamId']=null;}async function confirmDeleteTeam(){if(!state['deletingTeamId'])return;const _0x33513a=document['getElementById']('confirm-delete-team');_0x33513a['disabled']=!![],_0x33513a['textContent']='Deleting…';try{await API['deleteTeam'](state['deletingTeamId']),Utils['showToast']('Team\x20deleted','success'),_0x33513a['disabled']=![],_0x33513a['textContent']='Delete\x20Team',hideDeleteModal(),await loadTeams();}catch(_0x1778ec){Utils['showToast']('Failed\x20to\x20delete\x20team:\x20'+_0x1778ec['message'],'error'),_0x33513a['disabled']=![],_0x33513a['textContent']='Delete\x20Team';}}function syncTeamInState(_0x1b70d8){const _0x3e0183=state['teams']['findIndex'](_0x1945cc=>_0x1945cc['id']===_0x1b70d8['id']);if(_0x3e0183>=0x0)state['teams'][_0x3e0183]=_0x1b70d8;renderTeams();}
1
+ import{API,Utils,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const state={'teams':[],'users':[],'roles':[],'environments':[],'teamBindings':[],'currentUser':null,'editingTeamId':null,'bindingsTeamId':null,'deletingTeamId':null,'modalSnapshot':null};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle();try{state['currentUser']=await API['getCurrentUser']();}catch{window['location']['href']='login.html';return;}await initializeAdminMenu(state['currentUser']);const _0x1da5f2=state['currentUser'];if(!Permissions['hasServerPermission'](_0x1da5f2,'teams:view')&&!Permissions['hasTeamPermission'](_0x1da5f2,'teams:manage')){Utils['showToast']('Access\x20denied:\x20You\x20do\x20not\x20have\x20permission\x20to\x20view\x20teams','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}(Permissions['hasServerPermission'](_0x1da5f2,'*')||Permissions['hasTeamPermission'](_0x1da5f2,'teams:manage'))&&(document['getElementById']('create-team-btn')['hidden']=![]),bindEventListeners(),await Promise['all']([loadTeams(),loadUsers(),loadRoles(),loadEnvironments()]),renderTeams();});async function loadTeams(){const _0x253d8c=document['getElementById']('teams-loading'),_0x1bad8f=document['getElementById']('teams-error'),_0x51f3fd=document['getElementById']('teams-content');try{_0x253d8c['hidden']=![],_0x1bad8f['hidden']=!![],_0x51f3fd['hidden']=!![];const {teams:_0x2cb833}=await API['getTeams']();state['teams']=_0x2cb833||[],renderTeams(),_0x253d8c['hidden']=!![],_0x51f3fd['hidden']=![];}catch(_0x4498d4){_0x253d8c['hidden']=!![],_0x1bad8f['hidden']=![],document['getElementById']('teams-error-message')['textContent']=_0x4498d4['message'];}}async function loadUsers(){try{const {users:_0x560ae6}=await API['getUsers']();state['users']=_0x560ae6||[];}catch{state['users']=[];}}async function loadRoles(){try{const {roles:_0x50f9cf}=await API['getRoleDefinitions']();state['roles']=_0x50f9cf||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x15de23=await API['getEnvironments']();state['environments']=_0x15de23['environments']||[];}catch{state['environments']=[];}}function renderTeams(){const _0x58bd9f=document['getElementById']('teams-table-body'),_0x3af05a=document['getElementById']('team-count');if(!_0x58bd9f)return;_0x3af05a&&(_0x3af05a['textContent']=state['teams']['length']+'\x20team'+(state['teams']['length']===0x1?'':'s'));if(state['teams']['length']===0x0){_0x58bd9f['innerHTML']='\x0a\x20\x20\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td\x20colspan=\x223\x22\x20style=\x22text-align:\x20center;\x20color:\x20var(--color-text-secondary);\x20padding:\x202rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20No\x20teams\x20yet.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage')?'Click\x20<strong>Create\x20Team</strong>\x20to\x20get\x20started.':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20</tr>';return;}const _0x12dda4=Permissions['hasServerPermission'](state['currentUser'],'*');_0x58bd9f['innerHTML']=state['teams']['map'](_0x25268c=>{const _0x292466=_0x12dda4||_0x25268c['canManageTeam'],_0x5dcbe5=_0x12dda4||_0x25268c['canManageMembers'],_0x4dd12c=_0x292466||_0x5dcbe5,_0x5b1e08=(_0x25268c['members']||[])['length'];return'\x0a\x20\x20\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-weight:\x20600;\x22>'+Utils['escapeHtml'](_0x25268c['name'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x25268c['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x25268c['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x5b1e08+'</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-actions\x22\x20style=\x22display:\x20flex;\x20gap:\x200.25rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4dd12c?'<button\x20class=\x22btn-icon\x22\x20title=\x22Edit\x20team\x22\x20onclick=\x22window.openTeamModal(\x27'+_0x25268c['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M11\x204H4a2\x202\x200\x200\x200-2\x202v14a2\x202\x200\x200\x200\x202\x202h14a2\x202\x200\x200\x200\x202-2v-7\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M18.5\x202.5a2.121\x202.121\x200\x200\x201\x203\x203L12\x2015l-4\x201\x201-4\x209.5-9.5z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x292466?'<button\x20class=\x22btn-icon\x22\x20title=\x22Access\x20bindings\x22\x20onclick=\x22window.openBindingsModal(\x27'+_0x25268c['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M12\x2022s8-4\x208-10V5l-8-3-8\x203v7c0\x206\x208\x2010\x208\x2010z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x292466?'<button\x20class=\x22btn-icon\x20btn-danger\x22\x20title=\x22Delete\x20team\x22\x20onclick=\x22window.deleteTeam(\x27'+_0x25268c['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2216\x22\x20height=\x2216\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<polyline\x20points=\x223\x206\x205\x206\x2021\x206\x22></polyline>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M19\x206v14a2\x202\x200\x200\x201-2\x202H7a2\x202\x200\x200\x201-2-2V6m3\x200V4a2\x202\x200\x200\x201\x202-2h4a2\x202\x200\x200\x201\x202\x202v2\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20</tr>';})['join']('');}function bindEventListeners(){document['getElementById']('create-team-btn')?.['addEventListener']('click',showCreateTeamModal),document['getElementById']('retry-teams-btn')?.['addEventListener']('click',loadTeams),document['getElementById']('close-team-modal')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('cancel-team')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('save-team')?.['addEventListener']('click',saveTeam),document['querySelector']('#team-modal\x20.modal-overlay')?.['addEventListener']('click',requestHideTeamModal),document['getElementById']('add-member-btn')?.['addEventListener']('click',addMember),document['getElementById']('close-bindings-modal')?.['addEventListener']('click',hideBindingsModal),document['querySelector']('#bindings-modal\x20.modal-overlay')?.['addEventListener']('click',hideBindingsModal),document['getElementById']('add-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-binding-form')['hidden']=![],document['getElementById']('add-binding-btn')['hidden']=!![],populateBindingForm();}),document['getElementById']('cancel-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![];}),document['getElementById']('save-binding-btn')?.['addEventListener']('click',saveBinding),document['getElementById']('binding-resource-type')?.['addEventListener']('change',onBindingResourceTypeChange),document['getElementById']('close-delete-team-modal')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('cancel-delete-team')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('confirm-delete-team')?.['addEventListener']('click',confirmDeleteTeam),document['querySelector']('#delete-team-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteModal);}function showCreateTeamModal(){state['editingTeamId']=null,state['modalSnapshot']={'name':'','description':''},document['getElementById']('team-modal-title')['textContent']='Create\x20Team',document['getElementById']('team-name')['value']='',document['getElementById']('team-name')['disabled']=![],document['getElementById']('team-description')['value']='',document['getElementById']('team-description')['disabled']=![],document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=!![],document['getElementById']('save-team')['hidden']=![],document['getElementById']('team-modal-footer')['hidden']=![],document['getElementById']('team-modal')['hidden']=![],setTimeout(()=>document['getElementById']('team-name')['focus'](),0x64);}window['openTeamModal']=function(_0x367496){const _0x54717d=state['teams']['find'](_0x504851=>_0x504851['id']===_0x367496);if(!_0x54717d)return;state['editingTeamId']=_0x367496;const _0x495f60=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x4958a5=_0x495f60||_0x54717d['canManageTeam'],_0xb0c4b9=_0x495f60||_0x54717d['canManageMembers'],_0x315ab2=_0x4958a5,_0xc62fa4=_0x4958a5||_0xb0c4b9,_0x247d65=_0x54717d['name'],_0x56d180=_0x54717d['description']||'';state['modalSnapshot']={'name':_0x247d65,'description':_0x56d180},document['getElementById']('team-modal-title')['textContent']=_0x247d65,document['getElementById']('team-name')['value']=_0x247d65,document['getElementById']('team-name')['disabled']=!_0x315ab2,document['getElementById']('team-description')['value']=_0x56d180,document['getElementById']('team-description')['disabled']=!_0x315ab2,document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=![],document['getElementById']('save-team')['hidden']=!_0x315ab2,renderMembersList(_0x54717d),updateMemberSelect(_0x54717d),document['getElementById']('team-modal')['hidden']=![];};function isTeamModalDirty(){if(!state['modalSnapshot'])return![];const _0x495323=document['getElementById']('team-name')['value']['trim'](),_0x1daf3c=document['getElementById']('team-description')['value']['trim']();return _0x495323!==state['modalSnapshot']['name']||_0x1daf3c!==state['modalSnapshot']['description'];}function requestHideTeamModal(){if(isTeamModalDirty()){if(!confirm('You\x20have\x20unsaved\x20changes.\x20Discard\x20them?'))return;}hideTeamModal();}function hideTeamModal(){document['getElementById']('team-modal')['hidden']=!![],document['getElementById']('team-name')['disabled']=![],document['getElementById']('team-description')['disabled']=![],state['editingTeamId']=null,state['modalSnapshot']=null;}window['openBindingsModal']=function(_0x2e9cb0){const _0x3dca39=state['teams']['find'](_0x1b1a3c=>_0x1b1a3c['id']===_0x2e9cb0);if(!_0x3dca39)return;state['bindingsTeamId']=_0x2e9cb0,document['getElementById']('bindings-modal-title')['textContent']='Access\x20Bindings\x20—\x20'+_0x3dca39['name'],document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('bindings-modal')['hidden']=![],loadTeamBindings(_0x2e9cb0);};function hideBindingsModal(){document['getElementById']('bindings-modal')['hidden']=!![],state['bindingsTeamId']=null;}function renderMembersList(_0x1ea1be){const _0x1924d6=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x22dfb6=_0x1924d6||_0x1ea1be['canManageMembers']||_0x1ea1be['canManageTeam'],_0x43d48e=_0x1ea1be['members']||[],_0xc63c7=document['getElementById']('members-list');if(_0x43d48e['length']===0x0){_0xc63c7['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x20margin:\x200.25rem\x200;\x22>No\x20members\x20yet</p>';return;}_0xc63c7['innerHTML']=_0x43d48e['map'](_0x4deb84=>{const _0x101c28=state['users']['find'](_0x234cae=>_0x234cae['id']===_0x4deb84),_0x13494c=_0x101c28?''+Utils['escapeHtml'](_0x101c28['username'])+(_0x101c28['name']?'\x20<span\x20style=\x22color:\x20var(--color-text-secondary);\x20font-size:\x200.85em;\x22>('+Utils['escapeHtml'](_0x101c28['name'])+')</span>':''):Utils['escapeHtml'](_0x4deb84);return'\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20align-items:\x20center;\x20justify-content:\x20space-between;\x20padding:\x200.35rem\x200;\x20border-bottom:\x201px\x20solid\x20var(--color-border);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.875rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x13494c+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x22dfb6?'<button\x20type=\x22button\x22\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.removeMemberClick(\x27'+_0x4deb84+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x20padding:\x200.15rem\x200.4rem;\x20font-size:\x200.8rem;\x22>Remove</button>':'')+'\x0a\x20\x20\x20\x20\x20\x20</div>';})['join']('');const _0x507fec=document['getElementById']('add-member-row');if(_0x507fec)_0x507fec['style']['display']=_0x22dfb6?'flex':'none';}function updateMemberSelect(_0x4e7770){const _0x3ba618=document['getElementById']('add-member-select');if(!_0x3ba618)return;const _0xd53258=new Set(_0x4e7770['members']||[]),_0x435dff=state['users']['filter'](_0x29c90a=>!_0xd53258['has'](_0x29c90a['id']));_0x3ba618['innerHTML']='<option\x20value=\x22\x22>Add\x20a\x20member…</option>'+_0x435dff['map'](_0x51a286=>'<option\x20value=\x22'+_0x51a286['id']+'\x22>'+Utils['escapeHtml'](_0x51a286['username'])+(_0x51a286['name']?'\x20('+Utils['escapeHtml'](_0x51a286['name'])+')':'')+'</option>')['join']('');}async function addMember(){const _0x5ed987=document['getElementById']('add-member-select'),_0xf8fe65=_0x5ed987['value'];if(!_0xf8fe65||!state['editingTeamId'])return;try{const {team:_0x1b43d5}=await API['addTeamMember'](state['editingTeamId'],_0xf8fe65);syncTeamInState(_0x1b43d5),renderMembersList(_0x1b43d5),updateMemberSelect(_0x1b43d5),_0x5ed987['value']='',Utils['showToast']('Member\x20added','success');}catch(_0x24107c){Utils['showToast'](_0x24107c['message'],'error');}}window['removeMemberClick']=async function(_0x5789c5){if(!state['editingTeamId'])return;try{const {team:_0x4fd759}=await API['removeTeamMember'](state['editingTeamId'],_0x5789c5);syncTeamInState(_0x4fd759),renderMembersList(_0x4fd759),updateMemberSelect(_0x4fd759),Utils['showToast']('Member\x20removed','success');}catch(_0x513829){Utils['showToast'](_0x513829['message'],'error');}};async function loadTeamBindings(_0x4adfa1){const _0x5d1b34=document['getElementById']('bindings-loading'),_0xf8aa80=document['getElementById']('bindings-empty'),_0x314fe8=document['getElementById']('bindings-list-container'),_0x261471=document['getElementById']('add-binding-btn');_0x5d1b34['hidden']=![],_0xf8aa80['hidden']=!![],_0x314fe8['style']['display']='none',_0x261471['hidden']=!![],document['getElementById']('add-binding-form')['hidden']=!![];try{const {bindings:_0x211937}=await API['getBindings']({'subject_type':'team','subject_id':_0x4adfa1});state['teamBindings']=_0x211937||[],_0x5d1b34['hidden']=!![],state['teamBindings']['length']===0x0?_0xf8aa80['hidden']=![]:(_0x314fe8['style']['display']='',renderBindingsTable()),(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage'))&&(_0x261471['hidden']=![]);}catch(_0x2d37b4){_0x5d1b34['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x2d37b4['message'],'error');}}function renderBindingsTable(){const _0x1ba880=document['getElementById']('bindings-table-body');if(!_0x1ba880)return;const _0x489c11=Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage');_0x1ba880['innerHTML']=state['teamBindings']['map'](_0x3dd7d8=>{const _0x355082=_0x3dd7d8['resource_type']==='server'?'Server':_0x3dd7d8['resource_id']==='*'?'All\x20'+_0x3dd7d8['resource_type']+'s':Utils['escapeHtml'](_0x3dd7d8['resource_name']||_0x3dd7d8['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x355082+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x3dd7d8['role_name']||_0x3dd7d8['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x489c11?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteBindingClick(\x27'+_0x3dd7d8['id']+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x22>Remove</button>':'—')+'\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>';})['join']('');}function populateBindingForm(){const _0x144c3b=document['getElementById']('binding-resource-type');_0x144c3b['value']='environment',updateBindingFormForResourceType('environment');}function onBindingResourceTypeChange(){const _0x51aaaa=document['getElementById']('binding-resource-type')['value'];updateBindingFormForResourceType(_0x51aaaa);}function updateBindingFormForResourceType(_0x12a07f){const _0x39c0d6=document['getElementById']('binding-resource-container'),_0x428f6f=document['getElementById']('binding-resource'),_0x10dcf7=document['getElementById']('binding-role');if(_0x12a07f==='server')_0x39c0d6['style']['display']='none';else{_0x39c0d6['style']['display']='';if(_0x12a07f==='environment'){const _0x5753de=new Set(state['teamBindings']['filter'](_0x3798ae=>_0x3798ae['resource_type']==='environment')['map'](_0x55cc4d=>_0x55cc4d['resource_id'])),_0x5e52f3=state['environments']['filter'](_0x348638=>!_0x5753de['has'](_0x348638['name']));_0x428f6f['innerHTML']=_0x5e52f3['length']?_0x5e52f3['map'](_0x3deb13=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x3deb13['name'])+'\x22>'+Utils['escapeHtml'](_0x3deb13['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x12a07f==='team'){const _0x24ff4e=new Set(state['teamBindings']['filter'](_0x36e8de=>_0x36e8de['resource_type']==='team')['map'](_0x4986d4=>_0x4986d4['resource_id'])),_0x2cd8bc=state['teams']['filter'](_0x38359b=>!_0x24ff4e['has'](_0x38359b['id']));_0x428f6f['innerHTML']=_0x2cd8bc['length']?_0x2cd8bc['map'](_0x473e72=>'<option\x20value=\x22'+_0x473e72['id']+'\x22>'+Utils['escapeHtml'](_0x473e72['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x3cb9ba=state['roles']['filter'](_0x332c59=>_0x332c59['resource_type']===_0x12a07f);_0x10dcf7['innerHTML']=_0x3cb9ba['length']?_0x3cb9ba['filter'](_0x7081f4=>{const _0x4b8626=_0x12a07f==='server'?undefined:_0x428f6f['value'];return!state['teamBindings']['some'](_0x470214=>_0x470214['resource_type']===_0x12a07f&&_0x470214['role_id']===_0x7081f4['id']&&(_0x12a07f==='server'||_0x470214['resource_id']===_0x4b8626));})['map'](_0x2ddfda=>'<option\x20value=\x22'+_0x2ddfda['id']+'\x22>'+Utils['escapeHtml'](_0x2ddfda['name'])+'</option>')['join']('')||'<option\x20value=\x22\x22>No\x20available\x20roles</option>':'<option\x20value=\x22\x22>No\x20roles\x20for\x20this\x20resource\x20type</option>';}async function saveBinding(){const _0x5e5f55=document['getElementById']('binding-resource-type')['value'],_0x5c7765=document['getElementById']('binding-role')['value'];if(!_0x5c7765||!state['bindingsTeamId'])return;const _0x5432de=_0x5e5f55==='server'?undefined:document['getElementById']('binding-resource')['value'];if(_0x5e5f55!=='server'&&!_0x5432de)return;const _0x59783a=document['getElementById']('save-binding-btn');_0x59783a['disabled']=!![],_0x59783a['textContent']='Adding…';try{const _0x266659={'subject_type':'team','subject_id':state['bindingsTeamId'],'role_id':_0x5c7765,'resource_type':_0x5e5f55};if(_0x5432de)_0x266659['resource_id']=_0x5432de;await API['createBinding'](_0x266659),Utils['showToast']('Binding\x20added','success'),document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![],await loadTeamBindings(state['bindingsTeamId']);}catch(_0x1b8849){Utils['showToast'](_0x1b8849['message'],'error');}finally{_0x59783a['disabled']=![],_0x59783a['textContent']='Add\x20Binding';}}window['deleteBindingClick']=async function(_0x45282b){try{await API['deleteBinding'](_0x45282b),Utils['showToast']('Binding\x20removed','success'),await loadTeamBindings(state['bindingsTeamId']);}catch(_0x443ffd){Utils['showToast'](_0x443ffd['message'],'error');}};async function saveTeam(){const _0x36daa9=document['getElementById']('team-name')['value']['trim'](),_0x4d9f43=document['getElementById']('team-description')['value']['trim'](),_0xad1935=document['getElementById']('team-form-error'),_0x40cfa6=document['getElementById']('save-team');if(!_0x36daa9){_0xad1935['textContent']='Team\x20name\x20is\x20required',_0xad1935['hidden']=![];return;}_0xad1935['hidden']=!![];const _0x2b0748=_0x40cfa6['textContent'];_0x40cfa6['disabled']=!![],_0x40cfa6['textContent']=state['editingTeamId']?'Saving…':'Creating…';try{if(state['editingTeamId']){const {team:_0x3ae620}=await API['updateTeam'](state['editingTeamId'],{'name':_0x36daa9,'description':_0x4d9f43});syncTeamInState(_0x3ae620),document['getElementById']('team-modal-title')['textContent']=_0x3ae620['name'],Utils['showToast']('Team\x20updated','success');}else await API['createTeam']({'name':_0x36daa9,'description':_0x4d9f43}),Utils['showToast']('Team\x20created','success');_0x40cfa6['disabled']=![],_0x40cfa6['textContent']=_0x2b0748,hideTeamModal(),await loadTeams();}catch(_0x3620ec){_0xad1935['textContent']=_0x3620ec['message'],_0xad1935['hidden']=![],_0x40cfa6['disabled']=![],_0x40cfa6['textContent']=_0x2b0748;}}window['deleteTeam']=function(_0x3045db){const _0x12d14f=state['teams']['find'](_0x3e25a=>_0x3e25a['id']===_0x3045db);if(!_0x12d14f)return;state['deletingTeamId']=_0x3045db,document['getElementById']('delete-team-name')['textContent']=_0x12d14f['name'],document['getElementById']('delete-team-modal')['hidden']=![];};function hideDeleteModal(){document['getElementById']('delete-team-modal')['hidden']=!![],state['deletingTeamId']=null;}async function confirmDeleteTeam(){if(!state['deletingTeamId'])return;const _0x5ab38c=document['getElementById']('confirm-delete-team');_0x5ab38c['disabled']=!![],_0x5ab38c['textContent']='Deleting…';try{await API['deleteTeam'](state['deletingTeamId']),Utils['showToast']('Team\x20deleted','success'),_0x5ab38c['disabled']=![],_0x5ab38c['textContent']='Delete\x20Team',hideDeleteModal(),await loadTeams();}catch(_0x19a513){Utils['showToast']('Failed\x20to\x20delete\x20team:\x20'+_0x19a513['message'],'error'),_0x5ab38c['disabled']=![],_0x5ab38c['textContent']='Delete\x20Team';}}function syncTeamInState(_0x4aaf3b){const _0x48e34c=state['teams']['findIndex'](_0x3aa18a=>_0x3aa18a['id']===_0x4aaf3b['id']);if(_0x48e34c>=0x0)state['teams'][_0x48e34c]=_0x4aaf3b;renderTeams();}
@@ -1 +1 @@
1
- import{API,Utils}from'./app.js';import{Terminal}from'/vendor/xterm/5.3.0/xterm.esm.js';import{FitAddon}from'/vendor/xterm-addon-fit/0.7.0/xterm-addon-fit.esm.js';import{getCurrentTheme,initTheme,mountThemeToggle,onThemeChange}from'./theme.js';const params=Utils['getQueryParams'](),containerId=params['container'],command=(params['cmd']||'')['trim'](),useServerExec=params['server_exec']==='true',isEmbedded=params['embedded']==='true',terminalTabId=params['tabId']||'',titleEl=document['getElementById']('terminal-title'),subtitleEl=document['getElementById']('terminal-subtitle'),statusEl=document['getElementById']('terminal-status'),terminalEl=document['getElementById']('terminal-container'),closeBtn=document['getElementById']('close-terminal');initTheme();isEmbedded?(document['documentElement']['classList']['add']('terminal-embedded'),document['body']['classList']['add']('terminal-embedded')):mountThemeToggle({'targetSelectors':['.terminal-actions']});const getXtermTheme=()=>{return{'background':'#0f172a','foreground':'#e2e8f0','cursor':'#e2e8f0','cursorAccent':'#0f172a'};};closeBtn&&closeBtn['addEventListener']('click',()=>{if(isEmbedded&&window['parent']&&window['parent']!==window){window['parent']['postMessage']({'type':'coderflow-terminal-close','tabId':terminalTabId},window['location']['origin']);return;}window['close']();});if(!containerId){updateStatus('Missing\x20container\x20identifier','error');throw new Error('container\x20parameter\x20is\x20required');}document['title']='Terminal\x20·\x20'+containerId['slice'](0x0,0xc),enrichContainerDetails(containerId)['catch'](()=>{subtitleEl['textContent']='Container\x20'+containerId['substring'](0x0,0xc);});const term=new Terminal({'convertEol':!![],'cursorBlink':!![],'fontFamily':'JetBrains\x20Mono,\x20SFMono-Regular,\x20Consolas,\x20monospace','fontSize':0x10,'theme':getXtermTheme()}),fitAddon=new FitAddon();term['loadAddon'](fitAddon),term['open'](terminalEl),term['focus']();let isFitting=![];const doFit=()=>{if(isFitting)return;isFitting=!![],fitAddon['fit'](),sendResize(),term['scrollToBottom'](),setTimeout(()=>{isFitting=![];},0x32);};window['addEventListener']('resize',()=>{requestAnimationFrame(()=>{!isFitting&&doFit();});});const resizeObserver=new ResizeObserver(()=>{requestAnimationFrame(()=>{!isFitting&&doFit();});});resizeObserver['observe'](terminalEl);const socketProtocol=window['location']['protocol']==='https:'?'wss':'ws',socketUrl=new URL('/ws/containers/'+encodeURIComponent(containerId),window['location']['href']);command&&useServerExec&&socketUrl['searchParams']['set']('cmd',command);socketUrl['protocol']=socketProtocol+':';const socket=new WebSocket(socketUrl['toString']());term['onData'](_0x5829bf=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':_0x5829bf}));});let commandSent=![],hasReceivedOutput=![];socket['addEventListener']('message',_0x2ba20b=>{try{const _0x373adb=JSON['parse'](_0x2ba20b['data']);if(_0x373adb['type']==='data'&&typeof _0x373adb['data']==='string')term['write'](_0x373adb['data']),!hasReceivedOutput&&_0x373adb['data']['length']>0x0&&(hasReceivedOutput=!![],command&&!useServerExec&&!commandSent&&(commandSent=!![],setTimeout(()=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':command+'\x0d'}));},0xc8)));else{if(_0x373adb['type']==='status'&&_0x373adb['status']){if(_0x373adb['status']==='connected'){if(command&&useServerExec)updateStatus('Running:\x20'+command,'info');else command?updateStatus('Preparing:\x20'+command,'info'):updateStatus('Terminal\x20connected','success');doFit(),term['focus'](),command&&!useServerExec&&!commandSent&&setTimeout(()=>{!commandSent&&socket['readyState']===WebSocket['OPEN']&&(commandSent=!![],socket['send'](JSON['stringify']({'type':'data','data':command+'\x0d'})),updateStatus('Running:\x20'+command,'info'));},0x7d0);}else updateStatus('Session\x20'+_0x373adb['status'],_0x373adb['status']==='connected'?'success':'info');}else _0x373adb['type']==='error'&&_0x373adb['message']&&updateStatus(_0x373adb['message'],'error');}}catch(_0x50dccc){console['error']('Failed\x20to\x20parse\x20terminal\x20message',_0x50dccc);}}),socket['addEventListener']('close',_0x26ebd5=>{const _0x1544c2=_0x26ebd5['reason']||'Connection\x20closed';updateStatus(_0x1544c2,_0x26ebd5['wasClean']?'info':'error'),isEmbedded&&terminalTabId&&window['parent']&&window['parent']!==window&&window['parent']['postMessage']({'type':'coderflow-terminal-disconnected','tabId':terminalTabId},window['location']['origin']);}),socket['addEventListener']('error',_0x5d2134=>{console['error']('Terminal\x20websocket\x20error',_0x5d2134),updateStatus('Connection\x20error','error');});function sendResize(){if(socket['readyState']!==WebSocket['OPEN'])return;const _0x499899=term['cols'],_0x4878bb=term['rows'];socket['send'](JSON['stringify']({'type':'resize','cols':_0x499899,'rows':_0x4878bb}));}function updateStatus(_0x4789a4,_0x182218='info'){if(!statusEl)return;statusEl['textContent']=_0x4789a4,statusEl['dataset']['variant']=_0x182218;}async function enrichContainerDetails(_0x255a11){try{const _0x403a11=await API['getContainer'](_0x255a11);updateTerminalDetails(_0x403a11);}catch{try{const _0x3d9ded=await API['getContainers'](),_0x9532bb=(_0x3d9ded['containers']||[])['find'](_0x58e132=>_0x58e132['containerId']===_0x255a11||_0x58e132['name']===_0x255a11||_0x58e132['fullContainerId']?.['startsWith'](_0x255a11));if(_0x9532bb){updateTerminalDetails(_0x9532bb);return;}subtitleEl['textContent']='Container\x20'+_0x255a11['substring'](0x0,0xc);}catch{subtitleEl['textContent']='Container\x20'+_0x255a11['substring'](0x0,0xc);}}}function updateTerminalDetails(_0xd4502b){const _0x342205=_0xd4502b['containerId']||_0xd4502b['name']||_0xd4502b['fullContainerId']||containerId,_0x25d7f8=_0xd4502b['environment']?'Environment\x20'+_0xd4502b['environment']:'Environment\x20unknown',_0x5ee59a=_0xd4502b['defaultAgent']?'\x20·\x20Agent\x20'+_0xd4502b['defaultAgent']:'',_0x3f2c49=_0xd4502b['createdAt']?'\x20·\x20Started\x20'+Utils['formatRelativeTime'](_0xd4502b['createdAt']):'';titleEl['textContent']='Terminal\x20·\x20'+_0x342205['substring'](0x0,0xc);const _0x3483a7=command?'\x20·\x20Command\x20'+command:'';subtitleEl['textContent']=''+_0x25d7f8+_0x5ee59a+_0x3f2c49+_0x3483a7;}
1
+ import{API,Utils}from'./app.js';import{Terminal}from'/vendor/xterm/5.3.0/xterm.esm.js';import{FitAddon}from'/vendor/xterm-addon-fit/0.7.0/xterm-addon-fit.esm.js';import{getCurrentTheme,initTheme,mountThemeToggle,onThemeChange}from'./theme.js';const params=Utils['getQueryParams'](),containerId=params['container'],command=(params['cmd']||'')['trim'](),useServerExec=params['server_exec']==='true',isEmbedded=params['embedded']==='true',terminalTabId=params['tabId']||'',titleEl=document['getElementById']('terminal-title'),subtitleEl=document['getElementById']('terminal-subtitle'),statusEl=document['getElementById']('terminal-status'),terminalEl=document['getElementById']('terminal-container'),closeBtn=document['getElementById']('close-terminal');initTheme();isEmbedded?(document['documentElement']['classList']['add']('terminal-embedded'),document['body']['classList']['add']('terminal-embedded')):mountThemeToggle({'targetSelectors':['.terminal-actions']});const getXtermTheme=()=>{return{'background':'#0f172a','foreground':'#e2e8f0','cursor':'#e2e8f0','cursorAccent':'#0f172a'};};closeBtn&&closeBtn['addEventListener']('click',()=>{if(isEmbedded&&window['parent']&&window['parent']!==window){window['parent']['postMessage']({'type':'coderflow-terminal-close','tabId':terminalTabId},window['location']['origin']);return;}window['close']();});if(!containerId){updateStatus('Missing\x20container\x20identifier','error');throw new Error('container\x20parameter\x20is\x20required');}document['title']='Terminal\x20·\x20'+containerId['slice'](0x0,0xc),enrichContainerDetails(containerId)['catch'](()=>{subtitleEl['textContent']='Container\x20'+containerId['substring'](0x0,0xc);});const term=new Terminal({'convertEol':!![],'cursorBlink':!![],'fontFamily':'JetBrains\x20Mono,\x20SFMono-Regular,\x20Consolas,\x20monospace','fontSize':0x10,'theme':getXtermTheme()}),fitAddon=new FitAddon();term['loadAddon'](fitAddon),term['open'](terminalEl),term['focus']();let isFitting=![];const doFit=()=>{if(isFitting)return;isFitting=!![],fitAddon['fit'](),sendResize(),term['scrollToBottom'](),setTimeout(()=>{isFitting=![];},0x32);};window['addEventListener']('resize',()=>{requestAnimationFrame(()=>{!isFitting&&doFit();});});const resizeObserver=new ResizeObserver(()=>{requestAnimationFrame(()=>{!isFitting&&doFit();});});resizeObserver['observe'](terminalEl);const socketProtocol=window['location']['protocol']==='https:'?'wss':'ws',socketUrl=new URL('/ws/containers/'+encodeURIComponent(containerId),window['location']['href']);command&&useServerExec&&socketUrl['searchParams']['set']('cmd',command);socketUrl['protocol']=socketProtocol+':';const socket=new WebSocket(socketUrl['toString']());term['onData'](_0x314188=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':_0x314188}));});let commandSent=![],hasReceivedOutput=![];socket['addEventListener']('message',_0x814930=>{try{const _0x14f878=JSON['parse'](_0x814930['data']);if(_0x14f878['type']==='data'&&typeof _0x14f878['data']==='string')term['write'](_0x14f878['data']),!hasReceivedOutput&&_0x14f878['data']['length']>0x0&&(hasReceivedOutput=!![],command&&!useServerExec&&!commandSent&&(commandSent=!![],setTimeout(()=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':command+'\x0d'}));},0xc8)));else{if(_0x14f878['type']==='status'&&_0x14f878['status']){if(_0x14f878['status']==='connected'){if(command&&useServerExec)updateStatus('Running:\x20'+command,'info');else command?updateStatus('Preparing:\x20'+command,'info'):updateStatus('Terminal\x20connected','success');doFit(),term['focus'](),command&&!useServerExec&&!commandSent&&setTimeout(()=>{!commandSent&&socket['readyState']===WebSocket['OPEN']&&(commandSent=!![],socket['send'](JSON['stringify']({'type':'data','data':command+'\x0d'})),updateStatus('Running:\x20'+command,'info'));},0x7d0);}else updateStatus('Session\x20'+_0x14f878['status'],_0x14f878['status']==='connected'?'success':'info');}else _0x14f878['type']==='error'&&_0x14f878['message']&&updateStatus(_0x14f878['message'],'error');}}catch(_0x3648bf){console['error']('Failed\x20to\x20parse\x20terminal\x20message',_0x3648bf);}}),socket['addEventListener']('close',_0x3fc8a3=>{const _0x1fd313=_0x3fc8a3['reason']||'Connection\x20closed';updateStatus(_0x1fd313,_0x3fc8a3['wasClean']?'info':'error'),isEmbedded&&terminalTabId&&window['parent']&&window['parent']!==window&&window['parent']['postMessage']({'type':'coderflow-terminal-disconnected','tabId':terminalTabId},window['location']['origin']);}),socket['addEventListener']('error',_0x2407ef=>{console['error']('Terminal\x20websocket\x20error',_0x2407ef),updateStatus('Connection\x20error','error');});function sendResize(){if(socket['readyState']!==WebSocket['OPEN'])return;const _0xcc0bac=term['cols'],_0x16720e=term['rows'];socket['send'](JSON['stringify']({'type':'resize','cols':_0xcc0bac,'rows':_0x16720e}));}function updateStatus(_0x2baa2c,_0x437f90='info'){if(!statusEl)return;statusEl['textContent']=_0x2baa2c,statusEl['dataset']['variant']=_0x437f90;}async function enrichContainerDetails(_0x203689){try{const _0x46847b=await API['getContainer'](_0x203689);updateTerminalDetails(_0x46847b);}catch{try{const _0x3bab1d=await API['getContainers'](),_0x44cac0=(_0x3bab1d['containers']||[])['find'](_0x3b49f7=>_0x3b49f7['containerId']===_0x203689||_0x3b49f7['name']===_0x203689||_0x3b49f7['fullContainerId']?.['startsWith'](_0x203689));if(_0x44cac0){updateTerminalDetails(_0x44cac0);return;}subtitleEl['textContent']='Container\x20'+_0x203689['substring'](0x0,0xc);}catch{subtitleEl['textContent']='Container\x20'+_0x203689['substring'](0x0,0xc);}}}function updateTerminalDetails(_0x2e507a){const _0x45bf91=_0x2e507a['containerId']||_0x2e507a['name']||_0x2e507a['fullContainerId']||containerId,_0x3489bb=_0x2e507a['environment']?'Environment\x20'+_0x2e507a['environment']:'Environment\x20unknown',_0x528da1=_0x2e507a['defaultAgent']?'\x20·\x20Agent\x20'+_0x2e507a['defaultAgent']:'',_0x448b4c=_0x2e507a['createdAt']?'\x20·\x20Started\x20'+Utils['formatRelativeTime'](_0x2e507a['createdAt']):'';titleEl['textContent']='Terminal\x20·\x20'+_0x45bf91['substring'](0x0,0xc);const _0x3119c2=command?'\x20·\x20Command\x20'+command:'';subtitleEl['textContent']=''+_0x3489bb+_0x528da1+_0x448b4c+_0x3119c2;}
@@ -1 +1 @@
1
- const THEME_STORAGE_KEY='profound-coder-theme',THEME_CHANGE_EVENT='profound-theme-change',VALID_THEMES=new Set(['light','dark']),DEFAULT_TARGET_SELECTORS=['#theme-toggle-container','.header-actions','.status-actions','.terminal-actions','.top-bar'];function readStoredTheme(){try{const _0x302b78=localStorage['getItem'](THEME_STORAGE_KEY);if(_0x302b78&&VALID_THEMES['has'](_0x302b78))return _0x302b78;}catch(_0x4700ac){console['warn']('[Theme]\x20Failed\x20to\x20read\x20stored\x20theme\x20preference:',_0x4700ac);}return null;}export function getPreferredTheme(){const _0x1bb8f8=readStoredTheme();if(_0x1bb8f8)return _0x1bb8f8;const _0x144ab1=window['matchMedia']&&window['matchMedia']('(prefers-color-scheme:\x20dark)')['matches'];return _0x144ab1?'dark':'light';}export function getCurrentTheme(){const _0x11af3a=document['documentElement']['dataset']['theme'];if(_0x11af3a&&VALID_THEMES['has'](_0x11af3a))return _0x11af3a;return getPreferredTheme();}export function applyTheme(_0x2f16ad,{persist:persist=!![],emitEvent:emitEvent=!![]}={}){const _0x29566e=VALID_THEMES['has'](_0x2f16ad)?_0x2f16ad:'light';document['documentElement']['dataset']['theme']=_0x29566e,document['documentElement']['style']['colorScheme']=_0x29566e==='dark'?'dark':'light';if(persist)try{localStorage['setItem'](THEME_STORAGE_KEY,_0x29566e);}catch(_0x17d863){console['warn']('[Theme]\x20Failed\x20to\x20persist\x20theme\x20preference:',_0x17d863);}return emitEvent&&window['dispatchEvent'](new CustomEvent(THEME_CHANGE_EVENT,{'detail':{'theme':_0x29566e}})),_0x29566e;}export function initTheme(_0x3754db={}){const {emitEvent:emitEvent=![]}=_0x3754db;return applyTheme(getPreferredTheme(),{'persist':![],'emitEvent':emitEvent});}export function toggleTheme(){const _0x5703d0=getCurrentTheme()==='dark'?'light':'dark';return applyTheme(_0x5703d0);}export function onThemeChange(_0x583eb4,{runImmediately:runImmediately=![]}={}){const _0x385d33=_0x12697f=>{_0x583eb4(_0x12697f['detail']['theme']);};return window['addEventListener'](THEME_CHANGE_EVENT,_0x385d33),runImmediately&&_0x583eb4(getCurrentTheme()),()=>window['removeEventListener'](THEME_CHANGE_EVENT,_0x385d33);}export function mountThemeToggle(_0xbf3a04={}){const {targetSelectors:targetSelectors=DEFAULT_TARGET_SELECTORS}=_0xbf3a04,_0x358786=targetSelectors['map'](_0x2a193b=>document['querySelector'](_0x2a193b))['find'](Boolean),_0x48c00a=document['createElement']('button');_0x48c00a['type']='button',_0x48c00a['className']='btn-ghost\x20theme-toggle-btn',_0x48c00a['id']='theme-toggle-btn',_0x48c00a['setAttribute']('aria-pressed','false'),_0x48c00a['style']['padding']='8px',_0x48c00a['style']['lineHeight']='0',_0x48c00a['style']['width']='36px',_0x48c00a['style']['height']='36px',_0x48c00a['style']['display']='flex',_0x48c00a['style']['alignItems']='center',_0x48c00a['style']['justifyContent']='center';const _0x458246=document['createElement']('span');_0x458246['className']='theme-icon',_0x458246['style']['display']='flex',_0x48c00a['append'](_0x458246);const _0x236f70='<svg\x20xmlns=\x22http://www.w3.org/2000/svg\x22\x20width=\x2220\x22\x20height=\x2220\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22><path\x20d=\x22M21\x2012.79A9\x209\x200\x201\x201\x2011.21\x203\x207\x207\x200\x200\x200\x2021\x2012.79z\x22></path></svg>',_0x5f32bd='<svg\x20xmlns=\x22http://www.w3.org/2000/svg\x22\x20width=\x2220\x22\x20height=\x2220\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22><circle\x20cx=\x2212\x22\x20cy=\x2212\x22\x20r=\x225\x22></circle><line\x20x1=\x2212\x22\x20y1=\x221\x22\x20x2=\x2212\x22\x20y2=\x223\x22></line><line\x20x1=\x2212\x22\x20y1=\x2221\x22\x20x2=\x2212\x22\x20y2=\x2223\x22></line><line\x20x1=\x224.22\x22\x20y1=\x224.22\x22\x20x2=\x225.64\x22\x20y2=\x225.64\x22></line><line\x20x1=\x2218.36\x22\x20y1=\x2218.36\x22\x20x2=\x2219.78\x22\x20y2=\x2219.78\x22></line><line\x20x1=\x221\x22\x20y1=\x2212\x22\x20x2=\x223\x22\x20y2=\x2212\x22></line><line\x20x1=\x2221\x22\x20y1=\x2212\x22\x20x2=\x2223\x22\x20y2=\x2212\x22></line><line\x20x1=\x224.22\x22\x20y1=\x2219.78\x22\x20x2=\x225.64\x22\x20y2=\x2218.36\x22></line><line\x20x1=\x2218.36\x22\x20y1=\x225.64\x22\x20x2=\x2219.78\x22\x20y2=\x224.22\x22></line></svg>',_0x3d9cf8=_0x127e10=>{const _0x514072=_0x127e10==='dark';_0x458246['innerHTML']=_0x514072?_0x236f70:_0x5f32bd,_0x48c00a['title']=_0x514072?'Switch\x20to\x20light\x20mode':'Switch\x20to\x20dark\x20mode',_0x48c00a['dataset']['theme']=_0x127e10,_0x48c00a['setAttribute']('aria-pressed',String(_0x514072));};return _0x48c00a['addEventListener']('click',()=>{const _0x1f872a=getCurrentTheme()==='dark'?'light':'dark';applyTheme(_0x1f872a);}),_0x358786?_0x358786['appendChild'](_0x48c00a):(_0x48c00a['classList']['add']('theme-toggle-floating'),document['body']['appendChild'](_0x48c00a)),_0x3d9cf8(initTheme()),onThemeChange(_0x3d9cf8),_0x48c00a;}export{THEME_STORAGE_KEY,THEME_CHANGE_EVENT};
1
+ const THEME_STORAGE_KEY='profound-coder-theme',THEME_CHANGE_EVENT='profound-theme-change',VALID_THEMES=new Set(['light','dark']),DEFAULT_TARGET_SELECTORS=['#theme-toggle-container','.header-actions','.status-actions','.terminal-actions','.top-bar'];function readStoredTheme(){try{const _0x547eb6=localStorage['getItem'](THEME_STORAGE_KEY);if(_0x547eb6&&VALID_THEMES['has'](_0x547eb6))return _0x547eb6;}catch(_0x556233){console['warn']('[Theme]\x20Failed\x20to\x20read\x20stored\x20theme\x20preference:',_0x556233);}return null;}export function getPreferredTheme(){const _0x13fafb=readStoredTheme();if(_0x13fafb)return _0x13fafb;const _0x175780=window['matchMedia']&&window['matchMedia']('(prefers-color-scheme:\x20dark)')['matches'];return _0x175780?'dark':'light';}export function getCurrentTheme(){const _0x3bd900=document['documentElement']['dataset']['theme'];if(_0x3bd900&&VALID_THEMES['has'](_0x3bd900))return _0x3bd900;return getPreferredTheme();}export function applyTheme(_0x2d7121,{persist:persist=!![],emitEvent:emitEvent=!![]}={}){const _0x4081f6=VALID_THEMES['has'](_0x2d7121)?_0x2d7121:'light';document['documentElement']['dataset']['theme']=_0x4081f6,document['documentElement']['style']['colorScheme']=_0x4081f6==='dark'?'dark':'light';if(persist)try{localStorage['setItem'](THEME_STORAGE_KEY,_0x4081f6);}catch(_0x4eb63e){console['warn']('[Theme]\x20Failed\x20to\x20persist\x20theme\x20preference:',_0x4eb63e);}return emitEvent&&window['dispatchEvent'](new CustomEvent(THEME_CHANGE_EVENT,{'detail':{'theme':_0x4081f6}})),_0x4081f6;}export function initTheme(_0x4f86c0={}){const {emitEvent:emitEvent=![]}=_0x4f86c0;return applyTheme(getPreferredTheme(),{'persist':![],'emitEvent':emitEvent});}export function toggleTheme(){const _0x281d3b=getCurrentTheme()==='dark'?'light':'dark';return applyTheme(_0x281d3b);}export function onThemeChange(_0x1a74fc,{runImmediately:runImmediately=![]}={}){const _0x382f4a=_0x5bd2fe=>{_0x1a74fc(_0x5bd2fe['detail']['theme']);};return window['addEventListener'](THEME_CHANGE_EVENT,_0x382f4a),runImmediately&&_0x1a74fc(getCurrentTheme()),()=>window['removeEventListener'](THEME_CHANGE_EVENT,_0x382f4a);}export function mountThemeToggle(_0x151eb1={}){const {targetSelectors:targetSelectors=DEFAULT_TARGET_SELECTORS}=_0x151eb1,_0x3c8f9e=targetSelectors['map'](_0x1f54eb=>document['querySelector'](_0x1f54eb))['find'](Boolean),_0x502305=document['createElement']('button');_0x502305['type']='button',_0x502305['className']='btn-ghost\x20theme-toggle-btn',_0x502305['id']='theme-toggle-btn',_0x502305['setAttribute']('aria-pressed','false'),_0x502305['style']['padding']='8px',_0x502305['style']['lineHeight']='0',_0x502305['style']['width']='36px',_0x502305['style']['height']='36px',_0x502305['style']['display']='flex',_0x502305['style']['alignItems']='center',_0x502305['style']['justifyContent']='center';const _0x404136=document['createElement']('span');_0x404136['className']='theme-icon',_0x404136['style']['display']='flex',_0x502305['append'](_0x404136);const _0x18ebc4='<svg\x20xmlns=\x22http://www.w3.org/2000/svg\x22\x20width=\x2220\x22\x20height=\x2220\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22><path\x20d=\x22M21\x2012.79A9\x209\x200\x201\x201\x2011.21\x203\x207\x207\x200\x200\x200\x2021\x2012.79z\x22></path></svg>',_0x40db98='<svg\x20xmlns=\x22http://www.w3.org/2000/svg\x22\x20width=\x2220\x22\x20height=\x2220\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22\x20stroke-linecap=\x22round\x22\x20stroke-linejoin=\x22round\x22><circle\x20cx=\x2212\x22\x20cy=\x2212\x22\x20r=\x225\x22></circle><line\x20x1=\x2212\x22\x20y1=\x221\x22\x20x2=\x2212\x22\x20y2=\x223\x22></line><line\x20x1=\x2212\x22\x20y1=\x2221\x22\x20x2=\x2212\x22\x20y2=\x2223\x22></line><line\x20x1=\x224.22\x22\x20y1=\x224.22\x22\x20x2=\x225.64\x22\x20y2=\x225.64\x22></line><line\x20x1=\x2218.36\x22\x20y1=\x2218.36\x22\x20x2=\x2219.78\x22\x20y2=\x2219.78\x22></line><line\x20x1=\x221\x22\x20y1=\x2212\x22\x20x2=\x223\x22\x20y2=\x2212\x22></line><line\x20x1=\x2221\x22\x20y1=\x2212\x22\x20x2=\x2223\x22\x20y2=\x2212\x22></line><line\x20x1=\x224.22\x22\x20y1=\x2219.78\x22\x20x2=\x225.64\x22\x20y2=\x2218.36\x22></line><line\x20x1=\x2218.36\x22\x20y1=\x225.64\x22\x20x2=\x2219.78\x22\x20y2=\x224.22\x22></line></svg>',_0x18627c=_0x453f36=>{const _0x117c5b=_0x453f36==='dark';_0x404136['innerHTML']=_0x117c5b?_0x18ebc4:_0x40db98,_0x502305['title']=_0x117c5b?'Switch\x20to\x20light\x20mode':'Switch\x20to\x20dark\x20mode',_0x502305['dataset']['theme']=_0x453f36,_0x502305['setAttribute']('aria-pressed',String(_0x117c5b));};return _0x502305['addEventListener']('click',()=>{const _0x419dd6=getCurrentTheme()==='dark'?'light':'dark';applyTheme(_0x419dd6);}),_0x3c8f9e?_0x3c8f9e['appendChild'](_0x502305):(_0x502305['classList']['add']('theme-toggle-floating'),document['body']['appendChild'](_0x502305)),_0x18627c(initTheme()),onThemeChange(_0x18627c),_0x502305;}export{THEME_STORAGE_KEY,THEME_CHANGE_EVENT};
@@ -95,11 +95,11 @@
95
95
  </svg>
96
96
  <span class="option-text">Server Settings</span>
97
97
  </button>
98
- <button type="button" class="dropdown-item admin-menu-item" id="server-health-btn">
98
+ <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='admin.html'">
99
99
  <svg class="option-icon icon-health" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
100
100
  <path d="M22 12h-4l-3 9L9 3l-3 9H2"></path>
101
101
  </svg>
102
- <span class="option-text">Server Health</span>
102
+ <span class="option-text">Server Administration</span>
103
103
  </button>
104
104
  <button type="button" class="dropdown-item admin-menu-item" onclick="window.location.href='git-history.html'">
105
105
  <svg class="option-icon icon-git-history" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -1 +1 @@
1
- import{API,Utils,ConfirmDialog,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const state={'users':[],'editingUserId':null,'bindingsUserId':null,'deletingUserId':null,'setupLinkData':null,'emailConfigured':![],'currentUser':null,'roles':[],'environments':[],'teams':[],'userBindings':[],'bindingsDirty':![]};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle(),await checkAdminAccess(),await initializeAdminMenu(state['currentUser']),await Promise['all']([checkEmailConfig(),loadRoles(),loadEnvironments(),loadTeams()]),bindEventListeners(),await loadUsers();});async function checkAdminAccess(){try{const _0x228fe1=await API['getCurrentUser']();state['currentUser']=_0x228fe1;if(!Permissions['hasServerPermission'](_0x228fe1,'*')&&!Permissions['hasServerPermission'](_0x228fe1,'users:create')){Utils['showToast']('Access\x20denied:\x20Server\x20admin\x20privileges\x20required','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}}catch(_0x2810e8){window['location']['href']='login.html';}}async function checkEmailConfig(){try{const _0xe297c0=await API['getEmailConfig']();state['emailConfigured']=_0xe297c0['configured'];}catch(_0x1621d1){console['error']('Failed\x20to\x20check\x20email\x20config',_0x1621d1),state['emailConfigured']=![];}}async function loadRoles(){try{const {roles:_0x74f21e}=await API['getRoleDefinitions']();state['roles']=_0x74f21e||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x367289=await API['getEnvironments']();state['environments']=_0x367289['environments']||[];}catch{state['environments']=[];}}async function loadTeams(){try{const {teams:_0x48e2f5}=await API['getTeams']();state['teams']=_0x48e2f5||[];}catch{state['teams']=[];}}function bindEventListeners(){document['getElementById']('create-user-btn')?.['addEventListener']('click',showCreateUserModal),document['getElementById']('close-user-modal')?.['addEventListener']('click',hideUserModal),document['getElementById']('cancel-user')?.['addEventListener']('click',hideUserModal),document['getElementById']('save-user')?.['addEventListener']('click',saveUser),document['querySelector']('#user-modal\x20.modal-overlay')?.['addEventListener']('click',hideUserModal),document['getElementById']('close-delete-modal')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('cancel-delete')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('confirm-delete')?.['addEventListener']('click',confirmDeleteUser),document['querySelector']('#delete-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('close-setup-link-modal')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('close-setup-link')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('copy-setup-link')?.['addEventListener']('click',copySetupLink),document['getElementById']('email-setup-link')?.['addEventListener']('click',emailSetupLink),document['querySelector']('#setup-link-modal\x20.modal-overlay')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('skip-password')?.['addEventListener']('change',handleSkipPasswordChange),document['getElementById']('retry-users-btn')?.['addEventListener']('click',loadUsers),document['getElementById']('close-bindings-modal')?.['addEventListener']('click',hideAccessBindingsModal),document['getElementById']('close-bindings-modal-footer')?.['addEventListener']('click',hideAccessBindingsModal),document['querySelector']('#bindings-modal\x20.modal-overlay')?.['addEventListener']('click',hideAccessBindingsModal),document['getElementById']('add-user-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-user-binding-form')['hidden']=![],document['getElementById']('add-user-binding-btn')['hidden']=!![],populateUserBindingForm();}),document['getElementById']('cancel-user-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![];}),document['getElementById']('save-user-binding-btn')?.['addEventListener']('click',saveUserBinding),document['getElementById']('user-binding-resource-type')?.['addEventListener']('change',onUserBindingResourceTypeChange);}async function loadUsers(){const _0xbb05db=document['getElementById']('users-loading'),_0x245485=document['getElementById']('users-error'),_0x139dac=document['getElementById']('users-content');try{_0xbb05db['hidden']=![],_0x245485['hidden']=!![],_0x139dac['hidden']=!![];const _0x130921=await API['getUsers']();state['users']=_0x130921['users']||[],renderUsers(),_0xbb05db['hidden']=!![],_0x139dac['hidden']=![];}catch(_0x53a3fb){console['error']('Failed\x20to\x20load\x20users',_0x53a3fb),_0xbb05db['hidden']=!![],_0x245485['hidden']=![],document['getElementById']('users-error-message')['textContent']=_0x53a3fb['message'];}}function renderUsers(){const _0x33304e=document['getElementById']('users-table-body'),_0x41a7b8=document['getElementById']('user-count');if(!_0x33304e)return;_0x41a7b8&&(_0x41a7b8['textContent']=state['users']['length']+'\x20user'+(state['users']['length']===0x1?'':'s'));const _0x4e8030=[...state['users']]['sort']((_0x4a60f5,_0x16955b)=>{const _0xb8c948=new Date(_0x4a60f5['created_at'])['getTime'](),_0x2ffea0=new Date(_0x16955b['created_at'])['getTime']();return _0x2ffea0-_0xb8c948;});_0x33304e['innerHTML']=_0x4e8030['map'](_0x15ba05=>'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-username\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+Utils['escapeHtml'](_0x15ba05['username'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x15ba05['name'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x15ba05['email'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22access-badges\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x15ba05['isServerAdmin']?'<span\x20class=\x22role-badge\x20role-admin\x22>Server\x20Admin</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x15ba05['hasUserBinding']?'<span\x20class=\x22role-badge\x20role-user-binding\x22>User\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x15ba05['hasTeamBinding']?'<span\x20class=\x22role-badge\x20role-team-binding\x22>Team\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['formatRelativeTime'](_0x15ba05['created_at'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-actions\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x22\x20onclick=\x22window.editUser(\x27'+_0x15ba05['id']+'\x27)\x22\x20title=\x22Edit\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M11\x204H4a2\x202\x200\x200\x200-2\x202v14a2\x202\x200\x200\x200\x202\x202h14a2\x202\x200\x200\x200\x202-2v-7\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M18.5\x202.5a2.121\x202.121\x200\x200\x201\x203\x203L12\x2015l-4\x201\x201-4\x209.5-9.5z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x22\x20onclick=\x22window.showAccessBindings(\x27'+_0x15ba05['id']+'\x27)\x22\x20title=\x22Access\x20Bindings\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M12\x2022s8-4\x208-10V5l-8-3-8\x203v7c0\x206\x208\x2010\x208\x2010z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x20btn-danger\x22\x20onclick=\x22window.deleteUser(\x27'+_0x15ba05['id']+'\x27)\x22\x20title=\x22Delete\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<polyline\x20points=\x223\x206\x205\x206\x2021\x206\x22></polyline>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M19\x206v14a2\x202\x200\x200\x201-2\x202H7a2\x202\x200\x200\x201-2-2V6m3\x200V4a2\x202\x200\x200\x201\x202-2h4a2\x202\x200\x200\x201\x202\x202v2\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-secondary\x20btn-small\x22\x20onclick=\x22window.resetPassword(\x27'+_0x15ba05['id']+'\x27)\x22>Reset\x20Password</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>\x0a\x20\x20')['join']('');}window['showAccessBindings']=function(_0x495e23){const _0x2ab471=state['users']['find'](_0x5a6bb6=>_0x5a6bb6['id']===_0x495e23);if(!_0x2ab471)return;state['bindingsUserId']=_0x495e23,state['bindingsDirty']=![];const _0x236e99=document['getElementById']('bindings-modal'),_0x2c8216=document['getElementById']('bindings-modal-title');_0x2c8216['textContent']='Access\x20Bindings\x20—\x20'+_0x2ab471['name'],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],_0x236e99['hidden']=![],loadUserBindings(_0x495e23);};function hasUnsavedBindingChanges(){const _0x56436b=document['getElementById']('add-user-binding-form');return _0x56436b&&!_0x56436b['hidden'];}async function hideAccessBindingsModal(){if(hasUnsavedBindingChanges()){if(!confirm('You\x20have\x20an\x20unsaved\x20binding.\x20Discard\x20changes?'))return;document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![];}const _0x3e9f6b=document['getElementById']('bindings-modal');_0x3e9f6b['hidden']=!![];const _0x3794bd=state['bindingsDirty'];state['bindingsUserId']=null,state['userBindings']=[],state['bindingsDirty']=![],_0x3794bd&&await loadUsers();}async function loadUserBindings(_0x485f74){const _0x5e7819=document['getElementById']('user-bindings-loading'),_0x423dfd=document['getElementById']('user-bindings-empty'),_0x283fc5=document['getElementById']('user-bindings-list-container'),_0x40f9bc=document['getElementById']('add-user-binding-btn'),_0x881105=document['getElementById']('user-team-bindings-note'),_0x4beae1=document['getElementById']('user-team-bindings-text');_0x5e7819['hidden']=![],_0x423dfd['hidden']=!![],_0x283fc5['style']['display']='none',_0x40f9bc['hidden']=!![],_0x881105['hidden']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![];try{const [_0x767098,_0x420ad8]=await Promise['all']([API['getBindings']({'subject_type':'user','subject_id':_0x485f74}),API['getTeams']()]);state['userBindings']=_0x767098['bindings']||[];const _0x3b765f=(_0x420ad8['teams']||[])['filter'](_0x39016c=>(_0x39016c['members']||[])['includes'](_0x485f74)),_0x43ad59=[];if(_0x3b765f['length']>0x0){const _0x375bcb=await Promise['all'](_0x3b765f['map'](_0x1e80e7=>API['getBindings']({'subject_type':'team','subject_id':_0x1e80e7['id']})));for(let _0x23d1eb=0x0;_0x23d1eb<_0x3b765f['length'];_0x23d1eb++){const _0x98a1d=_0x375bcb[_0x23d1eb]['bindings']||[];_0x98a1d['length']>0x0&&_0x43ad59['push'](_0x3b765f[_0x23d1eb]);}}_0x5e7819['hidden']=!![];state['userBindings']['length']===0x0?_0x423dfd['hidden']=![]:(_0x283fc5['style']['display']='',renderUserBindingsTable());if(_0x43ad59['length']>0x0){const _0x23ef85=_0x43ad59['map'](_0x21e645=>_0x21e645['name']),_0x516b84=_0x23ef85['length']<=0x3?_0x23ef85['join'](',\x20'):_0x23ef85['slice'](0x0,0x3)['join'](',\x20')+(',\x20and\x20'+(_0x23ef85['length']-0x3)+'\x20more');_0x4beae1['textContent']='This\x20user\x20also\x20has\x20access\x20via\x20team\x20memberships\x20('+_0x516b84+').';}else _0x4beae1['textContent']='This\x20user\x20has\x20no\x20access\x20via\x20team\x20memberships.';_0x881105['hidden']=![],_0x40f9bc['hidden']=![];}catch(_0x2a798d){_0x5e7819['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x2a798d['message'],'error');}}function renderUserBindingsTable(){const _0x29e88d=document['getElementById']('user-bindings-table-body');if(!_0x29e88d)return;_0x29e88d['innerHTML']=state['userBindings']['map'](_0x363159=>{const _0x40a06d=_0x363159['resource_type']==='server'?'Server':_0x363159['resource_id']==='*'?'All\x20'+_0x363159['resource_type']+'s':Utils['escapeHtml'](_0x363159['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x40a06d+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x363159['role_name']||_0x363159['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteUserBindingClick(\x27'+_0x363159['id']+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x22>Remove</button>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>';})['join']('');}function populateUserBindingForm(){const _0x5a991e=document['getElementById']('user-binding-resource-type');_0x5a991e['value']='environment',updateUserBindingFormForResourceType('environment');}function onUserBindingResourceTypeChange(){const _0x342091=document['getElementById']('user-binding-resource-type')['value'];updateUserBindingFormForResourceType(_0x342091);}function updateUserBindingFormForResourceType(_0x1847fb){const _0x34b1dc=document['getElementById']('user-binding-resource-container'),_0x1f95e6=document['getElementById']('user-binding-resource'),_0x515d02=document['getElementById']('user-binding-role');if(_0x1847fb==='server')_0x34b1dc['style']['display']='none';else{_0x34b1dc['style']['display']='';if(_0x1847fb==='environment'){const _0x2a0faa=new Set(state['userBindings']['filter'](_0x2033e0=>_0x2033e0['resource_type']==='environment')['map'](_0x55be35=>_0x55be35['resource_id'])),_0x1baee3=state['environments']['filter'](_0xe2d5ab=>!_0x2a0faa['has'](_0xe2d5ab['name']));_0x1f95e6['innerHTML']=_0x1baee3['length']?_0x1baee3['map'](_0x22719e=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x22719e['name'])+'\x22>'+Utils['escapeHtml'](_0x22719e['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x1847fb==='team'){const _0x31c0fd=new Set(state['userBindings']['filter'](_0x2a1151=>_0x2a1151['resource_type']==='team')['map'](_0xc65903=>_0xc65903['resource_id'])),_0x8d42c3=state['teams']['filter'](_0x3c07a4=>!_0x31c0fd['has'](_0x3c07a4['id']));_0x1f95e6['innerHTML']=_0x8d42c3['length']?_0x8d42c3['map'](_0x7ab63a=>'<option\x20value=\x22'+_0x7ab63a['id']+'\x22>'+Utils['escapeHtml'](_0x7ab63a['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x57ed64=state['roles']['filter'](_0x3b48f0=>_0x3b48f0['resource_type']===_0x1847fb);_0x515d02['innerHTML']=_0x57ed64['length']?_0x57ed64['filter'](_0x8253f0=>{const _0x5adb9d=_0x1847fb==='server'?undefined:_0x1f95e6['value'];return!state['userBindings']['some'](_0x5fdb7d=>_0x5fdb7d['resource_type']===_0x1847fb&&_0x5fdb7d['role_id']===_0x8253f0['id']&&(_0x1847fb==='server'||_0x5fdb7d['resource_id']===_0x5adb9d));})['map'](_0x18bb6f=>'<option\x20value=\x22'+_0x18bb6f['id']+'\x22>'+Utils['escapeHtml'](_0x18bb6f['name'])+'</option>')['join']('')||'<option\x20value=\x22\x22>No\x20available\x20roles</option>':'<option\x20value=\x22\x22>No\x20roles\x20for\x20this\x20resource\x20type</option>';}async function saveUserBinding(){const _0x2f095e=document['getElementById']('user-binding-resource-type')['value'],_0x15e734=document['getElementById']('user-binding-role')['value'];if(!_0x15e734||!state['bindingsUserId'])return;const _0x2d5035=_0x2f095e==='server'?undefined:document['getElementById']('user-binding-resource')['value'];if(_0x2f095e!=='server'&&!_0x2d5035)return;const _0x3e23c1=document['getElementById']('save-user-binding-btn');_0x3e23c1['disabled']=!![],_0x3e23c1['textContent']='Adding…';try{const _0x2814f9={'subject_type':'user','subject_id':state['bindingsUserId'],'role_id':_0x15e734,'resource_type':_0x2f095e};if(_0x2d5035)_0x2814f9['resource_id']=_0x2d5035;await API['createBinding'](_0x2814f9),Utils['showToast']('Binding\x20added','success'),state['bindingsDirty']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],await loadUserBindings(state['bindingsUserId']);}catch(_0x8c8b8d){Utils['showToast'](_0x8c8b8d['message'],'error');}finally{_0x3e23c1['disabled']=![],_0x3e23c1['textContent']='Add\x20Binding';}}window['deleteUserBindingClick']=async function(_0x28395d){try{await API['deleteBinding'](_0x28395d),Utils['showToast']('Binding\x20removed','success'),state['bindingsDirty']=!![],await loadUserBindings(state['bindingsUserId']);}catch(_0xaf1bae){Utils['showToast'](_0xaf1bae['message'],'error');}};function showCreateUserModal(){state['editingUserId']=null;const _0x87f0e3=document['getElementById']('user-modal'),_0x50a9f1=document['getElementById']('modal-title'),_0x520fda=document['getElementById']('user-password'),_0x5b0f3f=document['getElementById']('password-required'),_0x67e26a=document['getElementById']('password-hint'),_0x2fbedb=document['getElementById']('skip-password-container'),_0x322a34=document['getElementById']('skip-password');_0x50a9f1['textContent']='Create\x20User',document['getElementById']('user-form')['reset'](),_0x520fda['required']=!![];if(_0x5b0f3f)_0x5b0f3f['textContent']='*';_0x2fbedb&&(_0x2fbedb['style']['display']='block',_0x322a34['checked']=![]),_0x67e26a&&(_0x67e26a['textContent']='Minimum\x208\x20characters'),_0x87f0e3['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);}window['editUser']=function(_0x5be629){const _0x5985e9=state['users']['find'](_0x385980=>_0x385980['id']===_0x5be629);if(!_0x5985e9)return;state['editingUserId']=_0x5be629;const _0x20acdb=document['getElementById']('user-modal'),_0x54fe38=document['getElementById']('modal-title'),_0x3f8b07=document['getElementById']('user-password'),_0x52d5ab=document['getElementById']('password-required'),_0x2267a1=document['getElementById']('password-hint'),_0x3ee405=document['getElementById']('skip-password-container');_0x54fe38['textContent']='Edit\x20User',document['getElementById']('user-username')['value']=_0x5985e9['username'],document['getElementById']('user-name')['value']=_0x5985e9['name'],document['getElementById']('user-email')['value']=_0x5985e9['email'],_0x3f8b07['value']='',_0x3f8b07['required']=![];if(_0x52d5ab)_0x52d5ab['textContent']='';_0x3ee405&&(_0x3ee405['style']['display']='none'),_0x2267a1&&(_0x2267a1['textContent']='Leave\x20blank\x20to\x20keep\x20current\x20password'),_0x20acdb['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);};function hideUserModal(){const _0x400659=document['getElementById']('user-modal'),_0x461010=document['getElementById']('form-error'),_0x194ea0=document['getElementById']('save-user');_0x400659['hidden']=!![],_0x461010['hidden']=!![],state['editingUserId']=null,_0x194ea0&&(_0x194ea0['disabled']=![],_0x194ea0['textContent']='Save\x20User');}async function saveUser(){const _0x1115b9=document['getElementById']('user-form'),_0x2ddfe9=document['getElementById']('skip-password')?.['checked']||![];if(!_0x2ddfe9&&!_0x1115b9['checkValidity']()){_0x1115b9['reportValidity']();return;}const _0x2094ea=document['getElementById']('form-error'),_0x36ede9=document['getElementById']('save-user'),_0x1f5b10=document['getElementById']('user-username')['value']['trim'](),_0x498fa9=document['getElementById']('user-name')['value']['trim'](),_0x1f20fa=document['getElementById']('user-email')['value']['trim'](),_0x504422=document['getElementById']('user-password')['value'];if(!_0x1f5b10||!_0x498fa9||!_0x1f20fa){_0x2094ea['textContent']='Please\x20fill\x20in\x20all\x20required\x20fields',_0x2094ea['hidden']=![],_0x2094ea['scrollIntoView']({'behavior':'smooth','block':'nearest'});return;}_0x2094ea['hidden']=!![];const _0x360cb2=_0x36ede9['textContent'];_0x36ede9['disabled']=!![],_0x36ede9['textContent']=state['editingUserId']?'Updating...':'Creating...';try{if(state['editingUserId']){const _0x3c0b7f={'username':_0x1f5b10,'name':_0x498fa9,'email':_0x1f20fa};_0x504422&&(_0x3c0b7f['password']=_0x504422),await API['updateUser'](state['editingUserId'],_0x3c0b7f),Utils['showToast']('User\x20updated\x20successfully','success'),await loadUsers(),hideUserModal();}else{const _0x452ff9={'username':_0x1f5b10,'name':_0x498fa9,'email':_0x1f20fa};if(!_0x2ddfe9){if(!_0x504422)throw new Error('Password\x20is\x20required\x20for\x20new\x20users');_0x452ff9['password']=_0x504422;}const _0x25858d=await API['createUser'](_0x452ff9),_0x2973dc=_0x25858d['user'];if(_0x2ddfe9||!_0x504422){const _0x358539=await API['createPasswordToken'](_0x2973dc['id'],'setup',![]);state['setupLinkData']={'username':_0x2973dc['username'],'email':_0x2973dc['email'],'url':_0x358539['token']['setupUrl'],'userId':_0x2973dc['id'],'type':'setup','emailSent':![]},await loadUsers(),hideUserModal(),showSetupLinkModal();}else Utils['showToast']('User\x20created\x20successfully','success'),await loadUsers(),hideUserModal();}}catch(_0xc29009){console['error']('Failed\x20to\x20save\x20user',_0xc29009),_0x2094ea['textContent']=_0xc29009['message'],_0x2094ea['hidden']=![],_0x2094ea['scrollIntoView']({'behavior':'smooth','block':'nearest'}),_0x36ede9['disabled']=![],_0x36ede9['textContent']=_0x360cb2;}}window['deleteUser']=function(_0x58f782){const _0x13065b=state['users']['find'](_0x48e7db=>_0x48e7db['id']===_0x58f782);if(!_0x13065b)return;state['deletingUserId']=_0x58f782;const _0x231527=document['getElementById']('delete-modal'),_0x39f070=document['getElementById']('delete-user-name');_0x39f070['textContent']=_0x13065b['name']+'\x20('+_0x13065b['username']+')',_0x231527['hidden']=![];};function hideDeleteModal(){const _0x1199cf=document['getElementById']('delete-modal');_0x1199cf['hidden']=!![],state['deletingUserId']=null;const _0xb7f281=document['getElementById']('confirm-delete');_0xb7f281&&(_0xb7f281['disabled']=![],_0xb7f281['textContent']='Delete\x20User');}async function confirmDeleteUser(){if(!state['deletingUserId'])return;const _0x44f46c=document['getElementById']('confirm-delete'),_0x4899b0=_0x44f46c['textContent'];_0x44f46c['disabled']=!![],_0x44f46c['textContent']='Deleting...';try{await API['deleteUser'](state['deletingUserId']),Utils['showToast']('User\x20deleted\x20successfully','success'),await loadUsers(),hideDeleteModal();}catch(_0x527e2d){console['error']('Failed\x20to\x20delete\x20user',_0x527e2d),Utils['showToast']('Failed\x20to\x20delete\x20user:\x20'+_0x527e2d['message'],'error'),_0x44f46c['disabled']=![],_0x44f46c['textContent']=_0x4899b0;}}function handleSkipPasswordChange(_0x5c94fd){const _0x2740db=document['getElementById']('user-password'),_0x23e917=_0x5c94fd['target']['checked'];_0x23e917?(_0x2740db['required']=![],_0x2740db['disabled']=!![],_0x2740db['value']=''):(_0x2740db['required']=!![],_0x2740db['disabled']=![]);}function showSetupLinkModal(){if(!state['setupLinkData'])return;const _0x53179f=document['getElementById']('setup-link-modal'),_0x3431ef=document['getElementById']('setup-link-username'),_0x3b1701=document['getElementById']('setup-link-url'),_0xc5dc0a=document['getElementById']('email-setup-link'),_0xf48070=document['getElementById']('email-button-text');_0x3431ef['textContent']=state['setupLinkData']['username'],_0x3b1701['textContent']=state['setupLinkData']['url'],_0xc5dc0a&&_0xf48070&&(_0xc5dc0a['disabled']=![],_0xf48070['textContent']='Email\x20Link',state['emailConfigured']&&!state['setupLinkData']['emailSent']?_0xc5dc0a['style']['display']='inline-block':_0xc5dc0a['style']['display']='none'),_0x53179f['hidden']=![];}function hideSetupLinkModal(){const _0x402123=document['getElementById']('setup-link-modal');_0x402123['hidden']=!![],state['setupLinkData']=null;}async function copySetupLink(){if(!state['setupLinkData'])return;try{await navigator['clipboard']['writeText'](state['setupLinkData']['url']),Utils['showToast']('Link\x20copied\x20to\x20clipboard','success');}catch(_0x164077){console['error']('Failed\x20to\x20copy\x20link',_0x164077),Utils['showToast']('Failed\x20to\x20copy\x20link','error');}}async function emailSetupLink(){if(!state['setupLinkData'])return;const _0x22e95f=document['getElementById']('email-setup-link'),_0x59695a=document['getElementById']('email-button-text');if(!_0x22e95f||!_0x59695a)return;const _0x5f4d47=_0x59695a['textContent'];_0x22e95f['disabled']=!![],_0x59695a['textContent']='Sending...';try{const _0x42d2ec=await API['createPasswordToken'](state['setupLinkData']['userId'],state['setupLinkData']['type'],!![]);if(_0x42d2ec['emailSent'])Utils['showToast']('Email\x20sent\x20to\x20'+state['setupLinkData']['email'],'success'),state['setupLinkData']['emailSent']=!![],_0x22e95f['style']['display']='none';else{const _0x3ccebc=_0x42d2ec['emailError']||'Failed\x20to\x20send\x20email';Utils['showToast'](_0x3ccebc,'error'),_0x22e95f['disabled']=![],_0x59695a['textContent']=_0x5f4d47;}}catch(_0x35bebc){console['error']('Failed\x20to\x20email\x20setup\x20link',_0x35bebc),Utils['showToast']('Failed\x20to\x20send\x20email:\x20'+_0x35bebc['message'],'error'),_0x22e95f['disabled']=![],_0x59695a['textContent']=_0x5f4d47;}}window['resetPassword']=async function(_0x23b2b1){const _0x4d93d2=state['users']['find'](_0xb26310=>_0xb26310['id']===_0x23b2b1);if(!_0x4d93d2)return;const _0x356006=await ConfirmDialog['show']({'title':'Reset\x20Password','message':'Generate\x20a\x20password\x20reset\x20link\x20for\x20'+_0x4d93d2['name']+'\x20('+_0x4d93d2['username']+')?\x20This\x20will\x20create\x20a\x20link\x20that\x20they\x20can\x20use\x20to\x20set\x20a\x20new\x20password.','confirmText':'Generate\x20Link'});if(!_0x356006)return;try{const _0x3e8e90=await API['createPasswordToken'](_0x23b2b1,'reset',![]);state['setupLinkData']={'username':_0x4d93d2['username'],'email':_0x4d93d2['email'],'url':_0x3e8e90['token']['setupUrl'],'userId':_0x4d93d2['id'],'type':'reset','emailSent':![]},showSetupLinkModal();}catch(_0x3c22fe){console['error']('Failed\x20to\x20create\x20password\x20reset\x20link',_0x3c22fe),Utils['showToast']('Failed\x20to\x20create\x20password\x20reset\x20link:\x20'+_0x3c22fe['message'],'error');}};
1
+ import{API,Utils,ConfirmDialog,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const state={'users':[],'editingUserId':null,'bindingsUserId':null,'deletingUserId':null,'setupLinkData':null,'emailConfigured':![],'currentUser':null,'roles':[],'environments':[],'teams':[],'userBindings':[],'bindingsDirty':![]};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle(),await checkAdminAccess(),await initializeAdminMenu(state['currentUser']),await Promise['all']([checkEmailConfig(),loadRoles(),loadEnvironments(),loadTeams()]),bindEventListeners(),await loadUsers();});async function checkAdminAccess(){try{const _0x15af30=await API['getCurrentUser']();state['currentUser']=_0x15af30;if(!Permissions['hasServerPermission'](_0x15af30,'*')&&!Permissions['hasServerPermission'](_0x15af30,'users:create')){Utils['showToast']('Access\x20denied:\x20Server\x20admin\x20privileges\x20required','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}}catch(_0x3a4b41){window['location']['href']='login.html';}}async function checkEmailConfig(){try{const _0x3d44f2=await API['getEmailConfig']();state['emailConfigured']=_0x3d44f2['configured'];}catch(_0xc82826){console['error']('Failed\x20to\x20check\x20email\x20config',_0xc82826),state['emailConfigured']=![];}}async function loadRoles(){try{const {roles:_0x3a716d}=await API['getRoleDefinitions']();state['roles']=_0x3a716d||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x28a3b9=await API['getEnvironments']();state['environments']=_0x28a3b9['environments']||[];}catch{state['environments']=[];}}async function loadTeams(){try{const {teams:_0x2e263d}=await API['getTeams']();state['teams']=_0x2e263d||[];}catch{state['teams']=[];}}function bindEventListeners(){document['getElementById']('create-user-btn')?.['addEventListener']('click',showCreateUserModal),document['getElementById']('close-user-modal')?.['addEventListener']('click',hideUserModal),document['getElementById']('cancel-user')?.['addEventListener']('click',hideUserModal),document['getElementById']('save-user')?.['addEventListener']('click',saveUser),document['querySelector']('#user-modal\x20.modal-overlay')?.['addEventListener']('click',hideUserModal),document['getElementById']('close-delete-modal')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('cancel-delete')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('confirm-delete')?.['addEventListener']('click',confirmDeleteUser),document['querySelector']('#delete-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteModal),document['getElementById']('close-setup-link-modal')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('close-setup-link')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('copy-setup-link')?.['addEventListener']('click',copySetupLink),document['getElementById']('email-setup-link')?.['addEventListener']('click',emailSetupLink),document['querySelector']('#setup-link-modal\x20.modal-overlay')?.['addEventListener']('click',hideSetupLinkModal),document['getElementById']('skip-password')?.['addEventListener']('change',handleSkipPasswordChange),document['getElementById']('retry-users-btn')?.['addEventListener']('click',loadUsers),document['getElementById']('close-bindings-modal')?.['addEventListener']('click',hideAccessBindingsModal),document['getElementById']('close-bindings-modal-footer')?.['addEventListener']('click',hideAccessBindingsModal),document['querySelector']('#bindings-modal\x20.modal-overlay')?.['addEventListener']('click',hideAccessBindingsModal),document['getElementById']('add-user-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-user-binding-form')['hidden']=![],document['getElementById']('add-user-binding-btn')['hidden']=!![],populateUserBindingForm();}),document['getElementById']('cancel-user-binding-btn')?.['addEventListener']('click',()=>{document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![];}),document['getElementById']('save-user-binding-btn')?.['addEventListener']('click',saveUserBinding),document['getElementById']('user-binding-resource-type')?.['addEventListener']('change',onUserBindingResourceTypeChange);}async function loadUsers(){const _0xcc9bcd=document['getElementById']('users-loading'),_0x176306=document['getElementById']('users-error'),_0x5c66a9=document['getElementById']('users-content');try{_0xcc9bcd['hidden']=![],_0x176306['hidden']=!![],_0x5c66a9['hidden']=!![];const _0x79432b=await API['getUsers']();state['users']=_0x79432b['users']||[],renderUsers(),_0xcc9bcd['hidden']=!![],_0x5c66a9['hidden']=![];}catch(_0x36fbe3){console['error']('Failed\x20to\x20load\x20users',_0x36fbe3),_0xcc9bcd['hidden']=!![],_0x176306['hidden']=![],document['getElementById']('users-error-message')['textContent']=_0x36fbe3['message'];}}function renderUsers(){const _0x3d7bb5=document['getElementById']('users-table-body'),_0x2cc407=document['getElementById']('user-count');if(!_0x3d7bb5)return;_0x2cc407&&(_0x2cc407['textContent']=state['users']['length']+'\x20user'+(state['users']['length']===0x1?'':'s'));const _0xcb2535=[...state['users']]['sort']((_0x333482,_0x4447aa)=>{const _0xee4dc1=new Date(_0x333482['created_at'])['getTime'](),_0x1d3615=new Date(_0x4447aa['created_at'])['getTime']();return _0x1d3615-_0xee4dc1;});_0x3d7bb5['innerHTML']=_0xcb2535['map'](_0x4cd748=>'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-username\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+Utils['escapeHtml'](_0x4cd748['username'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x4cd748['name'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x4cd748['email'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22access-badges\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4cd748['isServerAdmin']?'<span\x20class=\x22role-badge\x20role-admin\x22>Server\x20Admin</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4cd748['hasUserBinding']?'<span\x20class=\x22role-badge\x20role-user-binding\x22>User\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4cd748['hasTeamBinding']?'<span\x20class=\x22role-badge\x20role-team-binding\x22>Team\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['formatRelativeTime'](_0x4cd748['created_at'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22user-actions\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x22\x20onclick=\x22window.editUser(\x27'+_0x4cd748['id']+'\x27)\x22\x20title=\x22Edit\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M11\x204H4a2\x202\x200\x200\x200-2\x202v14a2\x202\x200\x200\x200\x202\x202h14a2\x202\x200\x200\x200\x202-2v-7\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M18.5\x202.5a2.121\x202.121\x200\x200\x201\x203\x203L12\x2015l-4\x201\x201-4\x209.5-9.5z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x22\x20onclick=\x22window.showAccessBindings(\x27'+_0x4cd748['id']+'\x27)\x22\x20title=\x22Access\x20Bindings\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M12\x2022s8-4\x208-10V5l-8-3-8\x203v7c0\x206\x208\x2010\x208\x2010z\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-icon\x20btn-small\x20btn-danger\x22\x20onclick=\x22window.deleteUser(\x27'+_0x4cd748['id']+'\x27)\x22\x20title=\x22Delete\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<svg\x20width=\x2214\x22\x20height=\x2214\x22\x20viewBox=\x220\x200\x2024\x2024\x22\x20fill=\x22none\x22\x20stroke=\x22currentColor\x22\x20stroke-width=\x222\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<polyline\x20points=\x223\x206\x205\x206\x2021\x206\x22></polyline>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<path\x20d=\x22M19\x206v14a2\x202\x200\x200\x201-2\x202H7a2\x202\x200\x200\x201-2-2V6m3\x200V4a2\x202\x200\x200\x201\x202-2h4a2\x202\x200\x200\x201\x202\x202v2\x22></path>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</svg>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-secondary\x20btn-small\x22\x20onclick=\x22window.resetPassword(\x27'+_0x4cd748['id']+'\x27)\x22>Reset\x20Password</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>\x0a\x20\x20')['join']('');}window['showAccessBindings']=function(_0x4a7bbd){const _0x302091=state['users']['find'](_0x555017=>_0x555017['id']===_0x4a7bbd);if(!_0x302091)return;state['bindingsUserId']=_0x4a7bbd,state['bindingsDirty']=![];const _0x59da57=document['getElementById']('bindings-modal'),_0x4e74c7=document['getElementById']('bindings-modal-title');_0x4e74c7['textContent']='Access\x20Bindings\x20—\x20'+_0x302091['name'],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],_0x59da57['hidden']=![],loadUserBindings(_0x4a7bbd);};function hasUnsavedBindingChanges(){const _0x5f1079=document['getElementById']('add-user-binding-form');return _0x5f1079&&!_0x5f1079['hidden'];}async function hideAccessBindingsModal(){if(hasUnsavedBindingChanges()){if(!confirm('You\x20have\x20an\x20unsaved\x20binding.\x20Discard\x20changes?'))return;document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![];}const _0x560390=document['getElementById']('bindings-modal');_0x560390['hidden']=!![];const _0x48e696=state['bindingsDirty'];state['bindingsUserId']=null,state['userBindings']=[],state['bindingsDirty']=![],_0x48e696&&await loadUsers();}async function loadUserBindings(_0xbbbce1){const _0x27fc98=document['getElementById']('user-bindings-loading'),_0x55e71b=document['getElementById']('user-bindings-empty'),_0x2f3e11=document['getElementById']('user-bindings-list-container'),_0x17158a=document['getElementById']('add-user-binding-btn'),_0x1f41aa=document['getElementById']('user-team-bindings-note'),_0x29d87=document['getElementById']('user-team-bindings-text');_0x27fc98['hidden']=![],_0x55e71b['hidden']=!![],_0x2f3e11['style']['display']='none',_0x17158a['hidden']=!![],_0x1f41aa['hidden']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![];try{const [_0x54d236,_0x160c47]=await Promise['all']([API['getBindings']({'subject_type':'user','subject_id':_0xbbbce1}),API['getTeams']()]);state['userBindings']=_0x54d236['bindings']||[];const _0x54e7fd=(_0x160c47['teams']||[])['filter'](_0x25cb31=>(_0x25cb31['members']||[])['includes'](_0xbbbce1)),_0x3e4500=[];if(_0x54e7fd['length']>0x0){const _0x4666b9=await Promise['all'](_0x54e7fd['map'](_0x1fff75=>API['getBindings']({'subject_type':'team','subject_id':_0x1fff75['id']})));for(let _0x23119f=0x0;_0x23119f<_0x54e7fd['length'];_0x23119f++){const _0x308759=_0x4666b9[_0x23119f]['bindings']||[];_0x308759['length']>0x0&&_0x3e4500['push'](_0x54e7fd[_0x23119f]);}}_0x27fc98['hidden']=!![];state['userBindings']['length']===0x0?_0x55e71b['hidden']=![]:(_0x2f3e11['style']['display']='',renderUserBindingsTable());if(_0x3e4500['length']>0x0){const _0x6edfc6=_0x3e4500['map'](_0x49ae48=>_0x49ae48['name']),_0x152b33=_0x6edfc6['length']<=0x3?_0x6edfc6['join'](',\x20'):_0x6edfc6['slice'](0x0,0x3)['join'](',\x20')+(',\x20and\x20'+(_0x6edfc6['length']-0x3)+'\x20more');_0x29d87['textContent']='This\x20user\x20also\x20has\x20access\x20via\x20team\x20memberships\x20('+_0x152b33+').';}else _0x29d87['textContent']='This\x20user\x20has\x20no\x20access\x20via\x20team\x20memberships.';_0x1f41aa['hidden']=![],_0x17158a['hidden']=![];}catch(_0x440f93){_0x27fc98['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x440f93['message'],'error');}}function renderUserBindingsTable(){const _0x256ab0=document['getElementById']('user-bindings-table-body');if(!_0x256ab0)return;_0x256ab0['innerHTML']=state['userBindings']['map'](_0x413d47=>{const _0x51c84c=_0x413d47['resource_type']==='server'?'Server':_0x413d47['resource_id']==='*'?'All\x20'+_0x413d47['resource_type']+'s':Utils['escapeHtml'](_0x413d47['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x51c84c+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x413d47['role_name']||_0x413d47['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteUserBindingClick(\x27'+_0x413d47['id']+'\x27)\x22\x20style=\x22color:\x20var(--color-danger);\x22>Remove</button>\x0a\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20</tr>';})['join']('');}function populateUserBindingForm(){const _0x171637=document['getElementById']('user-binding-resource-type');_0x171637['value']='environment',updateUserBindingFormForResourceType('environment');}function onUserBindingResourceTypeChange(){const _0x383205=document['getElementById']('user-binding-resource-type')['value'];updateUserBindingFormForResourceType(_0x383205);}function updateUserBindingFormForResourceType(_0x427364){const _0x26cf58=document['getElementById']('user-binding-resource-container'),_0x2760a8=document['getElementById']('user-binding-resource'),_0x4d0ad3=document['getElementById']('user-binding-role');if(_0x427364==='server')_0x26cf58['style']['display']='none';else{_0x26cf58['style']['display']='';if(_0x427364==='environment'){const _0x2f8988=new Set(state['userBindings']['filter'](_0x38ca83=>_0x38ca83['resource_type']==='environment')['map'](_0x2fd509=>_0x2fd509['resource_id'])),_0x4c591d=state['environments']['filter'](_0x52efc7=>!_0x2f8988['has'](_0x52efc7['name']));_0x2760a8['innerHTML']=_0x4c591d['length']?_0x4c591d['map'](_0x62cfed=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x62cfed['name'])+'\x22>'+Utils['escapeHtml'](_0x62cfed['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x427364==='team'){const _0x3aa531=new Set(state['userBindings']['filter'](_0x27e0d6=>_0x27e0d6['resource_type']==='team')['map'](_0xb7fdf4=>_0xb7fdf4['resource_id'])),_0x4bda0e=state['teams']['filter'](_0xba94e7=>!_0x3aa531['has'](_0xba94e7['id']));_0x2760a8['innerHTML']=_0x4bda0e['length']?_0x4bda0e['map'](_0x430d9e=>'<option\x20value=\x22'+_0x430d9e['id']+'\x22>'+Utils['escapeHtml'](_0x430d9e['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x4d8a16=state['roles']['filter'](_0x5a4e9a=>_0x5a4e9a['resource_type']===_0x427364);_0x4d0ad3['innerHTML']=_0x4d8a16['length']?_0x4d8a16['filter'](_0x1c8889=>{const _0x161992=_0x427364==='server'?undefined:_0x2760a8['value'];return!state['userBindings']['some'](_0x295270=>_0x295270['resource_type']===_0x427364&&_0x295270['role_id']===_0x1c8889['id']&&(_0x427364==='server'||_0x295270['resource_id']===_0x161992));})['map'](_0x4a73ff=>'<option\x20value=\x22'+_0x4a73ff['id']+'\x22>'+Utils['escapeHtml'](_0x4a73ff['name'])+'</option>')['join']('')||'<option\x20value=\x22\x22>No\x20available\x20roles</option>':'<option\x20value=\x22\x22>No\x20roles\x20for\x20this\x20resource\x20type</option>';}async function saveUserBinding(){const _0x4a6cf8=document['getElementById']('user-binding-resource-type')['value'],_0x218e21=document['getElementById']('user-binding-role')['value'];if(!_0x218e21||!state['bindingsUserId'])return;const _0x3d98d0=_0x4a6cf8==='server'?undefined:document['getElementById']('user-binding-resource')['value'];if(_0x4a6cf8!=='server'&&!_0x3d98d0)return;const _0x1778ff=document['getElementById']('save-user-binding-btn');_0x1778ff['disabled']=!![],_0x1778ff['textContent']='Adding…';try{const _0x58957b={'subject_type':'user','subject_id':state['bindingsUserId'],'role_id':_0x218e21,'resource_type':_0x4a6cf8};if(_0x3d98d0)_0x58957b['resource_id']=_0x3d98d0;await API['createBinding'](_0x58957b),Utils['showToast']('Binding\x20added','success'),state['bindingsDirty']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],await loadUserBindings(state['bindingsUserId']);}catch(_0x3e64b1){Utils['showToast'](_0x3e64b1['message'],'error');}finally{_0x1778ff['disabled']=![],_0x1778ff['textContent']='Add\x20Binding';}}window['deleteUserBindingClick']=async function(_0x405c30){try{await API['deleteBinding'](_0x405c30),Utils['showToast']('Binding\x20removed','success'),state['bindingsDirty']=!![],await loadUserBindings(state['bindingsUserId']);}catch(_0x2ad5b6){Utils['showToast'](_0x2ad5b6['message'],'error');}};function showCreateUserModal(){state['editingUserId']=null;const _0x4b7283=document['getElementById']('user-modal'),_0x173d71=document['getElementById']('modal-title'),_0x681484=document['getElementById']('user-password'),_0x21765b=document['getElementById']('password-required'),_0x39e0db=document['getElementById']('password-hint'),_0x491a9c=document['getElementById']('skip-password-container'),_0x38ee83=document['getElementById']('skip-password');_0x173d71['textContent']='Create\x20User',document['getElementById']('user-form')['reset'](),_0x681484['required']=!![];if(_0x21765b)_0x21765b['textContent']='*';_0x491a9c&&(_0x491a9c['style']['display']='block',_0x38ee83['checked']=![]),_0x39e0db&&(_0x39e0db['textContent']='Minimum\x208\x20characters'),_0x4b7283['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);}window['editUser']=function(_0x295606){const _0x2a6940=state['users']['find'](_0x131272=>_0x131272['id']===_0x295606);if(!_0x2a6940)return;state['editingUserId']=_0x295606;const _0xb426a9=document['getElementById']('user-modal'),_0xf243f8=document['getElementById']('modal-title'),_0x2a2b1a=document['getElementById']('user-password'),_0x597c7c=document['getElementById']('password-required'),_0x28a2f1=document['getElementById']('password-hint'),_0x30a45a=document['getElementById']('skip-password-container');_0xf243f8['textContent']='Edit\x20User',document['getElementById']('user-username')['value']=_0x2a6940['username'],document['getElementById']('user-name')['value']=_0x2a6940['name'],document['getElementById']('user-email')['value']=_0x2a6940['email'],_0x2a2b1a['value']='',_0x2a2b1a['required']=![];if(_0x597c7c)_0x597c7c['textContent']='';_0x30a45a&&(_0x30a45a['style']['display']='none'),_0x28a2f1&&(_0x28a2f1['textContent']='Leave\x20blank\x20to\x20keep\x20current\x20password'),_0xb426a9['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);};function hideUserModal(){const _0x239697=document['getElementById']('user-modal'),_0x469ef0=document['getElementById']('form-error'),_0x2460bb=document['getElementById']('save-user');_0x239697['hidden']=!![],_0x469ef0['hidden']=!![],state['editingUserId']=null,_0x2460bb&&(_0x2460bb['disabled']=![],_0x2460bb['textContent']='Save\x20User');}async function saveUser(){const _0x4a9537=document['getElementById']('user-form'),_0x48a763=document['getElementById']('skip-password')?.['checked']||![];if(!_0x48a763&&!_0x4a9537['checkValidity']()){_0x4a9537['reportValidity']();return;}const _0x43cb5d=document['getElementById']('form-error'),_0x2d2f92=document['getElementById']('save-user'),_0x3e298a=document['getElementById']('user-username')['value']['trim'](),_0x41c661=document['getElementById']('user-name')['value']['trim'](),_0x28db28=document['getElementById']('user-email')['value']['trim'](),_0x29559d=document['getElementById']('user-password')['value'];if(!_0x3e298a||!_0x41c661||!_0x28db28){_0x43cb5d['textContent']='Please\x20fill\x20in\x20all\x20required\x20fields',_0x43cb5d['hidden']=![],_0x43cb5d['scrollIntoView']({'behavior':'smooth','block':'nearest'});return;}_0x43cb5d['hidden']=!![];const _0x595e11=_0x2d2f92['textContent'];_0x2d2f92['disabled']=!![],_0x2d2f92['textContent']=state['editingUserId']?'Updating...':'Creating...';try{if(state['editingUserId']){const _0x1b336b={'username':_0x3e298a,'name':_0x41c661,'email':_0x28db28};_0x29559d&&(_0x1b336b['password']=_0x29559d),await API['updateUser'](state['editingUserId'],_0x1b336b),Utils['showToast']('User\x20updated\x20successfully','success'),await loadUsers(),hideUserModal();}else{const _0x101510={'username':_0x3e298a,'name':_0x41c661,'email':_0x28db28};if(!_0x48a763){if(!_0x29559d)throw new Error('Password\x20is\x20required\x20for\x20new\x20users');_0x101510['password']=_0x29559d;}const _0x15a422=await API['createUser'](_0x101510),_0x2868b8=_0x15a422['user'];if(_0x48a763||!_0x29559d){const _0x54ee20=await API['createPasswordToken'](_0x2868b8['id'],'setup',![]);state['setupLinkData']={'username':_0x2868b8['username'],'email':_0x2868b8['email'],'url':_0x54ee20['token']['setupUrl'],'userId':_0x2868b8['id'],'type':'setup','emailSent':![]},await loadUsers(),hideUserModal(),showSetupLinkModal();}else Utils['showToast']('User\x20created\x20successfully','success'),await loadUsers(),hideUserModal();}}catch(_0x26d6a7){console['error']('Failed\x20to\x20save\x20user',_0x26d6a7),_0x43cb5d['textContent']=_0x26d6a7['message'],_0x43cb5d['hidden']=![],_0x43cb5d['scrollIntoView']({'behavior':'smooth','block':'nearest'}),_0x2d2f92['disabled']=![],_0x2d2f92['textContent']=_0x595e11;}}window['deleteUser']=function(_0x379866){const _0x36a476=state['users']['find'](_0x4f2a00=>_0x4f2a00['id']===_0x379866);if(!_0x36a476)return;state['deletingUserId']=_0x379866;const _0x4ac444=document['getElementById']('delete-modal'),_0x551c71=document['getElementById']('delete-user-name');_0x551c71['textContent']=_0x36a476['name']+'\x20('+_0x36a476['username']+')',_0x4ac444['hidden']=![];};function hideDeleteModal(){const _0x23626f=document['getElementById']('delete-modal');_0x23626f['hidden']=!![],state['deletingUserId']=null;const _0x168e5d=document['getElementById']('confirm-delete');_0x168e5d&&(_0x168e5d['disabled']=![],_0x168e5d['textContent']='Delete\x20User');}async function confirmDeleteUser(){if(!state['deletingUserId'])return;const _0x3b90c3=document['getElementById']('confirm-delete'),_0x2ce286=_0x3b90c3['textContent'];_0x3b90c3['disabled']=!![],_0x3b90c3['textContent']='Deleting...';try{await API['deleteUser'](state['deletingUserId']),Utils['showToast']('User\x20deleted\x20successfully','success'),await loadUsers(),hideDeleteModal();}catch(_0x59a703){console['error']('Failed\x20to\x20delete\x20user',_0x59a703),Utils['showToast']('Failed\x20to\x20delete\x20user:\x20'+_0x59a703['message'],'error'),_0x3b90c3['disabled']=![],_0x3b90c3['textContent']=_0x2ce286;}}function handleSkipPasswordChange(_0x19cdaf){const _0x36d89a=document['getElementById']('user-password'),_0x319312=_0x19cdaf['target']['checked'];_0x319312?(_0x36d89a['required']=![],_0x36d89a['disabled']=!![],_0x36d89a['value']=''):(_0x36d89a['required']=!![],_0x36d89a['disabled']=![]);}function showSetupLinkModal(){if(!state['setupLinkData'])return;const _0x32c5b1=document['getElementById']('setup-link-modal'),_0x34ce22=document['getElementById']('setup-link-username'),_0x3ee632=document['getElementById']('setup-link-url'),_0x1183f0=document['getElementById']('email-setup-link'),_0xa19f07=document['getElementById']('email-button-text');_0x34ce22['textContent']=state['setupLinkData']['username'],_0x3ee632['textContent']=state['setupLinkData']['url'],_0x1183f0&&_0xa19f07&&(_0x1183f0['disabled']=![],_0xa19f07['textContent']='Email\x20Link',state['emailConfigured']&&!state['setupLinkData']['emailSent']?_0x1183f0['style']['display']='inline-block':_0x1183f0['style']['display']='none'),_0x32c5b1['hidden']=![];}function hideSetupLinkModal(){const _0x4fe431=document['getElementById']('setup-link-modal');_0x4fe431['hidden']=!![],state['setupLinkData']=null;}async function copySetupLink(){if(!state['setupLinkData'])return;try{await navigator['clipboard']['writeText'](state['setupLinkData']['url']),Utils['showToast']('Link\x20copied\x20to\x20clipboard','success');}catch(_0x4c88f1){console['error']('Failed\x20to\x20copy\x20link',_0x4c88f1),Utils['showToast']('Failed\x20to\x20copy\x20link','error');}}async function emailSetupLink(){if(!state['setupLinkData'])return;const _0x1ca4a0=document['getElementById']('email-setup-link'),_0x5d5c67=document['getElementById']('email-button-text');if(!_0x1ca4a0||!_0x5d5c67)return;const _0x58de34=_0x5d5c67['textContent'];_0x1ca4a0['disabled']=!![],_0x5d5c67['textContent']='Sending...';try{const _0x1fd6fa=await API['createPasswordToken'](state['setupLinkData']['userId'],state['setupLinkData']['type'],!![]);if(_0x1fd6fa['emailSent'])Utils['showToast']('Email\x20sent\x20to\x20'+state['setupLinkData']['email'],'success'),state['setupLinkData']['emailSent']=!![],_0x1ca4a0['style']['display']='none';else{const _0x1f66e2=_0x1fd6fa['emailError']||'Failed\x20to\x20send\x20email';Utils['showToast'](_0x1f66e2,'error'),_0x1ca4a0['disabled']=![],_0x5d5c67['textContent']=_0x58de34;}}catch(_0x2d8403){console['error']('Failed\x20to\x20email\x20setup\x20link',_0x2d8403),Utils['showToast']('Failed\x20to\x20send\x20email:\x20'+_0x2d8403['message'],'error'),_0x1ca4a0['disabled']=![],_0x5d5c67['textContent']=_0x58de34;}}window['resetPassword']=async function(_0x5e77af){const _0x277093=state['users']['find'](_0x68ed48=>_0x68ed48['id']===_0x5e77af);if(!_0x277093)return;const _0xd93026=await ConfirmDialog['show']({'title':'Reset\x20Password','message':'Generate\x20a\x20password\x20reset\x20link\x20for\x20'+_0x277093['name']+'\x20('+_0x277093['username']+')?\x20This\x20will\x20create\x20a\x20link\x20that\x20they\x20can\x20use\x20to\x20set\x20a\x20new\x20password.','confirmText':'Generate\x20Link'});if(!_0xd93026)return;try{const _0x2cc9b8=await API['createPasswordToken'](_0x5e77af,'reset',![]);state['setupLinkData']={'username':_0x277093['username'],'email':_0x277093['email'],'url':_0x2cc9b8['token']['setupUrl'],'userId':_0x277093['id'],'type':'reset','emailSent':![]},showSetupLinkModal();}catch(_0x412d00){console['error']('Failed\x20to\x20create\x20password\x20reset\x20link',_0x412d00),Utils['showToast']('Failed\x20to\x20create\x20password\x20reset\x20link:\x20'+_0x412d00['message'],'error');}};