@profoundlogic/coderflow-server 0.7.7 → 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 (187) hide show
  1. package/dist/coder-server.js +1 -1
  2. package/dist/config.js +1 -1
  3. package/dist/lib/agent-keepalive.js +1 -1
  4. package/dist/lib/agent-models.js +1 -1
  5. package/dist/lib/api-keys.js +1 -1
  6. package/dist/lib/apiKeys.js +1 -1
  7. package/dist/lib/app-server-ports.js +1 -1
  8. package/dist/lib/auto-judge.js +1 -1
  9. package/dist/lib/automation-service.js +1 -1
  10. package/dist/lib/basic-auth.js +1 -1
  11. package/dist/lib/bindings.js +1 -1
  12. package/dist/lib/build-history.js +1 -1
  13. package/dist/lib/build-output-service.js +1 -1
  14. package/dist/lib/build-scheduler.js +1 -1
  15. package/dist/lib/build-service.js +1 -1
  16. package/dist/lib/ca-certificates.js +1 -1
  17. package/dist/lib/claude-oauth-refresh.js +1 -1
  18. package/dist/lib/cli/build.js +1 -1
  19. package/dist/lib/cli/cleanup-users.js +1 -1
  20. package/dist/lib/cli/config-command.js +1 -1
  21. package/dist/lib/cli/config.js +1 -1
  22. package/dist/lib/cli/create-user.js +1 -1
  23. package/dist/lib/cli/grant-admin.js +1 -1
  24. package/dist/lib/cli/init.js +1 -1
  25. package/dist/lib/cli/jira.js +1 -1
  26. package/dist/lib/cli/license.js +1 -1
  27. package/dist/lib/cli/list-roles.js +1 -1
  28. package/dist/lib/cli/list-users.js +1 -1
  29. package/dist/lib/cli/server-manager.js +1 -1
  30. package/dist/lib/cli/set-password.js +1 -1
  31. package/dist/lib/compression-filter.js +1 -0
  32. package/dist/lib/config-migration.js +1 -1
  33. package/dist/lib/container-credential-sync.js +1 -1
  34. package/dist/lib/container-tokens.js +1 -1
  35. package/dist/lib/data-dir.js +1 -1
  36. package/dist/lib/deployment-history.js +1 -1
  37. package/dist/lib/deployment-service.js +1 -1
  38. package/dist/lib/docker-utils.js +1 -1
  39. package/dist/lib/email.js +1 -1
  40. package/dist/lib/emailTemplates.js +1 -1
  41. package/dist/lib/entitlement.js +1 -1
  42. package/dist/lib/external-connections.js +1 -1
  43. package/dist/lib/fetch-utils.js +1 -1
  44. package/dist/lib/git-commit-details-route.js +1 -1
  45. package/dist/lib/git-history-diff-guardrails.js +1 -1
  46. package/dist/lib/git-provider-service.js +1 -1
  47. package/dist/lib/git-provider-setup/github-setup-handler.js +1 -1
  48. package/dist/lib/git-provider-setup/index.js +1 -1
  49. package/dist/lib/git-provider-setup/setup-factory.js +1 -1
  50. package/dist/lib/git-provider-setup/setup-interface.js +1 -1
  51. package/dist/lib/git-providers/azure-devops-provider.js +1 -1
  52. package/dist/lib/git-providers/github-app-provider.js +1 -1
  53. package/dist/lib/git-providers/index.js +1 -1
  54. package/dist/lib/git-providers/provider-factory.js +1 -1
  55. package/dist/lib/git-providers/provider-interface.js +1 -1
  56. package/dist/lib/github-urls.js +1 -1
  57. package/dist/lib/group-objective-linking.js +1 -1
  58. package/dist/lib/ibmi-sync.js +1 -1
  59. package/dist/lib/jira-client.js +1 -1
  60. package/dist/lib/judge-blinding.js +1 -1
  61. package/dist/lib/logger.js +1 -1
  62. package/dist/lib/memory-utils.js +1 -1
  63. package/dist/lib/migration-to-scoped-rbac.js +1 -1
  64. package/dist/lib/model-fetcher.js +1 -1
  65. package/dist/lib/notifications.js +1 -1
  66. package/dist/lib/objective-context.js +1 -1
  67. package/dist/lib/oidc-auth.js +1 -1
  68. package/dist/lib/oidc-device-flow.js +1 -1
  69. package/dist/lib/passwordTokens.js +1 -1
  70. package/dist/lib/permission-resolver.js +1 -1
  71. package/dist/lib/pin-cascade.js +1 -1
  72. package/dist/lib/provider-accounts.js +1 -1
  73. package/dist/lib/provider-oauth.js +1 -1
  74. package/dist/lib/provider-profile.js +1 -1
  75. package/dist/lib/provider-token-refresh.js +1 -1
  76. package/dist/lib/rbac-user-state.js +1 -1
  77. package/dist/lib/request-url.js +1 -1
  78. package/dist/lib/rewind.js +1 -1
  79. package/dist/lib/role-definitions.js +1 -1
  80. package/dist/lib/roles.js +1 -1
  81. package/dist/lib/secrets.js +1 -1
  82. package/dist/lib/setup-repo-git-auth.js +1 -1
  83. package/dist/lib/state-capture.js +1 -1
  84. package/dist/lib/static-files.js +1 -1
  85. package/dist/lib/task-aliases.js +1 -1
  86. package/dist/lib/task-name-format.js +1 -1
  87. package/dist/lib/task-name-generator.js +1 -1
  88. package/dist/lib/task-source-metadata.js +1 -1
  89. package/dist/lib/teams.js +1 -1
  90. package/dist/lib/user-git-oauth.js +1 -1
  91. package/dist/lib/user-git-tokens.js +1 -1
  92. package/dist/lib/users.js +1 -1
  93. package/dist/middleware/requireAuth.js +1 -1
  94. package/dist/middleware/requireInit.js +1 -1
  95. package/dist/middleware/requirePermission.js +1 -1
  96. package/dist/package.json +1 -1
  97. package/dist/playwright.config.js +1 -1
  98. package/dist/playwright.task-terminal.config.js +1 -1
  99. package/dist/routes/apiKeys.js +1 -1
  100. package/dist/routes/auth-oidc.js +1 -1
  101. package/dist/routes/auth.js +1 -1
  102. package/dist/routes/automations.js +1 -1
  103. package/dist/routes/bindings.js +1 -1
  104. package/dist/routes/build.js +1 -1
  105. package/dist/routes/containers.js +1 -1
  106. package/dist/routes/deploy-task.js +1 -1
  107. package/dist/routes/environment-management.js +1 -1
  108. package/dist/routes/environments.js +1 -1
  109. package/dist/routes/external-skills.js +1 -1
  110. package/dist/routes/git-credentials.js +1 -1
  111. package/dist/routes/git-oauth.js +1 -1
  112. package/dist/routes/git-provider-setup.js +1 -1
  113. package/dist/routes/health.js +1 -1
  114. package/dist/routes/jira.js +1 -1
  115. package/dist/routes/logs.js +1 -0
  116. package/dist/routes/objective-management.js +1 -1
  117. package/dist/routes/password.js +1 -1
  118. package/dist/routes/prompt.js +1 -1
  119. package/dist/routes/provider-auth.js +1 -1
  120. package/dist/routes/qa.js +1 -1
  121. package/dist/routes/roles.js +1 -1
  122. package/dist/routes/settings.js +1 -1
  123. package/dist/routes/skill-management.js +1 -1
  124. package/dist/routes/skills.js +1 -1
  125. package/dist/routes/stats.js +1 -0
  126. package/dist/routes/tasks.js +1 -1
  127. package/dist/routes/teams.js +1 -1
  128. package/dist/routes/templates.js +1 -1
  129. package/dist/routes/test-task.js +1 -1
  130. package/dist/routes/test.js +1 -1
  131. package/dist/routes/users.js +1 -1
  132. package/dist/routes/visualizations.js +1 -1
  133. package/dist/scripts/create-user.js +1 -1
  134. package/dist/scripts/migrate-config-to-data-dir.js +1 -1
  135. package/dist/start.js +1 -1
  136. package/dist/web-ui/public/activity-detail-modal.js +1 -1
  137. package/dist/web-ui/public/activity-feed.js +1 -1
  138. package/dist/web-ui/public/activity-formatters.js +1 -1
  139. package/dist/web-ui/public/admin.css +575 -0
  140. package/dist/web-ui/public/admin.html +636 -0
  141. package/dist/web-ui/public/admin.js +1 -0
  142. package/dist/web-ui/public/agent-event-parser.js +1 -1
  143. package/dist/web-ui/public/app.js +1 -1
  144. package/dist/web-ui/public/approve-dialog.js +1 -1
  145. package/dist/web-ui/public/automation-links.js +1 -1
  146. package/dist/web-ui/public/automation-schedule.js +1 -1
  147. package/dist/web-ui/public/comments-widget.js +1 -1
  148. package/dist/web-ui/public/diff-utils.js +1 -1
  149. package/dist/web-ui/public/environments.html +2 -2
  150. package/dist/web-ui/public/environments.js +1 -1
  151. package/dist/web-ui/public/feedback-widget.js +1 -1
  152. package/dist/web-ui/public/file-selection-tree.js +1 -1
  153. package/dist/web-ui/public/git-history-lazy-utils.js +1 -1
  154. package/dist/web-ui/public/git-history.html +2 -2
  155. package/dist/web-ui/public/git-history.js +1 -1
  156. package/dist/web-ui/public/git-status.js +1 -1
  157. package/dist/web-ui/public/ibmi-file-filter.js +1 -1
  158. package/dist/web-ui/public/index.html +2 -170
  159. package/dist/web-ui/public/index.js +1 -1
  160. package/dist/web-ui/public/login.js +1 -1
  161. package/dist/web-ui/public/markdown-editor.js +1 -1
  162. package/dist/web-ui/public/markdown-file-editor.js +1 -1
  163. package/dist/web-ui/public/modal-maximize.js +1 -1
  164. package/dist/web-ui/public/notifications.js +1 -1
  165. package/dist/web-ui/public/permissions.js +1 -1
  166. package/dist/web-ui/public/pr-dialog.js +1 -1
  167. package/dist/web-ui/public/roles.html +2 -2
  168. package/dist/web-ui/public/roles.js +1 -1
  169. package/dist/web-ui/public/settings.html +66 -4
  170. package/dist/web-ui/public/settings.js +1 -1
  171. package/dist/web-ui/public/setup-password.js +1 -1
  172. package/dist/web-ui/public/skills.html +2 -2
  173. package/dist/web-ui/public/skills.js +1 -1
  174. package/dist/web-ui/public/sse-client.js +1 -1
  175. package/dist/web-ui/public/sse-shared-worker.js +1 -1
  176. package/dist/web-ui/public/styles.css +1 -1
  177. package/dist/web-ui/public/task-judging-helpers.js +1 -1
  178. package/dist/web-ui/public/task.js +1 -1
  179. package/dist/web-ui/public/teams.html +2 -2
  180. package/dist/web-ui/public/teams.js +1 -1
  181. package/dist/web-ui/public/terminal.js +1 -1
  182. package/dist/web-ui/public/theme.js +1 -1
  183. package/dist/web-ui/public/users.html +2 -2
  184. package/dist/web-ui/public/users.js +1 -1
  185. package/dist/web-ui/public/variant-grouping.js +1 -1
  186. package/package.json +1 -1
  187. 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 _0x2b3968=state['currentUser'];if(!Permissions['hasServerPermission'](_0x2b3968,'teams:view')&&!Permissions['hasTeamPermission'](_0x2b3968,'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'](_0x2b3968,'*')||Permissions['hasTeamPermission'](_0x2b3968,'teams:manage'))&&(document['getElementById']('create-team-btn')['hidden']=![]),bindEventListeners(),await Promise['all']([loadTeams(),loadUsers(),loadRoles(),loadEnvironments()]),renderTeams();});async function loadTeams(){const _0x237645=document['getElementById']('teams-loading'),_0x3f1e3e=document['getElementById']('teams-error'),_0x4960e1=document['getElementById']('teams-content');try{_0x237645['hidden']=![],_0x3f1e3e['hidden']=!![],_0x4960e1['hidden']=!![];const {teams:_0xf178b7}=await API['getTeams']();state['teams']=_0xf178b7||[],renderTeams(),_0x237645['hidden']=!![],_0x4960e1['hidden']=![];}catch(_0x4e598a){_0x237645['hidden']=!![],_0x3f1e3e['hidden']=![],document['getElementById']('teams-error-message')['textContent']=_0x4e598a['message'];}}async function loadUsers(){try{const {users:_0x3c13d8}=await API['getUsers']();state['users']=_0x3c13d8||[];}catch{state['users']=[];}}async function loadRoles(){try{const {roles:_0xd73f2}=await API['getRoleDefinitions']();state['roles']=_0xd73f2||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x3b3e29=await API['getEnvironments']();state['environments']=_0x3b3e29['environments']||[];}catch{state['environments']=[];}}function renderTeams(){const _0x1fc47c=document['getElementById']('teams-table-body'),_0x2e0b83=document['getElementById']('team-count');if(!_0x1fc47c)return;_0x2e0b83&&(_0x2e0b83['textContent']=state['teams']['length']+'\x20team'+(state['teams']['length']===0x1?'':'s'));if(state['teams']['length']===0x0){_0x1fc47c['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 _0x1f4a1e=Permissions['hasServerPermission'](state['currentUser'],'*');_0x1fc47c['innerHTML']=state['teams']['map'](_0x306eb4=>{const _0x203593=_0x1f4a1e||_0x306eb4['canManageTeam'],_0x36229d=_0x1f4a1e||_0x306eb4['canManageMembers'],_0x469659=_0x203593||_0x36229d,_0x528cf6=(_0x306eb4['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'](_0x306eb4['name'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x306eb4['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x306eb4['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x528cf6+'</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'+(_0x469659?'<button\x20class=\x22btn-icon\x22\x20title=\x22Edit\x20team\x22\x20onclick=\x22window.openTeamModal(\x27'+_0x306eb4['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'+(_0x203593?'<button\x20class=\x22btn-icon\x22\x20title=\x22Access\x20bindings\x22\x20onclick=\x22window.openBindingsModal(\x27'+_0x306eb4['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'+(_0x203593?'<button\x20class=\x22btn-icon\x20btn-danger\x22\x20title=\x22Delete\x20team\x22\x20onclick=\x22window.deleteTeam(\x27'+_0x306eb4['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(_0x594cef){const _0x5ba752=state['teams']['find'](_0x483015=>_0x483015['id']===_0x594cef);if(!_0x5ba752)return;state['editingTeamId']=_0x594cef;const _0x1792a4=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x442217=_0x1792a4||_0x5ba752['canManageTeam'],_0xc5eb54=_0x1792a4||_0x5ba752['canManageMembers'],_0x1055d4=_0x442217,_0x3ee43e=_0x442217||_0xc5eb54,_0x27d4b3=_0x5ba752['name'],_0xa0f6bd=_0x5ba752['description']||'';state['modalSnapshot']={'name':_0x27d4b3,'description':_0xa0f6bd},document['getElementById']('team-modal-title')['textContent']=_0x27d4b3,document['getElementById']('team-name')['value']=_0x27d4b3,document['getElementById']('team-name')['disabled']=!_0x1055d4,document['getElementById']('team-description')['value']=_0xa0f6bd,document['getElementById']('team-description')['disabled']=!_0x1055d4,document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=![],document['getElementById']('save-team')['hidden']=!_0x1055d4,renderMembersList(_0x5ba752),updateMemberSelect(_0x5ba752),document['getElementById']('team-modal')['hidden']=![];};function isTeamModalDirty(){if(!state['modalSnapshot'])return![];const _0x47c9a2=document['getElementById']('team-name')['value']['trim'](),_0x41a473=document['getElementById']('team-description')['value']['trim']();return _0x47c9a2!==state['modalSnapshot']['name']||_0x41a473!==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(_0x289b87){const _0x4319b1=state['teams']['find'](_0x11dd91=>_0x11dd91['id']===_0x289b87);if(!_0x4319b1)return;state['bindingsTeamId']=_0x289b87,document['getElementById']('bindings-modal-title')['textContent']='Access\x20Bindings\x20—\x20'+_0x4319b1['name'],document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('bindings-modal')['hidden']=![],loadTeamBindings(_0x289b87);};function hideBindingsModal(){document['getElementById']('bindings-modal')['hidden']=!![],state['bindingsTeamId']=null;}function renderMembersList(_0x2e44e0){const _0x25244c=Permissions['hasServerPermission'](state['currentUser'],'*'),_0xf4db39=_0x25244c||_0x2e44e0['canManageMembers']||_0x2e44e0['canManageTeam'],_0x59f6fe=_0x2e44e0['members']||[],_0x42397b=document['getElementById']('members-list');if(_0x59f6fe['length']===0x0){_0x42397b['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x20margin:\x200.25rem\x200;\x22>No\x20members\x20yet</p>';return;}_0x42397b['innerHTML']=_0x59f6fe['map'](_0x25d04c=>{const _0x690ca0=state['users']['find'](_0x2caf53=>_0x2caf53['id']===_0x25d04c),_0xf9bf7=_0x690ca0?''+Utils['escapeHtml'](_0x690ca0['username'])+(_0x690ca0['name']?'\x20<span\x20style=\x22color:\x20var(--color-text-secondary);\x20font-size:\x200.85em;\x22>('+Utils['escapeHtml'](_0x690ca0['name'])+')</span>':''):Utils['escapeHtml'](_0x25d04c);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'+_0xf9bf7+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0xf4db39?'<button\x20type=\x22button\x22\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.removeMemberClick(\x27'+_0x25d04c+'\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 _0x5115c1=document['getElementById']('add-member-row');if(_0x5115c1)_0x5115c1['style']['display']=_0xf4db39?'flex':'none';}function updateMemberSelect(_0x2dec5a){const _0x521c32=document['getElementById']('add-member-select');if(!_0x521c32)return;const _0x5b7e27=new Set(_0x2dec5a['members']||[]),_0x411583=state['users']['filter'](_0x3d2ea0=>!_0x5b7e27['has'](_0x3d2ea0['id']));_0x521c32['innerHTML']='<option\x20value=\x22\x22>Add\x20a\x20member…</option>'+_0x411583['map'](_0x27195a=>'<option\x20value=\x22'+_0x27195a['id']+'\x22>'+Utils['escapeHtml'](_0x27195a['username'])+(_0x27195a['name']?'\x20('+Utils['escapeHtml'](_0x27195a['name'])+')':'')+'</option>')['join']('');}async function addMember(){const _0x3171c0=document['getElementById']('add-member-select'),_0x4e558d=_0x3171c0['value'];if(!_0x4e558d||!state['editingTeamId'])return;try{const {team:_0x63463f}=await API['addTeamMember'](state['editingTeamId'],_0x4e558d);syncTeamInState(_0x63463f),renderMembersList(_0x63463f),updateMemberSelect(_0x63463f),_0x3171c0['value']='',Utils['showToast']('Member\x20added','success');}catch(_0x4dc70e){Utils['showToast'](_0x4dc70e['message'],'error');}}window['removeMemberClick']=async function(_0x2b408b){if(!state['editingTeamId'])return;try{const {team:_0x18068d}=await API['removeTeamMember'](state['editingTeamId'],_0x2b408b);syncTeamInState(_0x18068d),renderMembersList(_0x18068d),updateMemberSelect(_0x18068d),Utils['showToast']('Member\x20removed','success');}catch(_0x4a8422){Utils['showToast'](_0x4a8422['message'],'error');}};async function loadTeamBindings(_0xfd50cb){const _0xaf34b=document['getElementById']('bindings-loading'),_0x5863ac=document['getElementById']('bindings-empty'),_0x99819b=document['getElementById']('bindings-list-container'),_0xc23a9a=document['getElementById']('add-binding-btn');_0xaf34b['hidden']=![],_0x5863ac['hidden']=!![],_0x99819b['style']['display']='none',_0xc23a9a['hidden']=!![],document['getElementById']('add-binding-form')['hidden']=!![];try{const {bindings:_0x5d3cd5}=await API['getBindings']({'subject_type':'team','subject_id':_0xfd50cb});state['teamBindings']=_0x5d3cd5||[],_0xaf34b['hidden']=!![],state['teamBindings']['length']===0x0?_0x5863ac['hidden']=![]:(_0x99819b['style']['display']='',renderBindingsTable()),(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage'))&&(_0xc23a9a['hidden']=![]);}catch(_0x229d91){_0xaf34b['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x229d91['message'],'error');}}function renderBindingsTable(){const _0x32d9e5=document['getElementById']('bindings-table-body');if(!_0x32d9e5)return;const _0x195bf5=Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage');_0x32d9e5['innerHTML']=state['teamBindings']['map'](_0x3533cc=>{const _0x760546=_0x3533cc['resource_type']==='server'?'Server':_0x3533cc['resource_id']==='*'?'All\x20'+_0x3533cc['resource_type']+'s':Utils['escapeHtml'](_0x3533cc['resource_name']||_0x3533cc['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x760546+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x3533cc['role_name']||_0x3533cc['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x195bf5?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteBindingClick(\x27'+_0x3533cc['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 _0x1ad785=document['getElementById']('binding-resource-type');_0x1ad785['value']='environment',updateBindingFormForResourceType('environment');}function onBindingResourceTypeChange(){const _0x4dcf28=document['getElementById']('binding-resource-type')['value'];updateBindingFormForResourceType(_0x4dcf28);}function updateBindingFormForResourceType(_0x39b1e3){const _0xa7c268=document['getElementById']('binding-resource-container'),_0x5c01c7=document['getElementById']('binding-resource'),_0x17760b=document['getElementById']('binding-role');if(_0x39b1e3==='server')_0xa7c268['style']['display']='none';else{_0xa7c268['style']['display']='';if(_0x39b1e3==='environment'){const _0x1ccba9=new Set(state['teamBindings']['filter'](_0x110f4c=>_0x110f4c['resource_type']==='environment')['map'](_0x37c498=>_0x37c498['resource_id'])),_0x2fcabe=state['environments']['filter'](_0x370891=>!_0x1ccba9['has'](_0x370891['name']));_0x5c01c7['innerHTML']=_0x2fcabe['length']?_0x2fcabe['map'](_0x44f06e=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x44f06e['name'])+'\x22>'+Utils['escapeHtml'](_0x44f06e['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x39b1e3==='team'){const _0x2404b4=new Set(state['teamBindings']['filter'](_0x2327be=>_0x2327be['resource_type']==='team')['map'](_0x6ea127=>_0x6ea127['resource_id'])),_0x141d2e=state['teams']['filter'](_0x5a96a5=>!_0x2404b4['has'](_0x5a96a5['id']));_0x5c01c7['innerHTML']=_0x141d2e['length']?_0x141d2e['map'](_0x198a98=>'<option\x20value=\x22'+_0x198a98['id']+'\x22>'+Utils['escapeHtml'](_0x198a98['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x293b2a=state['roles']['filter'](_0x54066d=>_0x54066d['resource_type']===_0x39b1e3);_0x17760b['innerHTML']=_0x293b2a['length']?_0x293b2a['filter'](_0x3e7f68=>{const _0x4e8b57=_0x39b1e3==='server'?undefined:_0x5c01c7['value'];return!state['teamBindings']['some'](_0x546924=>_0x546924['resource_type']===_0x39b1e3&&_0x546924['role_id']===_0x3e7f68['id']&&(_0x39b1e3==='server'||_0x546924['resource_id']===_0x4e8b57));})['map'](_0x4c7a94=>'<option\x20value=\x22'+_0x4c7a94['id']+'\x22>'+Utils['escapeHtml'](_0x4c7a94['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 _0x29b354=document['getElementById']('binding-resource-type')['value'],_0x1f5932=document['getElementById']('binding-role')['value'];if(!_0x1f5932||!state['bindingsTeamId'])return;const _0x46e55e=_0x29b354==='server'?undefined:document['getElementById']('binding-resource')['value'];if(_0x29b354!=='server'&&!_0x46e55e)return;const _0x138596=document['getElementById']('save-binding-btn');_0x138596['disabled']=!![],_0x138596['textContent']='Adding…';try{const _0x55ac95={'subject_type':'team','subject_id':state['bindingsTeamId'],'role_id':_0x1f5932,'resource_type':_0x29b354};if(_0x46e55e)_0x55ac95['resource_id']=_0x46e55e;await API['createBinding'](_0x55ac95),Utils['showToast']('Binding\x20added','success'),document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![],await loadTeamBindings(state['bindingsTeamId']);}catch(_0x4e95af){Utils['showToast'](_0x4e95af['message'],'error');}finally{_0x138596['disabled']=![],_0x138596['textContent']='Add\x20Binding';}}window['deleteBindingClick']=async function(_0x21b4b3){try{await API['deleteBinding'](_0x21b4b3),Utils['showToast']('Binding\x20removed','success'),await loadTeamBindings(state['bindingsTeamId']);}catch(_0x24a9ed){Utils['showToast'](_0x24a9ed['message'],'error');}};async function saveTeam(){const _0x157837=document['getElementById']('team-name')['value']['trim'](),_0x26d6e5=document['getElementById']('team-description')['value']['trim'](),_0x1e1b82=document['getElementById']('team-form-error'),_0xb1d16=document['getElementById']('save-team');if(!_0x157837){_0x1e1b82['textContent']='Team\x20name\x20is\x20required',_0x1e1b82['hidden']=![];return;}_0x1e1b82['hidden']=!![];const _0x599f07=_0xb1d16['textContent'];_0xb1d16['disabled']=!![],_0xb1d16['textContent']=state['editingTeamId']?'Saving…':'Creating…';try{if(state['editingTeamId']){const {team:_0x3ee370}=await API['updateTeam'](state['editingTeamId'],{'name':_0x157837,'description':_0x26d6e5});syncTeamInState(_0x3ee370),document['getElementById']('team-modal-title')['textContent']=_0x3ee370['name'],Utils['showToast']('Team\x20updated','success');}else await API['createTeam']({'name':_0x157837,'description':_0x26d6e5}),Utils['showToast']('Team\x20created','success');_0xb1d16['disabled']=![],_0xb1d16['textContent']=_0x599f07,hideTeamModal(),await loadTeams();}catch(_0x3cb739){_0x1e1b82['textContent']=_0x3cb739['message'],_0x1e1b82['hidden']=![],_0xb1d16['disabled']=![],_0xb1d16['textContent']=_0x599f07;}}window['deleteTeam']=function(_0x14a617){const _0x405ff2=state['teams']['find'](_0x219338=>_0x219338['id']===_0x14a617);if(!_0x405ff2)return;state['deletingTeamId']=_0x14a617,document['getElementById']('delete-team-name')['textContent']=_0x405ff2['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 _0x3fc675=document['getElementById']('confirm-delete-team');_0x3fc675['disabled']=!![],_0x3fc675['textContent']='Deleting…';try{await API['deleteTeam'](state['deletingTeamId']),Utils['showToast']('Team\x20deleted','success'),_0x3fc675['disabled']=![],_0x3fc675['textContent']='Delete\x20Team',hideDeleteModal(),await loadTeams();}catch(_0x5dfc80){Utils['showToast']('Failed\x20to\x20delete\x20team:\x20'+_0x5dfc80['message'],'error'),_0x3fc675['disabled']=![],_0x3fc675['textContent']='Delete\x20Team';}}function syncTeamInState(_0x41fb9c){const _0x58299e=state['teams']['findIndex'](_0x184466=>_0x184466['id']===_0x41fb9c['id']);if(_0x58299e>=0x0)state['teams'][_0x58299e]=_0x41fb9c;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'](_0x37c283=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':_0x37c283}));});let commandSent=![],hasReceivedOutput=![];socket['addEventListener']('message',_0x966645=>{try{const _0x33aba6=JSON['parse'](_0x966645['data']);if(_0x33aba6['type']==='data'&&typeof _0x33aba6['data']==='string')term['write'](_0x33aba6['data']),!hasReceivedOutput&&_0x33aba6['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(_0x33aba6['type']==='status'&&_0x33aba6['status']){if(_0x33aba6['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'+_0x33aba6['status'],_0x33aba6['status']==='connected'?'success':'info');}else _0x33aba6['type']==='error'&&_0x33aba6['message']&&updateStatus(_0x33aba6['message'],'error');}}catch(_0x1b7f05){console['error']('Failed\x20to\x20parse\x20terminal\x20message',_0x1b7f05);}}),socket['addEventListener']('close',_0x794e3b=>{const _0x2c2d5d=_0x794e3b['reason']||'Connection\x20closed';updateStatus(_0x2c2d5d,_0x794e3b['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',_0x5a77d1=>{console['error']('Terminal\x20websocket\x20error',_0x5a77d1),updateStatus('Connection\x20error','error');});function sendResize(){if(socket['readyState']!==WebSocket['OPEN'])return;const _0x34133f=term['cols'],_0x409510=term['rows'];socket['send'](JSON['stringify']({'type':'resize','cols':_0x34133f,'rows':_0x409510}));}function updateStatus(_0x1db531,_0x51fb67='info'){if(!statusEl)return;statusEl['textContent']=_0x1db531,statusEl['dataset']['variant']=_0x51fb67;}async function enrichContainerDetails(_0x16a004){try{const _0x31c186=await API['getContainer'](_0x16a004);updateTerminalDetails(_0x31c186);}catch{try{const _0x1005f1=await API['getContainers'](),_0x113a40=(_0x1005f1['containers']||[])['find'](_0x10668d=>_0x10668d['containerId']===_0x16a004||_0x10668d['name']===_0x16a004||_0x10668d['fullContainerId']?.['startsWith'](_0x16a004));if(_0x113a40){updateTerminalDetails(_0x113a40);return;}subtitleEl['textContent']='Container\x20'+_0x16a004['substring'](0x0,0xc);}catch{subtitleEl['textContent']='Container\x20'+_0x16a004['substring'](0x0,0xc);}}}function updateTerminalDetails(_0x4fe152){const _0x1a867e=_0x4fe152['containerId']||_0x4fe152['name']||_0x4fe152['fullContainerId']||containerId,_0x556c6d=_0x4fe152['environment']?'Environment\x20'+_0x4fe152['environment']:'Environment\x20unknown',_0x455f1a=_0x4fe152['defaultAgent']?'\x20·\x20Agent\x20'+_0x4fe152['defaultAgent']:'',_0x9842bc=_0x4fe152['createdAt']?'\x20·\x20Started\x20'+Utils['formatRelativeTime'](_0x4fe152['createdAt']):'';titleEl['textContent']='Terminal\x20·\x20'+_0x1a867e['substring'](0x0,0xc);const _0x4b5f80=command?'\x20·\x20Command\x20'+command:'';subtitleEl['textContent']=''+_0x556c6d+_0x455f1a+_0x9842bc+_0x4b5f80;}
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 _0x3402f3=localStorage['getItem'](THEME_STORAGE_KEY);if(_0x3402f3&&VALID_THEMES['has'](_0x3402f3))return _0x3402f3;}catch(_0xcfea08){console['warn']('[Theme]\x20Failed\x20to\x20read\x20stored\x20theme\x20preference:',_0xcfea08);}return null;}export function getPreferredTheme(){const _0x795d95=readStoredTheme();if(_0x795d95)return _0x795d95;const _0x4a9642=window['matchMedia']&&window['matchMedia']('(prefers-color-scheme:\x20dark)')['matches'];return _0x4a9642?'dark':'light';}export function getCurrentTheme(){const _0xd96a79=document['documentElement']['dataset']['theme'];if(_0xd96a79&&VALID_THEMES['has'](_0xd96a79))return _0xd96a79;return getPreferredTheme();}export function applyTheme(_0x379251,{persist:persist=!![],emitEvent:emitEvent=!![]}={}){const _0x2e8f22=VALID_THEMES['has'](_0x379251)?_0x379251:'light';document['documentElement']['dataset']['theme']=_0x2e8f22,document['documentElement']['style']['colorScheme']=_0x2e8f22==='dark'?'dark':'light';if(persist)try{localStorage['setItem'](THEME_STORAGE_KEY,_0x2e8f22);}catch(_0xe2fb35){console['warn']('[Theme]\x20Failed\x20to\x20persist\x20theme\x20preference:',_0xe2fb35);}return emitEvent&&window['dispatchEvent'](new CustomEvent(THEME_CHANGE_EVENT,{'detail':{'theme':_0x2e8f22}})),_0x2e8f22;}export function initTheme(_0x521648={}){const {emitEvent:emitEvent=![]}=_0x521648;return applyTheme(getPreferredTheme(),{'persist':![],'emitEvent':emitEvent});}export function toggleTheme(){const _0x1a5a7c=getCurrentTheme()==='dark'?'light':'dark';return applyTheme(_0x1a5a7c);}export function onThemeChange(_0x2197b1,{runImmediately:runImmediately=![]}={}){const _0x358112=_0x4ae9da=>{_0x2197b1(_0x4ae9da['detail']['theme']);};return window['addEventListener'](THEME_CHANGE_EVENT,_0x358112),runImmediately&&_0x2197b1(getCurrentTheme()),()=>window['removeEventListener'](THEME_CHANGE_EVENT,_0x358112);}export function mountThemeToggle(_0x4cb079={}){const {targetSelectors:targetSelectors=DEFAULT_TARGET_SELECTORS}=_0x4cb079,_0x4e3aa3=targetSelectors['map'](_0x53d2fe=>document['querySelector'](_0x53d2fe))['find'](Boolean),_0x4fe4d8=document['createElement']('button');_0x4fe4d8['type']='button',_0x4fe4d8['className']='btn-ghost\x20theme-toggle-btn',_0x4fe4d8['id']='theme-toggle-btn',_0x4fe4d8['setAttribute']('aria-pressed','false'),_0x4fe4d8['style']['padding']='8px',_0x4fe4d8['style']['lineHeight']='0',_0x4fe4d8['style']['width']='36px',_0x4fe4d8['style']['height']='36px',_0x4fe4d8['style']['display']='flex',_0x4fe4d8['style']['alignItems']='center',_0x4fe4d8['style']['justifyContent']='center';const _0x320437=document['createElement']('span');_0x320437['className']='theme-icon',_0x320437['style']['display']='flex',_0x4fe4d8['append'](_0x320437);const _0x4a2004='<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>',_0x195e2c='<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>',_0x38f78c=_0x3c2b4a=>{const _0x56bb5c=_0x3c2b4a==='dark';_0x320437['innerHTML']=_0x56bb5c?_0x4a2004:_0x195e2c,_0x4fe4d8['title']=_0x56bb5c?'Switch\x20to\x20light\x20mode':'Switch\x20to\x20dark\x20mode',_0x4fe4d8['dataset']['theme']=_0x3c2b4a,_0x4fe4d8['setAttribute']('aria-pressed',String(_0x56bb5c));};return _0x4fe4d8['addEventListener']('click',()=>{const _0x3f79d4=getCurrentTheme()==='dark'?'light':'dark';applyTheme(_0x3f79d4);}),_0x4e3aa3?_0x4e3aa3['appendChild'](_0x4fe4d8):(_0x4fe4d8['classList']['add']('theme-toggle-floating'),document['body']['appendChild'](_0x4fe4d8)),_0x38f78c(initTheme()),onThemeChange(_0x38f78c),_0x4fe4d8;}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 _0x5cf1ca=await API['getCurrentUser']();state['currentUser']=_0x5cf1ca;if(!Permissions['hasServerPermission'](_0x5cf1ca,'*')&&!Permissions['hasServerPermission'](_0x5cf1ca,'users:create')){Utils['showToast']('Access\x20denied:\x20Server\x20admin\x20privileges\x20required','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}}catch(_0x341d20){window['location']['href']='login.html';}}async function checkEmailConfig(){try{const _0x5b4ac3=await API['getEmailConfig']();state['emailConfigured']=_0x5b4ac3['configured'];}catch(_0x55051e){console['error']('Failed\x20to\x20check\x20email\x20config',_0x55051e),state['emailConfigured']=![];}}async function loadRoles(){try{const {roles:_0x5662d7}=await API['getRoleDefinitions']();state['roles']=_0x5662d7||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x1fbad2=await API['getEnvironments']();state['environments']=_0x1fbad2['environments']||[];}catch{state['environments']=[];}}async function loadTeams(){try{const {teams:_0xaafce8}=await API['getTeams']();state['teams']=_0xaafce8||[];}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 _0x49a968=document['getElementById']('users-loading'),_0x43c372=document['getElementById']('users-error'),_0x17be17=document['getElementById']('users-content');try{_0x49a968['hidden']=![],_0x43c372['hidden']=!![],_0x17be17['hidden']=!![];const _0x24bddd=await API['getUsers']();state['users']=_0x24bddd['users']||[],renderUsers(),_0x49a968['hidden']=!![],_0x17be17['hidden']=![];}catch(_0x165768){console['error']('Failed\x20to\x20load\x20users',_0x165768),_0x49a968['hidden']=!![],_0x43c372['hidden']=![],document['getElementById']('users-error-message')['textContent']=_0x165768['message'];}}function renderUsers(){const _0x9fc1d3=document['getElementById']('users-table-body'),_0x4fd354=document['getElementById']('user-count');if(!_0x9fc1d3)return;_0x4fd354&&(_0x4fd354['textContent']=state['users']['length']+'\x20user'+(state['users']['length']===0x1?'':'s'));const _0x320ab2=[...state['users']]['sort']((_0x311b96,_0x1c7585)=>{const _0x4b3482=new Date(_0x311b96['created_at'])['getTime'](),_0x5ab575=new Date(_0x1c7585['created_at'])['getTime']();return _0x5ab575-_0x4b3482;});_0x9fc1d3['innerHTML']=_0x320ab2['map'](_0x147e91=>'\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'](_0x147e91['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'](_0x147e91['name'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x147e91['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'+(_0x147e91['isServerAdmin']?'<span\x20class=\x22role-badge\x20role-admin\x22>Server\x20Admin</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x147e91['hasUserBinding']?'<span\x20class=\x22role-badge\x20role-user-binding\x22>User\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x147e91['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'](_0x147e91['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'+_0x147e91['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'+_0x147e91['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'+_0x147e91['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'+_0x147e91['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(_0x100f8d){const _0x3382f3=state['users']['find'](_0x53dd84=>_0x53dd84['id']===_0x100f8d);if(!_0x3382f3)return;state['bindingsUserId']=_0x100f8d,state['bindingsDirty']=![];const _0x313056=document['getElementById']('bindings-modal'),_0x373f51=document['getElementById']('bindings-modal-title');_0x373f51['textContent']='Access\x20Bindings\x20—\x20'+_0x3382f3['name'],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],_0x313056['hidden']=![],loadUserBindings(_0x100f8d);};function hasUnsavedBindingChanges(){const _0xab563=document['getElementById']('add-user-binding-form');return _0xab563&&!_0xab563['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 _0x37dba2=document['getElementById']('bindings-modal');_0x37dba2['hidden']=!![];const _0x4b0276=state['bindingsDirty'];state['bindingsUserId']=null,state['userBindings']=[],state['bindingsDirty']=![],_0x4b0276&&await loadUsers();}async function loadUserBindings(_0x185fa5){const _0x6a7d94=document['getElementById']('user-bindings-loading'),_0x50f02d=document['getElementById']('user-bindings-empty'),_0x5008f7=document['getElementById']('user-bindings-list-container'),_0x322fdb=document['getElementById']('add-user-binding-btn'),_0x49436b=document['getElementById']('user-team-bindings-note'),_0x4123d7=document['getElementById']('user-team-bindings-text');_0x6a7d94['hidden']=![],_0x50f02d['hidden']=!![],_0x5008f7['style']['display']='none',_0x322fdb['hidden']=!![],_0x49436b['hidden']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![];try{const [_0x3d798a,_0x4fff58]=await Promise['all']([API['getBindings']({'subject_type':'user','subject_id':_0x185fa5}),API['getTeams']()]);state['userBindings']=_0x3d798a['bindings']||[];const _0x3fa99b=(_0x4fff58['teams']||[])['filter'](_0x3f7d60=>(_0x3f7d60['members']||[])['includes'](_0x185fa5)),_0x169179=[];if(_0x3fa99b['length']>0x0){const _0x5e2d88=await Promise['all'](_0x3fa99b['map'](_0x329a93=>API['getBindings']({'subject_type':'team','subject_id':_0x329a93['id']})));for(let _0x429aac=0x0;_0x429aac<_0x3fa99b['length'];_0x429aac++){const _0x2722e5=_0x5e2d88[_0x429aac]['bindings']||[];_0x2722e5['length']>0x0&&_0x169179['push'](_0x3fa99b[_0x429aac]);}}_0x6a7d94['hidden']=!![];state['userBindings']['length']===0x0?_0x50f02d['hidden']=![]:(_0x5008f7['style']['display']='',renderUserBindingsTable());if(_0x169179['length']>0x0){const _0x3ef6d9=_0x169179['map'](_0x435be1=>_0x435be1['name']),_0x423261=_0x3ef6d9['length']<=0x3?_0x3ef6d9['join'](',\x20'):_0x3ef6d9['slice'](0x0,0x3)['join'](',\x20')+(',\x20and\x20'+(_0x3ef6d9['length']-0x3)+'\x20more');_0x4123d7['textContent']='This\x20user\x20also\x20has\x20access\x20via\x20team\x20memberships\x20('+_0x423261+').';}else _0x4123d7['textContent']='This\x20user\x20has\x20no\x20access\x20via\x20team\x20memberships.';_0x49436b['hidden']=![],_0x322fdb['hidden']=![];}catch(_0x357eb6){_0x6a7d94['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x357eb6['message'],'error');}}function renderUserBindingsTable(){const _0x48b9b7=document['getElementById']('user-bindings-table-body');if(!_0x48b9b7)return;_0x48b9b7['innerHTML']=state['userBindings']['map'](_0x566270=>{const _0x2b1e45=_0x566270['resource_type']==='server'?'Server':_0x566270['resource_id']==='*'?'All\x20'+_0x566270['resource_type']+'s':Utils['escapeHtml'](_0x566270['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x2b1e45+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x566270['role_name']||_0x566270['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'+_0x566270['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 _0x370151=document['getElementById']('user-binding-resource-type');_0x370151['value']='environment',updateUserBindingFormForResourceType('environment');}function onUserBindingResourceTypeChange(){const _0x5cc1f1=document['getElementById']('user-binding-resource-type')['value'];updateUserBindingFormForResourceType(_0x5cc1f1);}function updateUserBindingFormForResourceType(_0x25f065){const _0x5517af=document['getElementById']('user-binding-resource-container'),_0x350ff6=document['getElementById']('user-binding-resource'),_0x36c075=document['getElementById']('user-binding-role');if(_0x25f065==='server')_0x5517af['style']['display']='none';else{_0x5517af['style']['display']='';if(_0x25f065==='environment'){const _0x237638=new Set(state['userBindings']['filter'](_0x74c6a2=>_0x74c6a2['resource_type']==='environment')['map'](_0x281132=>_0x281132['resource_id'])),_0x20c834=state['environments']['filter'](_0x2ac99b=>!_0x237638['has'](_0x2ac99b['name']));_0x350ff6['innerHTML']=_0x20c834['length']?_0x20c834['map'](_0x180dc9=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x180dc9['name'])+'\x22>'+Utils['escapeHtml'](_0x180dc9['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x25f065==='team'){const _0x46d0a3=new Set(state['userBindings']['filter'](_0x48b525=>_0x48b525['resource_type']==='team')['map'](_0x5e21d1=>_0x5e21d1['resource_id'])),_0x8f8eb5=state['teams']['filter'](_0x11b1bd=>!_0x46d0a3['has'](_0x11b1bd['id']));_0x350ff6['innerHTML']=_0x8f8eb5['length']?_0x8f8eb5['map'](_0x13d086=>'<option\x20value=\x22'+_0x13d086['id']+'\x22>'+Utils['escapeHtml'](_0x13d086['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x115507=state['roles']['filter'](_0x146426=>_0x146426['resource_type']===_0x25f065);_0x36c075['innerHTML']=_0x115507['length']?_0x115507['filter'](_0xe7fb24=>{const _0x220f14=_0x25f065==='server'?undefined:_0x350ff6['value'];return!state['userBindings']['some'](_0x52205c=>_0x52205c['resource_type']===_0x25f065&&_0x52205c['role_id']===_0xe7fb24['id']&&(_0x25f065==='server'||_0x52205c['resource_id']===_0x220f14));})['map'](_0x183416=>'<option\x20value=\x22'+_0x183416['id']+'\x22>'+Utils['escapeHtml'](_0x183416['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 _0x123ba5=document['getElementById']('user-binding-resource-type')['value'],_0x56e7e1=document['getElementById']('user-binding-role')['value'];if(!_0x56e7e1||!state['bindingsUserId'])return;const _0x5d7c3d=_0x123ba5==='server'?undefined:document['getElementById']('user-binding-resource')['value'];if(_0x123ba5!=='server'&&!_0x5d7c3d)return;const _0x72c6c6=document['getElementById']('save-user-binding-btn');_0x72c6c6['disabled']=!![],_0x72c6c6['textContent']='Adding…';try{const _0x2b8a6={'subject_type':'user','subject_id':state['bindingsUserId'],'role_id':_0x56e7e1,'resource_type':_0x123ba5};if(_0x5d7c3d)_0x2b8a6['resource_id']=_0x5d7c3d;await API['createBinding'](_0x2b8a6),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(_0x263256){Utils['showToast'](_0x263256['message'],'error');}finally{_0x72c6c6['disabled']=![],_0x72c6c6['textContent']='Add\x20Binding';}}window['deleteUserBindingClick']=async function(_0x576f07){try{await API['deleteBinding'](_0x576f07),Utils['showToast']('Binding\x20removed','success'),state['bindingsDirty']=!![],await loadUserBindings(state['bindingsUserId']);}catch(_0x2686c5){Utils['showToast'](_0x2686c5['message'],'error');}};function showCreateUserModal(){state['editingUserId']=null;const _0x1e05af=document['getElementById']('user-modal'),_0x39f7c0=document['getElementById']('modal-title'),_0x833472=document['getElementById']('user-password'),_0x141507=document['getElementById']('password-required'),_0x56ba3b=document['getElementById']('password-hint'),_0x290748=document['getElementById']('skip-password-container'),_0x28bc34=document['getElementById']('skip-password');_0x39f7c0['textContent']='Create\x20User',document['getElementById']('user-form')['reset'](),_0x833472['required']=!![];if(_0x141507)_0x141507['textContent']='*';_0x290748&&(_0x290748['style']['display']='block',_0x28bc34['checked']=![]),_0x56ba3b&&(_0x56ba3b['textContent']='Minimum\x208\x20characters'),_0x1e05af['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);}window['editUser']=function(_0x3d3b82){const _0x32669f=state['users']['find'](_0x56b556=>_0x56b556['id']===_0x3d3b82);if(!_0x32669f)return;state['editingUserId']=_0x3d3b82;const _0x1258f1=document['getElementById']('user-modal'),_0x643e5f=document['getElementById']('modal-title'),_0x3e8f0a=document['getElementById']('user-password'),_0x507d5b=document['getElementById']('password-required'),_0x4bc282=document['getElementById']('password-hint'),_0x43c0ac=document['getElementById']('skip-password-container');_0x643e5f['textContent']='Edit\x20User',document['getElementById']('user-username')['value']=_0x32669f['username'],document['getElementById']('user-name')['value']=_0x32669f['name'],document['getElementById']('user-email')['value']=_0x32669f['email'],_0x3e8f0a['value']='',_0x3e8f0a['required']=![];if(_0x507d5b)_0x507d5b['textContent']='';_0x43c0ac&&(_0x43c0ac['style']['display']='none'),_0x4bc282&&(_0x4bc282['textContent']='Leave\x20blank\x20to\x20keep\x20current\x20password'),_0x1258f1['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);};function hideUserModal(){const _0x10f697=document['getElementById']('user-modal'),_0x5366f1=document['getElementById']('form-error'),_0x3e4340=document['getElementById']('save-user');_0x10f697['hidden']=!![],_0x5366f1['hidden']=!![],state['editingUserId']=null,_0x3e4340&&(_0x3e4340['disabled']=![],_0x3e4340['textContent']='Save\x20User');}async function saveUser(){const _0x47d61f=document['getElementById']('user-form'),_0x26672b=document['getElementById']('skip-password')?.['checked']||![];if(!_0x26672b&&!_0x47d61f['checkValidity']()){_0x47d61f['reportValidity']();return;}const _0x56f2fd=document['getElementById']('form-error'),_0x579f2f=document['getElementById']('save-user'),_0x452638=document['getElementById']('user-username')['value']['trim'](),_0x3adc26=document['getElementById']('user-name')['value']['trim'](),_0x50eb52=document['getElementById']('user-email')['value']['trim'](),_0x2a8a30=document['getElementById']('user-password')['value'];if(!_0x452638||!_0x3adc26||!_0x50eb52){_0x56f2fd['textContent']='Please\x20fill\x20in\x20all\x20required\x20fields',_0x56f2fd['hidden']=![],_0x56f2fd['scrollIntoView']({'behavior':'smooth','block':'nearest'});return;}_0x56f2fd['hidden']=!![];const _0x1844b0=_0x579f2f['textContent'];_0x579f2f['disabled']=!![],_0x579f2f['textContent']=state['editingUserId']?'Updating...':'Creating...';try{if(state['editingUserId']){const _0x504f25={'username':_0x452638,'name':_0x3adc26,'email':_0x50eb52};_0x2a8a30&&(_0x504f25['password']=_0x2a8a30),await API['updateUser'](state['editingUserId'],_0x504f25),Utils['showToast']('User\x20updated\x20successfully','success'),await loadUsers(),hideUserModal();}else{const _0x590aa8={'username':_0x452638,'name':_0x3adc26,'email':_0x50eb52};if(!_0x26672b){if(!_0x2a8a30)throw new Error('Password\x20is\x20required\x20for\x20new\x20users');_0x590aa8['password']=_0x2a8a30;}const _0xb0d5ff=await API['createUser'](_0x590aa8),_0x2a9956=_0xb0d5ff['user'];if(_0x26672b||!_0x2a8a30){const _0x1f373b=await API['createPasswordToken'](_0x2a9956['id'],'setup',![]);state['setupLinkData']={'username':_0x2a9956['username'],'email':_0x2a9956['email'],'url':_0x1f373b['token']['setupUrl'],'userId':_0x2a9956['id'],'type':'setup','emailSent':![]},await loadUsers(),hideUserModal(),showSetupLinkModal();}else Utils['showToast']('User\x20created\x20successfully','success'),await loadUsers(),hideUserModal();}}catch(_0x2532af){console['error']('Failed\x20to\x20save\x20user',_0x2532af),_0x56f2fd['textContent']=_0x2532af['message'],_0x56f2fd['hidden']=![],_0x56f2fd['scrollIntoView']({'behavior':'smooth','block':'nearest'}),_0x579f2f['disabled']=![],_0x579f2f['textContent']=_0x1844b0;}}window['deleteUser']=function(_0x29746a){const _0x2c59ff=state['users']['find'](_0x59bf70=>_0x59bf70['id']===_0x29746a);if(!_0x2c59ff)return;state['deletingUserId']=_0x29746a;const _0x4e52f4=document['getElementById']('delete-modal'),_0x36c707=document['getElementById']('delete-user-name');_0x36c707['textContent']=_0x2c59ff['name']+'\x20('+_0x2c59ff['username']+')',_0x4e52f4['hidden']=![];};function hideDeleteModal(){const _0x3ee7cc=document['getElementById']('delete-modal');_0x3ee7cc['hidden']=!![],state['deletingUserId']=null;const _0x11e1af=document['getElementById']('confirm-delete');_0x11e1af&&(_0x11e1af['disabled']=![],_0x11e1af['textContent']='Delete\x20User');}async function confirmDeleteUser(){if(!state['deletingUserId'])return;const _0x24c04d=document['getElementById']('confirm-delete'),_0x459b6e=_0x24c04d['textContent'];_0x24c04d['disabled']=!![],_0x24c04d['textContent']='Deleting...';try{await API['deleteUser'](state['deletingUserId']),Utils['showToast']('User\x20deleted\x20successfully','success'),await loadUsers(),hideDeleteModal();}catch(_0x178b3b){console['error']('Failed\x20to\x20delete\x20user',_0x178b3b),Utils['showToast']('Failed\x20to\x20delete\x20user:\x20'+_0x178b3b['message'],'error'),_0x24c04d['disabled']=![],_0x24c04d['textContent']=_0x459b6e;}}function handleSkipPasswordChange(_0x34c624){const _0x87b23f=document['getElementById']('user-password'),_0x3a901a=_0x34c624['target']['checked'];_0x3a901a?(_0x87b23f['required']=![],_0x87b23f['disabled']=!![],_0x87b23f['value']=''):(_0x87b23f['required']=!![],_0x87b23f['disabled']=![]);}function showSetupLinkModal(){if(!state['setupLinkData'])return;const _0x521531=document['getElementById']('setup-link-modal'),_0x21d200=document['getElementById']('setup-link-username'),_0x9ff544=document['getElementById']('setup-link-url'),_0x52e780=document['getElementById']('email-setup-link'),_0x5507d4=document['getElementById']('email-button-text');_0x21d200['textContent']=state['setupLinkData']['username'],_0x9ff544['textContent']=state['setupLinkData']['url'],_0x52e780&&_0x5507d4&&(_0x52e780['disabled']=![],_0x5507d4['textContent']='Email\x20Link',state['emailConfigured']&&!state['setupLinkData']['emailSent']?_0x52e780['style']['display']='inline-block':_0x52e780['style']['display']='none'),_0x521531['hidden']=![];}function hideSetupLinkModal(){const _0x81522b=document['getElementById']('setup-link-modal');_0x81522b['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(_0xf70c0e){console['error']('Failed\x20to\x20copy\x20link',_0xf70c0e),Utils['showToast']('Failed\x20to\x20copy\x20link','error');}}async function emailSetupLink(){if(!state['setupLinkData'])return;const _0x550d28=document['getElementById']('email-setup-link'),_0x1f507b=document['getElementById']('email-button-text');if(!_0x550d28||!_0x1f507b)return;const _0x71405e=_0x1f507b['textContent'];_0x550d28['disabled']=!![],_0x1f507b['textContent']='Sending...';try{const _0x517f2a=await API['createPasswordToken'](state['setupLinkData']['userId'],state['setupLinkData']['type'],!![]);if(_0x517f2a['emailSent'])Utils['showToast']('Email\x20sent\x20to\x20'+state['setupLinkData']['email'],'success'),state['setupLinkData']['emailSent']=!![],_0x550d28['style']['display']='none';else{const _0x48fc5f=_0x517f2a['emailError']||'Failed\x20to\x20send\x20email';Utils['showToast'](_0x48fc5f,'error'),_0x550d28['disabled']=![],_0x1f507b['textContent']=_0x71405e;}}catch(_0x2cbb69){console['error']('Failed\x20to\x20email\x20setup\x20link',_0x2cbb69),Utils['showToast']('Failed\x20to\x20send\x20email:\x20'+_0x2cbb69['message'],'error'),_0x550d28['disabled']=![],_0x1f507b['textContent']=_0x71405e;}}window['resetPassword']=async function(_0x364541){const _0x5116bf=state['users']['find'](_0x4ab6b8=>_0x4ab6b8['id']===_0x364541);if(!_0x5116bf)return;const _0xbbd5f6=await ConfirmDialog['show']({'title':'Reset\x20Password','message':'Generate\x20a\x20password\x20reset\x20link\x20for\x20'+_0x5116bf['name']+'\x20('+_0x5116bf['username']+')?\x20This\x20will\x20create\x20a\x20link\x20that\x20they\x20can\x20use\x20to\x20set\x20a\x20new\x20password.','confirmText':'Generate\x20Link'});if(!_0xbbd5f6)return;try{const _0xd1bbcb=await API['createPasswordToken'](_0x364541,'reset',![]);state['setupLinkData']={'username':_0x5116bf['username'],'email':_0x5116bf['email'],'url':_0xd1bbcb['token']['setupUrl'],'userId':_0x5116bf['id'],'type':'reset','emailSent':![]},showSetupLinkModal();}catch(_0x36437f){console['error']('Failed\x20to\x20create\x20password\x20reset\x20link',_0x36437f),Utils['showToast']('Failed\x20to\x20create\x20password\x20reset\x20link:\x20'+_0x36437f['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');}};