@profoundlogic/coderflow-server 0.9.1 → 0.9.3
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.
- package/dist/coder-server.js +1 -1
- package/dist/config/skill-catalog.json +1 -1
- package/dist/config.js +1 -1
- package/dist/lib/agent-keepalive.js +1 -1
- package/dist/lib/agent-models.js +1 -1
- package/dist/lib/api-keys.js +1 -1
- package/dist/lib/apiKeys.js +1 -1
- package/dist/lib/app-server-ports.js +1 -1
- package/dist/lib/auto-judge.js +1 -1
- package/dist/lib/automation-service.js +1 -1
- package/dist/lib/basic-auth.js +1 -1
- package/dist/lib/bindings.js +1 -1
- package/dist/lib/build-history.js +1 -1
- package/dist/lib/build-output-service.js +1 -1
- package/dist/lib/build-scheduler.js +1 -1
- package/dist/lib/build-service.js +1 -1
- package/dist/lib/ca-certificates.js +1 -1
- package/dist/lib/claude-oauth-refresh.js +1 -1
- package/dist/lib/cli/build.js +1 -1
- package/dist/lib/cli/cleanup-users.js +1 -1
- package/dist/lib/cli/config-command.js +1 -1
- package/dist/lib/cli/config.js +1 -1
- package/dist/lib/cli/create-user.js +1 -1
- package/dist/lib/cli/grant-admin.js +1 -1
- package/dist/lib/cli/init.js +1 -1
- package/dist/lib/cli/jira.js +1 -1
- package/dist/lib/cli/license.js +1 -1
- package/dist/lib/cli/list-roles.js +1 -1
- package/dist/lib/cli/list-users.js +1 -1
- package/dist/lib/cli/server-manager.js +1 -1
- package/dist/lib/cli/set-password.js +1 -1
- package/dist/lib/compression-filter.js +1 -1
- package/dist/lib/config-migration.js +1 -1
- package/dist/lib/container-credential-sync.js +1 -1
- package/dist/lib/container-tokens.js +1 -1
- package/dist/lib/data-dir.js +1 -1
- package/dist/lib/deployment-history.js +1 -1
- package/dist/lib/deployment-service.js +1 -1
- package/dist/lib/docker-utils.js +1 -1
- package/dist/lib/email.js +1 -1
- package/dist/lib/emailTemplates.js +1 -1
- package/dist/lib/entitlement.js +1 -1
- package/dist/lib/external-connections.js +1 -1
- package/dist/lib/fetch-utils.js +1 -1
- package/dist/lib/git-commit-details-route.js +1 -1
- package/dist/lib/git-history-diff-guardrails.js +1 -1
- package/dist/lib/git-provider-service.js +1 -1
- package/dist/lib/git-provider-setup/github-setup-handler.js +1 -1
- package/dist/lib/git-provider-setup/index.js +1 -1
- package/dist/lib/git-provider-setup/setup-factory.js +1 -1
- package/dist/lib/git-provider-setup/setup-interface.js +1 -1
- package/dist/lib/git-providers/azure-devops-provider.js +1 -1
- package/dist/lib/git-providers/github-app-provider.js +1 -1
- package/dist/lib/git-providers/index.js +1 -1
- package/dist/lib/git-providers/provider-factory.js +1 -1
- package/dist/lib/git-providers/provider-interface.js +1 -1
- package/dist/lib/github-urls.js +1 -1
- package/dist/lib/group-objective-linking.js +1 -1
- package/dist/lib/ibmi-sync.js +1 -1
- package/dist/lib/jira-client.js +1 -1
- package/dist/lib/judge-blinding.js +1 -1
- package/dist/lib/logger.js +1 -1
- package/dist/lib/memory-utils.js +1 -1
- package/dist/lib/migration-to-scoped-rbac.js +1 -1
- package/dist/lib/model-fetcher.js +1 -1
- package/dist/lib/notifications.js +1 -1
- package/dist/lib/objective-context.js +1 -1
- package/dist/lib/oidc-auth.js +1 -1
- package/dist/lib/oidc-device-flow.js +1 -1
- package/dist/lib/passwordTokens.js +1 -1
- package/dist/lib/permission-resolver.js +1 -1
- package/dist/lib/pin-cascade.js +1 -1
- package/dist/lib/provider-accounts.js +1 -1
- package/dist/lib/provider-oauth.js +1 -1
- package/dist/lib/provider-profile.js +1 -1
- package/dist/lib/provider-token-refresh.js +1 -1
- package/dist/lib/rbac-user-state.js +1 -1
- package/dist/lib/request-url.js +1 -1
- package/dist/lib/rewind.js +1 -1
- package/dist/lib/role-definitions.js +1 -1
- package/dist/lib/roles.js +1 -1
- package/dist/lib/secrets.js +1 -1
- package/dist/lib/session-file-store.js +1 -0
- package/dist/lib/setup-repo-git-auth.js +1 -1
- package/dist/lib/slack-service.js +1 -1
- package/dist/lib/state-capture.js +1 -1
- package/dist/lib/static-files.js +1 -1
- package/dist/lib/task-aliases.js +1 -1
- package/dist/lib/task-container-init.js +1 -1
- package/dist/lib/task-context-usage.js +1 -1
- package/dist/lib/task-git-auth-errors.js +1 -1
- package/dist/lib/task-name-format.js +1 -1
- package/dist/lib/task-name-generator.js +1 -1
- package/dist/lib/task-source-metadata.js +1 -1
- package/dist/lib/teams.js +1 -1
- package/dist/lib/user-git-oauth.js +1 -1
- package/dist/lib/user-git-tokens.js +1 -1
- package/dist/lib/users.js +1 -1
- package/dist/middleware/requireAuth.js +1 -1
- package/dist/middleware/requireInit.js +1 -1
- package/dist/middleware/requirePermission.js +1 -1
- package/dist/package.json +1 -1
- package/dist/playwright.config.js +1 -1
- package/dist/playwright.task-terminal.config.js +1 -1
- package/dist/routes/apiKeys.js +1 -1
- package/dist/routes/auth-oidc.js +1 -1
- package/dist/routes/auth.js +1 -1
- package/dist/routes/automations.js +1 -1
- package/dist/routes/bindings.js +1 -1
- package/dist/routes/build.js +1 -1
- package/dist/routes/containers.js +1 -1
- package/dist/routes/deploy-task.js +1 -1
- package/dist/routes/environment-management.js +1 -1
- package/dist/routes/environments.js +1 -1
- package/dist/routes/external-skills.js +1 -1
- package/dist/routes/git-credentials.js +1 -1
- package/dist/routes/git-oauth.js +1 -1
- package/dist/routes/git-provider-setup.js +1 -1
- package/dist/routes/health.js +1 -1
- package/dist/routes/jira.js +1 -1
- package/dist/routes/logs.js +1 -1
- package/dist/routes/objective-management.js +1 -1
- package/dist/routes/password.js +1 -1
- package/dist/routes/prompt.js +1 -1
- package/dist/routes/provider-auth.js +1 -1
- package/dist/routes/qa.js +1 -1
- package/dist/routes/roles.js +1 -1
- package/dist/routes/settings.js +1 -1
- package/dist/routes/skill-management.js +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/slack.js +1 -1
- package/dist/routes/stats.js +1 -1
- package/dist/routes/tasks.js +1 -1
- package/dist/routes/teams.js +1 -1
- package/dist/routes/templates.js +1 -1
- package/dist/routes/test-task.js +1 -1
- package/dist/routes/test.js +1 -1
- package/dist/routes/users.js +1 -1
- package/dist/routes/visualizations.js +1 -1
- package/dist/scripts/create-user.js +1 -1
- package/dist/scripts/migrate-config-to-data-dir.js +1 -1
- package/dist/start.js +1 -1
- package/dist/web-ui/public/activity-detail-modal.js +1 -1
- package/dist/web-ui/public/activity-feed.js +1 -1
- package/dist/web-ui/public/activity-formatters.js +1 -1
- package/dist/web-ui/public/admin.html +6 -6
- package/dist/web-ui/public/admin.js +1 -1
- package/dist/web-ui/public/agent-event-parser.js +1 -1
- package/dist/web-ui/public/app.js +1 -1
- package/dist/web-ui/public/approve-dialog.js +1 -1
- package/dist/web-ui/public/automation-links.js +1 -1
- package/dist/web-ui/public/automation-schedule.js +1 -1
- package/dist/web-ui/public/comments-widget.js +1 -1
- package/dist/web-ui/public/diff-utils.js +1 -1
- package/dist/web-ui/public/docs/admin/automations.md +2 -1
- package/dist/web-ui/public/docs/admin/environments.md +2 -0
- package/dist/web-ui/public/docs/code/files-and-editing.md +1 -4
- package/dist/web-ui/public/docs/docsify-proxy-helper.js +1 -1
- package/dist/web-ui/public/environments.css +28 -0
- package/dist/web-ui/public/environments.html +33 -7
- package/dist/web-ui/public/environments.js +1 -1
- package/dist/web-ui/public/feedback-widget.js +1 -1
- package/dist/web-ui/public/file-selection-tree.js +1 -1
- package/dist/web-ui/public/git-history-lazy-utils.js +1 -1
- package/dist/web-ui/public/git-history.html +1 -1
- package/dist/web-ui/public/git-history.js +1 -1
- package/dist/web-ui/public/git-status.js +1 -1
- package/dist/web-ui/public/ibmi-file-filter.js +1 -1
- package/dist/web-ui/public/index.html +1 -1
- package/dist/web-ui/public/index.js +1 -1
- package/dist/web-ui/public/login.js +1 -1
- package/dist/web-ui/public/markdown-editor.js +1 -1
- package/dist/web-ui/public/markdown-file-editor.js +1 -1
- package/dist/web-ui/public/modal-maximize.js +1 -1
- package/dist/web-ui/public/notifications.js +1 -1
- package/dist/web-ui/public/permissions.js +1 -1
- package/dist/web-ui/public/pr-dialog.js +1 -1
- package/dist/web-ui/public/roles.html +1 -1
- package/dist/web-ui/public/roles.js +1 -1
- package/dist/web-ui/public/settings.html +1 -1
- package/dist/web-ui/public/settings.js +1 -1
- package/dist/web-ui/public/setup-password.js +1 -1
- package/dist/web-ui/public/skills.html +1 -1
- package/dist/web-ui/public/skills.js +1 -1
- package/dist/web-ui/public/sse-client.js +1 -1
- package/dist/web-ui/public/sse-client.transport-warning.js +1 -1
- package/dist/web-ui/public/sse-shared-worker.js +1 -1
- package/dist/web-ui/public/task-judging-helpers.js +1 -1
- package/dist/web-ui/public/task.js +1 -1
- package/dist/web-ui/public/teams.html +2 -2
- package/dist/web-ui/public/teams.js +1 -1
- package/dist/web-ui/public/terminal.js +1 -1
- package/dist/web-ui/public/theme.js +1 -1
- package/dist/web-ui/public/users.html +2 -2
- package/dist/web-ui/public/users.js +1 -1
- package/dist/web-ui/public/variant-grouping.js +1 -1
- package/package.json +1 -1
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
</div>
|
|
127
127
|
</div>
|
|
128
128
|
|
|
129
|
-
<div id="teams-loading" class="loading">Loading teams
|
|
129
|
+
<div id="teams-loading" class="loading">Loading teams</div>
|
|
130
130
|
<div id="teams-error" class="empty-state" hidden>
|
|
131
131
|
<h3>Failed to load teams</h3>
|
|
132
132
|
<p id="teams-error-message" class="text-muted"></p>
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
<button class="modal-close" id="close-bindings-modal">×</button>
|
|
211
211
|
</div>
|
|
212
212
|
<div class="modal-body">
|
|
213
|
-
<div id="bindings-loading" class="loading" hidden>Loading bindings
|
|
213
|
+
<div id="bindings-loading" class="loading" hidden>Loading bindings</div>
|
|
214
214
|
<div id="bindings-empty" hidden style="padding: 1.5rem 0; text-align: center; color: var(--color-text-secondary);">
|
|
215
215
|
No access bindings for this team yet.
|
|
216
216
|
</div>
|
|
@@ -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 _0x842c23=state['currentUser'];if(!Permissions['hasServerPermission'](_0x842c23,'teams:view')&&!Permissions['hasTeamPermission'](_0x842c23,'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'](_0x842c23,'*')||Permissions['hasTeamPermission'](_0x842c23,'teams:manage'))&&(document['getElementById']('create-team-btn')['hidden']=![]),bindEventListeners(),await Promise['all']([loadTeams(),loadUsers(),loadRoles(),loadEnvironments()]),renderTeams();});async function loadTeams(){const _0xaac75d=document['getElementById']('teams-loading'),_0x5bb4f3=document['getElementById']('teams-error'),_0x44418e=document['getElementById']('teams-content');try{_0xaac75d['hidden']=![],_0x5bb4f3['hidden']=!![],_0x44418e['hidden']=!![];const {teams:_0x1c7591}=await API['getTeams']();state['teams']=_0x1c7591||[],renderTeams(),_0xaac75d['hidden']=!![],_0x44418e['hidden']=![];}catch(_0xdfd0a1){_0xaac75d['hidden']=!![],_0x5bb4f3['hidden']=![],document['getElementById']('teams-error-message')['textContent']=_0xdfd0a1['message'];}}async function loadUsers(){try{const {users:_0x235a36}=await API['getUsers']();state['users']=_0x235a36||[];}catch{state['users']=[];}}async function loadRoles(){try{const {roles:_0x3366cc}=await API['getRoleDefinitions']();state['roles']=_0x3366cc||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x36d53b=await API['getEnvironments']();state['environments']=_0x36d53b['environments']||[];}catch{state['environments']=[];}}function renderTeams(){const _0x27f904=document['getElementById']('teams-table-body'),_0x539e58=document['getElementById']('team-count');if(!_0x27f904)return;_0x539e58&&(_0x539e58['textContent']=state['teams']['length']+'\x20team'+(state['teams']['length']===0x1?'':'s'));if(state['teams']['length']===0x0){_0x27f904['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 _0xf3dd8f=Permissions['hasServerPermission'](state['currentUser'],'*');_0x27f904['innerHTML']=state['teams']['map'](_0x4f0b15=>{const _0x580607=_0xf3dd8f||_0x4f0b15['canManageTeam'],_0x574eaf=_0xf3dd8f||_0x4f0b15['canManageMembers'],_0x5bfb66=_0x580607||_0x574eaf,_0x507009=(_0x4f0b15['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'](_0x4f0b15['name'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4f0b15['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x4f0b15['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x507009+'</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'+(_0x5bfb66?'<button\x20class=\x22btn-icon\x22\x20title=\x22Edit\x20team\x22\x20onclick=\x22window.openTeamModal(\x27'+_0x4f0b15['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'+(_0x580607?'<button\x20class=\x22btn-icon\x22\x20title=\x22Access\x20bindings\x22\x20onclick=\x22window.openBindingsModal(\x27'+_0x4f0b15['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'+(_0x580607?'<button\x20class=\x22btn-icon\x20btn-danger\x22\x20title=\x22Delete\x20team\x22\x20onclick=\x22window.deleteTeam(\x27'+_0x4f0b15['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(_0x36c694){const _0x110ce6=state['teams']['find'](_0x5c920a=>_0x5c920a['id']===_0x36c694);if(!_0x110ce6)return;state['editingTeamId']=_0x36c694;const _0x2811b1=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x21aa4b=_0x2811b1||_0x110ce6['canManageTeam'],_0x32fd6e=_0x2811b1||_0x110ce6['canManageMembers'],_0x200394=_0x21aa4b,_0x3f5283=_0x21aa4b||_0x32fd6e,_0x415279=_0x110ce6['name'],_0x498d87=_0x110ce6['description']||'';state['modalSnapshot']={'name':_0x415279,'description':_0x498d87},document['getElementById']('team-modal-title')['textContent']=_0x415279,document['getElementById']('team-name')['value']=_0x415279,document['getElementById']('team-name')['disabled']=!_0x200394,document['getElementById']('team-description')['value']=_0x498d87,document['getElementById']('team-description')['disabled']=!_0x200394,document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=![],document['getElementById']('save-team')['hidden']=!_0x200394,renderMembersList(_0x110ce6),updateMemberSelect(_0x110ce6),document['getElementById']('team-modal')['hidden']=![];};function isTeamModalDirty(){if(!state['modalSnapshot'])return![];const _0x3c6999=document['getElementById']('team-name')['value']['trim'](),_0x5c640c=document['getElementById']('team-description')['value']['trim']();return _0x3c6999!==state['modalSnapshot']['name']||_0x5c640c!==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(_0x28eb86){const _0x18e36c=state['teams']['find'](_0xa2085e=>_0xa2085e['id']===_0x28eb86);if(!_0x18e36c)return;state['bindingsTeamId']=_0x28eb86,document['getElementById']('bindings-modal-title')['textContent']='Access\x20Bindings\x20—\x20'+_0x18e36c['name'],document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('bindings-modal')['hidden']=![],loadTeamBindings(_0x28eb86);};function hideBindingsModal(){document['getElementById']('bindings-modal')['hidden']=!![],state['bindingsTeamId']=null;}function renderMembersList(_0x198be6){const _0x3525bf=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x396852=_0x3525bf||_0x198be6['canManageMembers']||_0x198be6['canManageTeam'],_0x13e343=_0x198be6['members']||[],_0x7471c9=document['getElementById']('members-list');if(_0x13e343['length']===0x0){_0x7471c9['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x20margin:\x200.25rem\x200;\x22>No\x20members\x20yet</p>';return;}_0x7471c9['innerHTML']=_0x13e343['map'](_0x379188=>{const _0x3d7e12=state['users']['find'](_0x1db81d=>_0x1db81d['id']===_0x379188),_0x1883d4=_0x3d7e12?''+Utils['escapeHtml'](_0x3d7e12['username'])+(_0x3d7e12['name']?'\x20<span\x20style=\x22color:\x20var(--color-text-secondary);\x20font-size:\x200.85em;\x22>('+Utils['escapeHtml'](_0x3d7e12['name'])+')</span>':''):Utils['escapeHtml'](_0x379188);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'+_0x1883d4+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x396852?'<button\x20type=\x22button\x22\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.removeMemberClick(\x27'+_0x379188+'\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 _0x20e0ab=document['getElementById']('add-member-row');if(_0x20e0ab)_0x20e0ab['style']['display']=_0x396852?'flex':'none';}function updateMemberSelect(_0x36ac07){const _0x4ae84b=document['getElementById']('add-member-select');if(!_0x4ae84b)return;const _0x24f52f=new Set(_0x36ac07['members']||[]),_0x2f7e57=state['users']['filter'](_0x4feae5=>!_0x24f52f['has'](_0x4feae5['id']));_0x4ae84b['innerHTML']='<option\x20value=\x22\x22>Add\x20a\x20member…</option>'+_0x2f7e57['map'](_0x21d9a5=>'<option\x20value=\x22'+_0x21d9a5['id']+'\x22>'+Utils['escapeHtml'](_0x21d9a5['username'])+(_0x21d9a5['name']?'\x20('+Utils['escapeHtml'](_0x21d9a5['name'])+')':'')+'</option>')['join']('');}async function addMember(){const _0x297773=document['getElementById']('add-member-select'),_0x36775c=_0x297773['value'];if(!_0x36775c||!state['editingTeamId'])return;try{const {team:_0x2d8060}=await API['addTeamMember'](state['editingTeamId'],_0x36775c);syncTeamInState(_0x2d8060),renderMembersList(_0x2d8060),updateMemberSelect(_0x2d8060),_0x297773['value']='',Utils['showToast']('Member\x20added','success');}catch(_0x487589){Utils['showToast'](_0x487589['message'],'error');}}window['removeMemberClick']=async function(_0x31d193){if(!state['editingTeamId'])return;try{const {team:_0x3a13ac}=await API['removeTeamMember'](state['editingTeamId'],_0x31d193);syncTeamInState(_0x3a13ac),renderMembersList(_0x3a13ac),updateMemberSelect(_0x3a13ac),Utils['showToast']('Member\x20removed','success');}catch(_0x59e887){Utils['showToast'](_0x59e887['message'],'error');}};async function loadTeamBindings(_0xe70225){const _0x49a7cd=document['getElementById']('bindings-loading'),_0x2c0aaa=document['getElementById']('bindings-empty'),_0x35b9a7=document['getElementById']('bindings-list-container'),_0x3cbd1f=document['getElementById']('add-binding-btn');_0x49a7cd['hidden']=![],_0x2c0aaa['hidden']=!![],_0x35b9a7['style']['display']='none',_0x3cbd1f['hidden']=!![],document['getElementById']('add-binding-form')['hidden']=!![];try{const {bindings:_0x4fe4f5}=await API['getBindings']({'subject_type':'team','subject_id':_0xe70225});state['teamBindings']=_0x4fe4f5||[],_0x49a7cd['hidden']=!![],state['teamBindings']['length']===0x0?_0x2c0aaa['hidden']=![]:(_0x35b9a7['style']['display']='',renderBindingsTable()),(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage'))&&(_0x3cbd1f['hidden']=![]);}catch(_0x444800){_0x49a7cd['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x444800['message'],'error');}}function renderBindingsTable(){const _0x48f6a0=document['getElementById']('bindings-table-body');if(!_0x48f6a0)return;const _0x4b04aa=Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage');_0x48f6a0['innerHTML']=state['teamBindings']['map'](_0x3e27ea=>{const _0x270491=_0x3e27ea['resource_type']==='server'?'Server':_0x3e27ea['resource_id']==='*'?'All\x20'+_0x3e27ea['resource_type']+'s':Utils['escapeHtml'](_0x3e27ea['resource_name']||_0x3e27ea['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x270491+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x3e27ea['role_name']||_0x3e27ea['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x4b04aa?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteBindingClick(\x27'+_0x3e27ea['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 _0x4e343a=document['getElementById']('binding-resource-type');_0x4e343a['value']='environment',updateBindingFormForResourceType('environment');}function onBindingResourceTypeChange(){const _0x5406ef=document['getElementById']('binding-resource-type')['value'];updateBindingFormForResourceType(_0x5406ef);}function updateBindingFormForResourceType(_0x1a44e1){const _0x5d2971=document['getElementById']('binding-resource-container'),_0x226ada=document['getElementById']('binding-resource'),_0x214d6e=document['getElementById']('binding-role');if(_0x1a44e1==='server')_0x5d2971['style']['display']='none';else{_0x5d2971['style']['display']='';if(_0x1a44e1==='environment'){const _0x2b18a6=new Set(state['teamBindings']['filter'](_0x5a6ab2=>_0x5a6ab2['resource_type']==='environment')['map'](_0xdbe42d=>_0xdbe42d['resource_id'])),_0x189b6e=state['environments']['filter'](_0x3e6005=>!_0x2b18a6['has'](_0x3e6005['name']));_0x226ada['innerHTML']=_0x189b6e['length']?_0x189b6e['map'](_0x3cefe4=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x3cefe4['name'])+'\x22>'+Utils['escapeHtml'](_0x3cefe4['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x1a44e1==='team'){const _0x1ae298=new Set(state['teamBindings']['filter'](_0x29e23f=>_0x29e23f['resource_type']==='team')['map'](_0xb131c=>_0xb131c['resource_id'])),_0x2ba614=state['teams']['filter'](_0x223a2a=>!_0x1ae298['has'](_0x223a2a['id']));_0x226ada['innerHTML']=_0x2ba614['length']?_0x2ba614['map'](_0x24f13e=>'<option\x20value=\x22'+_0x24f13e['id']+'\x22>'+Utils['escapeHtml'](_0x24f13e['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x5977c1=state['roles']['filter'](_0x9d4cbb=>_0x9d4cbb['resource_type']===_0x1a44e1);_0x214d6e['innerHTML']=_0x5977c1['length']?_0x5977c1['filter'](_0x254ab4=>{const _0x1d35f3=_0x1a44e1==='server'?undefined:_0x226ada['value'];return!state['teamBindings']['some'](_0x6f4285=>_0x6f4285['resource_type']===_0x1a44e1&&_0x6f4285['role_id']===_0x254ab4['id']&&(_0x1a44e1==='server'||_0x6f4285['resource_id']===_0x1d35f3));})['map'](_0x2dc173=>'<option\x20value=\x22'+_0x2dc173['id']+'\x22>'+Utils['escapeHtml'](_0x2dc173['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 _0x418ceb=document['getElementById']('binding-resource-type')['value'],_0x4af929=document['getElementById']('binding-role')['value'];if(!_0x4af929||!state['bindingsTeamId'])return;const _0x3e76bb=_0x418ceb==='server'?undefined:document['getElementById']('binding-resource')['value'];if(_0x418ceb!=='server'&&!_0x3e76bb)return;const _0x46c59f=document['getElementById']('save-binding-btn');_0x46c59f['disabled']=!![],_0x46c59f['textContent']='Adding…';try{const _0x4bd822={'subject_type':'team','subject_id':state['bindingsTeamId'],'role_id':_0x4af929,'resource_type':_0x418ceb};if(_0x3e76bb)_0x4bd822['resource_id']=_0x3e76bb;await API['createBinding'](_0x4bd822),Utils['showToast']('Binding\x20added','success'),document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![],await loadTeamBindings(state['bindingsTeamId']);}catch(_0x39fa1f){Utils['showToast'](_0x39fa1f['message'],'error');}finally{_0x46c59f['disabled']=![],_0x46c59f['textContent']='Add\x20Binding';}}window['deleteBindingClick']=async function(_0x3eb411){try{await API['deleteBinding'](_0x3eb411),Utils['showToast']('Binding\x20removed','success'),await loadTeamBindings(state['bindingsTeamId']);}catch(_0x1a0c47){Utils['showToast'](_0x1a0c47['message'],'error');}};async function saveTeam(){const _0x5d443d=document['getElementById']('team-name')['value']['trim'](),_0x291e89=document['getElementById']('team-description')['value']['trim'](),_0x1dcd84=document['getElementById']('team-form-error'),_0x2fffe3=document['getElementById']('save-team');if(!_0x5d443d){_0x1dcd84['textContent']='Team\x20name\x20is\x20required',_0x1dcd84['hidden']=![];return;}_0x1dcd84['hidden']=!![];const _0x2a2386=_0x2fffe3['textContent'];_0x2fffe3['disabled']=!![],_0x2fffe3['textContent']=state['editingTeamId']?'Saving…':'Creating…';try{if(state['editingTeamId']){const {team:_0x372d8b}=await API['updateTeam'](state['editingTeamId'],{'name':_0x5d443d,'description':_0x291e89});syncTeamInState(_0x372d8b),document['getElementById']('team-modal-title')['textContent']=_0x372d8b['name'],Utils['showToast']('Team\x20updated','success');}else await API['createTeam']({'name':_0x5d443d,'description':_0x291e89}),Utils['showToast']('Team\x20created','success');_0x2fffe3['disabled']=![],_0x2fffe3['textContent']=_0x2a2386,hideTeamModal(),await loadTeams();}catch(_0x74cf5c){_0x1dcd84['textContent']=_0x74cf5c['message'],_0x1dcd84['hidden']=![],_0x2fffe3['disabled']=![],_0x2fffe3['textContent']=_0x2a2386;}}window['deleteTeam']=function(_0x5bb6bf){const _0x5c65b0=state['teams']['find'](_0x5f5d7b=>_0x5f5d7b['id']===_0x5bb6bf);if(!_0x5c65b0)return;state['deletingTeamId']=_0x5bb6bf,document['getElementById']('delete-team-name')['textContent']=_0x5c65b0['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 _0xc2fa26=document['getElementById']('confirm-delete-team');_0xc2fa26['disabled']=!![],_0xc2fa26['textContent']='Deleting…';try{await API['deleteTeam'](state['deletingTeamId']),Utils['showToast']('Team\x20deleted','success'),_0xc2fa26['disabled']=![],_0xc2fa26['textContent']='Delete\x20Team',hideDeleteModal(),await loadTeams();}catch(_0x2a9479){Utils['showToast']('Failed\x20to\x20delete\x20team:\x20'+_0x2a9479['message'],'error'),_0xc2fa26['disabled']=![],_0xc2fa26['textContent']='Delete\x20Team';}}function syncTeamInState(_0x53697c){const _0x1f39d3=state['teams']['findIndex'](_0x1c514a=>_0x1c514a['id']===_0x53697c['id']);if(_0x1f39d3>=0x0)state['teams'][_0x1f39d3]=_0x53697c;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 _0x39fb0f=state['currentUser'];if(!Permissions['hasServerPermission'](_0x39fb0f,'teams:view')&&!Permissions['hasTeamPermission'](_0x39fb0f,'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'](_0x39fb0f,'*')||Permissions['hasTeamPermission'](_0x39fb0f,'teams:manage'))&&(document['getElementById']('create-team-btn')['hidden']=![]),bindEventListeners(),await Promise['all']([loadTeams(),loadUsers(),loadRoles(),loadEnvironments()]),renderTeams();});async function loadTeams(){const _0x492dca=document['getElementById']('teams-loading'),_0x279f8a=document['getElementById']('teams-error'),_0x21ece3=document['getElementById']('teams-content');try{_0x492dca['hidden']=![],_0x279f8a['hidden']=!![],_0x21ece3['hidden']=!![];const {teams:_0x576b9c}=await API['getTeams']();state['teams']=_0x576b9c||[],renderTeams(),_0x492dca['hidden']=!![],_0x21ece3['hidden']=![];}catch(_0x4015f8){_0x492dca['hidden']=!![],_0x279f8a['hidden']=![],document['getElementById']('teams-error-message')['textContent']=_0x4015f8['message'];}}async function loadUsers(){try{const {users:_0xc86d44}=await API['getUsers']();state['users']=_0xc86d44||[];}catch{state['users']=[];}}async function loadRoles(){try{const {roles:_0x2470ff}=await API['getRoleDefinitions']();state['roles']=_0x2470ff||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x1f76f3=await API['getEnvironments']();state['environments']=_0x1f76f3['environments']||[];}catch{state['environments']=[];}}function renderTeams(){const _0x1b5040=document['getElementById']('teams-table-body'),_0x4e88a2=document['getElementById']('team-count');if(!_0x1b5040)return;_0x4e88a2&&(_0x4e88a2['textContent']=state['teams']['length']+'\x20team'+(state['teams']['length']===0x1?'':'s'));if(state['teams']['length']===0x0){_0x1b5040['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 _0x4f1753=Permissions['hasServerPermission'](state['currentUser'],'*');_0x1b5040['innerHTML']=state['teams']['map'](_0x1ddee4=>{const _0x5c186e=_0x4f1753||_0x1ddee4['canManageTeam'],_0x3b8e85=_0x4f1753||_0x1ddee4['canManageMembers'],_0x4ed112=_0x5c186e||_0x3b8e85,_0x1d150a=(_0x1ddee4['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'](_0x1ddee4['name'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x1ddee4['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x1ddee4['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x1d150a+'</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'+(_0x4ed112?'<button\x20class=\x22btn-icon\x22\x20title=\x22Edit\x20team\x22\x20onclick=\x22window.openTeamModal(\x27'+_0x1ddee4['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'+(_0x5c186e?'<button\x20class=\x22btn-icon\x22\x20title=\x22Access\x20bindings\x22\x20onclick=\x22window.openBindingsModal(\x27'+_0x1ddee4['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'+(_0x5c186e?'<button\x20class=\x22btn-icon\x20btn-danger\x22\x20title=\x22Delete\x20team\x22\x20onclick=\x22window.deleteTeam(\x27'+_0x1ddee4['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(_0x5559de){const _0x1e23dd=state['teams']['find'](_0x4457c5=>_0x4457c5['id']===_0x5559de);if(!_0x1e23dd)return;state['editingTeamId']=_0x5559de;const _0x1f9c8b=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x5ea88d=_0x1f9c8b||_0x1e23dd['canManageTeam'],_0x20c4c9=_0x1f9c8b||_0x1e23dd['canManageMembers'],_0x370c4f=_0x5ea88d,_0x8db61a=_0x5ea88d||_0x20c4c9,_0x1b3096=_0x1e23dd['name'],_0x73d685=_0x1e23dd['description']||'';state['modalSnapshot']={'name':_0x1b3096,'description':_0x73d685},document['getElementById']('team-modal-title')['textContent']=_0x1b3096,document['getElementById']('team-name')['value']=_0x1b3096,document['getElementById']('team-name')['disabled']=!_0x370c4f,document['getElementById']('team-description')['value']=_0x73d685,document['getElementById']('team-description')['disabled']=!_0x370c4f,document['getElementById']('team-form-error')['hidden']=!![],document['getElementById']('members-section')['hidden']=![],document['getElementById']('save-team')['hidden']=!_0x370c4f,renderMembersList(_0x1e23dd),updateMemberSelect(_0x1e23dd),document['getElementById']('team-modal')['hidden']=![];};function isTeamModalDirty(){if(!state['modalSnapshot'])return![];const _0x2cfc36=document['getElementById']('team-name')['value']['trim'](),_0x45aa62=document['getElementById']('team-description')['value']['trim']();return _0x2cfc36!==state['modalSnapshot']['name']||_0x45aa62!==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(_0x392a08){const _0x1ca1bf=state['teams']['find'](_0x228fa3=>_0x228fa3['id']===_0x392a08);if(!_0x1ca1bf)return;state['bindingsTeamId']=_0x392a08,document['getElementById']('bindings-modal-title')['textContent']='Access\x20Bindings\x20—\x20'+_0x1ca1bf['name'],document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('bindings-modal')['hidden']=![],loadTeamBindings(_0x392a08);};function hideBindingsModal(){document['getElementById']('bindings-modal')['hidden']=!![],state['bindingsTeamId']=null;}function renderMembersList(_0x306326){const _0x29b590=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x1d5d07=_0x29b590||_0x306326['canManageMembers']||_0x306326['canManageTeam'],_0x5e1ce0=_0x306326['members']||[],_0x11a455=document['getElementById']('members-list');if(_0x5e1ce0['length']===0x0){_0x11a455['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x20margin:\x200.25rem\x200;\x22>No\x20members\x20yet</p>';return;}_0x11a455['innerHTML']=_0x5e1ce0['map'](_0x21dd63=>{const _0x1686ac=state['users']['find'](_0x3fd40f=>_0x3fd40f['id']===_0x21dd63),_0x1ce9ea=_0x1686ac?''+Utils['escapeHtml'](_0x1686ac['username'])+(_0x1686ac['name']?'\x20<span\x20style=\x22color:\x20var(--color-text-secondary);\x20font-size:\x200.85em;\x22>('+Utils['escapeHtml'](_0x1686ac['name'])+')</span>':''):Utils['escapeHtml'](_0x21dd63);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'+_0x1ce9ea+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x1d5d07?'<button\x20type=\x22button\x22\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.removeMemberClick(\x27'+_0x21dd63+'\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 _0x52f1ef=document['getElementById']('add-member-row');if(_0x52f1ef)_0x52f1ef['style']['display']=_0x1d5d07?'flex':'none';}function updateMemberSelect(_0x31a162){const _0x2a76a0=document['getElementById']('add-member-select');if(!_0x2a76a0)return;const _0x3c1f2d=new Set(_0x31a162['members']||[]),_0x5d1fc2=state['users']['filter'](_0x59b786=>!_0x3c1f2d['has'](_0x59b786['id']));_0x2a76a0['innerHTML']='<option\x20value=\x22\x22>Add\x20a\x20member…</option>'+_0x5d1fc2['map'](_0x4801be=>'<option\x20value=\x22'+_0x4801be['id']+'\x22>'+Utils['escapeHtml'](_0x4801be['username'])+(_0x4801be['name']?'\x20('+Utils['escapeHtml'](_0x4801be['name'])+')':'')+'</option>')['join']('');}async function addMember(){const _0x5dd1bf=document['getElementById']('add-member-select'),_0x478bc3=_0x5dd1bf['value'];if(!_0x478bc3||!state['editingTeamId'])return;try{const {team:_0x58ac57}=await API['addTeamMember'](state['editingTeamId'],_0x478bc3);syncTeamInState(_0x58ac57),renderMembersList(_0x58ac57),updateMemberSelect(_0x58ac57),_0x5dd1bf['value']='',Utils['showToast']('Member\x20added','success');}catch(_0x4fc148){Utils['showToast'](_0x4fc148['message'],'error');}}window['removeMemberClick']=async function(_0x142e5d){if(!state['editingTeamId'])return;try{const {team:_0x2578ec}=await API['removeTeamMember'](state['editingTeamId'],_0x142e5d);syncTeamInState(_0x2578ec),renderMembersList(_0x2578ec),updateMemberSelect(_0x2578ec),Utils['showToast']('Member\x20removed','success');}catch(_0x1b4af6){Utils['showToast'](_0x1b4af6['message'],'error');}};async function loadTeamBindings(_0x4aef04){const _0x259c83=document['getElementById']('bindings-loading'),_0x3d05c6=document['getElementById']('bindings-empty'),_0x2bc8ae=document['getElementById']('bindings-list-container'),_0xaa5f5e=document['getElementById']('add-binding-btn');_0x259c83['hidden']=![],_0x3d05c6['hidden']=!![],_0x2bc8ae['style']['display']='none',_0xaa5f5e['hidden']=!![],document['getElementById']('add-binding-form')['hidden']=!![];try{const {bindings:_0x2b38c1}=await API['getBindings']({'subject_type':'team','subject_id':_0x4aef04});state['teamBindings']=_0x2b38c1||[],_0x259c83['hidden']=!![],state['teamBindings']['length']===0x0?_0x3d05c6['hidden']=![]:(_0x2bc8ae['style']['display']='',renderBindingsTable()),(Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage'))&&(_0xaa5f5e['hidden']=![]);}catch(_0x42ea5d){_0x259c83['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x42ea5d['message'],'error');}}function renderBindingsTable(){const _0x24dd7b=document['getElementById']('bindings-table-body');if(!_0x24dd7b)return;const _0x57b67f=Permissions['hasServerPermission'](state['currentUser'],'*')||Permissions['hasTeamPermission'](state['currentUser'],'teams:manage');_0x24dd7b['innerHTML']=state['teamBindings']['map'](_0x11229f=>{const _0x4b18f1=_0x11229f['resource_type']==='server'?'Server':_0x11229f['resource_id']==='*'?'All\x20'+_0x11229f['resource_type']+'s':Utils['escapeHtml'](_0x11229f['resource_name']||_0x11229f['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x4b18f1+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x11229f['role_name']||_0x11229f['role_id'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x57b67f?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteBindingClick(\x27'+_0x11229f['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 _0x441798=document['getElementById']('binding-resource-type');_0x441798['value']='environment',updateBindingFormForResourceType('environment');}function onBindingResourceTypeChange(){const _0x54e707=document['getElementById']('binding-resource-type')['value'];updateBindingFormForResourceType(_0x54e707);}function updateBindingFormForResourceType(_0x2266f4){const _0x4c782f=document['getElementById']('binding-resource-container'),_0x56cf30=document['getElementById']('binding-resource'),_0x315859=document['getElementById']('binding-role');if(_0x2266f4==='server')_0x4c782f['style']['display']='none';else{_0x4c782f['style']['display']='';if(_0x2266f4==='environment'){const _0x39a68f=new Set(state['teamBindings']['filter'](_0xa8c0fa=>_0xa8c0fa['resource_type']==='environment')['map'](_0x40fdfc=>_0x40fdfc['resource_id'])),_0x2fbf05=state['environments']['filter'](_0x640f5f=>!_0x39a68f['has'](_0x640f5f['name']));_0x56cf30['innerHTML']=_0x2fbf05['length']?_0x2fbf05['map'](_0x24e251=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x24e251['name'])+'\x22>'+Utils['escapeHtml'](_0x24e251['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x2266f4==='team'){const _0x2369f3=new Set(state['teamBindings']['filter'](_0x52bac4=>_0x52bac4['resource_type']==='team')['map'](_0x1c54a6=>_0x1c54a6['resource_id'])),_0x10235a=state['teams']['filter'](_0x31d6a2=>!_0x2369f3['has'](_0x31d6a2['id']));_0x56cf30['innerHTML']=_0x10235a['length']?_0x10235a['map'](_0x5a60e1=>'<option\x20value=\x22'+_0x5a60e1['id']+'\x22>'+Utils['escapeHtml'](_0x5a60e1['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x58a0b6=state['roles']['filter'](_0x5c92ce=>_0x5c92ce['resource_type']===_0x2266f4);_0x315859['innerHTML']=_0x58a0b6['length']?_0x58a0b6['filter'](_0x296a43=>{const _0x4ca592=_0x2266f4==='server'?undefined:_0x56cf30['value'];return!state['teamBindings']['some'](_0x3972eb=>_0x3972eb['resource_type']===_0x2266f4&&_0x3972eb['role_id']===_0x296a43['id']&&(_0x2266f4==='server'||_0x3972eb['resource_id']===_0x4ca592));})['map'](_0x1b16cb=>'<option\x20value=\x22'+_0x1b16cb['id']+'\x22>'+Utils['escapeHtml'](_0x1b16cb['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 _0x214f5f=document['getElementById']('binding-resource-type')['value'],_0x535017=document['getElementById']('binding-role')['value'];if(!_0x535017||!state['bindingsTeamId'])return;const _0x3b1b9e=_0x214f5f==='server'?undefined:document['getElementById']('binding-resource')['value'];if(_0x214f5f!=='server'&&!_0x3b1b9e)return;const _0x17d86a=document['getElementById']('save-binding-btn');_0x17d86a['disabled']=!![],_0x17d86a['textContent']='Adding…';try{const _0x439771={'subject_type':'team','subject_id':state['bindingsTeamId'],'role_id':_0x535017,'resource_type':_0x214f5f};if(_0x3b1b9e)_0x439771['resource_id']=_0x3b1b9e;await API['createBinding'](_0x439771),Utils['showToast']('Binding\x20added','success'),document['getElementById']('add-binding-form')['hidden']=!![],document['getElementById']('add-binding-btn')['hidden']=![],await loadTeamBindings(state['bindingsTeamId']);}catch(_0x5245d8){Utils['showToast'](_0x5245d8['message'],'error');}finally{_0x17d86a['disabled']=![],_0x17d86a['textContent']='Add\x20Binding';}}window['deleteBindingClick']=async function(_0x2323b8){try{await API['deleteBinding'](_0x2323b8),Utils['showToast']('Binding\x20removed','success'),await loadTeamBindings(state['bindingsTeamId']);}catch(_0x2f9237){Utils['showToast'](_0x2f9237['message'],'error');}};async function saveTeam(){const _0x9f8094=document['getElementById']('team-name')['value']['trim'](),_0x38901b=document['getElementById']('team-description')['value']['trim'](),_0x242e9c=document['getElementById']('team-form-error'),_0x46dd2b=document['getElementById']('save-team');if(!_0x9f8094){_0x242e9c['textContent']='Team\x20name\x20is\x20required',_0x242e9c['hidden']=![];return;}_0x242e9c['hidden']=!![];const _0x3b9ba0=_0x46dd2b['textContent'];_0x46dd2b['disabled']=!![],_0x46dd2b['textContent']=state['editingTeamId']?'Saving…':'Creating…';try{if(state['editingTeamId']){const {team:_0x2f3299}=await API['updateTeam'](state['editingTeamId'],{'name':_0x9f8094,'description':_0x38901b});syncTeamInState(_0x2f3299),document['getElementById']('team-modal-title')['textContent']=_0x2f3299['name'],Utils['showToast']('Team\x20updated','success');}else await API['createTeam']({'name':_0x9f8094,'description':_0x38901b}),Utils['showToast']('Team\x20created','success');_0x46dd2b['disabled']=![],_0x46dd2b['textContent']=_0x3b9ba0,hideTeamModal(),await loadTeams();}catch(_0x250b7a){_0x242e9c['textContent']=_0x250b7a['message'],_0x242e9c['hidden']=![],_0x46dd2b['disabled']=![],_0x46dd2b['textContent']=_0x3b9ba0;}}window['deleteTeam']=function(_0x2d44cc){const _0x3b4124=state['teams']['find'](_0x3c7fef=>_0x3c7fef['id']===_0x2d44cc);if(!_0x3b4124)return;state['deletingTeamId']=_0x2d44cc,document['getElementById']('delete-team-name')['textContent']=_0x3b4124['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 _0xb09cb5=document['getElementById']('confirm-delete-team');_0xb09cb5['disabled']=!![],_0xb09cb5['textContent']='Deleting…';try{await API['deleteTeam'](state['deletingTeamId']),Utils['showToast']('Team\x20deleted','success'),_0xb09cb5['disabled']=![],_0xb09cb5['textContent']='Delete\x20Team',hideDeleteModal(),await loadTeams();}catch(_0x24d698){Utils['showToast']('Failed\x20to\x20delete\x20team:\x20'+_0x24d698['message'],'error'),_0xb09cb5['disabled']=![],_0xb09cb5['textContent']='Delete\x20Team';}}function syncTeamInState(_0x1e4dde){const _0x82ef69=state['teams']['findIndex'](_0xbfb5c5=>_0xbfb5c5['id']===_0x1e4dde['id']);if(_0x82ef69>=0x0)state['teams'][_0x82ef69]=_0x1e4dde;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'](
|
|
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'](_0x4973d6=>{socket['readyState']===WebSocket['OPEN']&&socket['send'](JSON['stringify']({'type':'data','data':_0x4973d6}));});let commandSent=![],hasReceivedOutput=![];socket['addEventListener']('message',_0x2b4353=>{try{const _0x2f683e=JSON['parse'](_0x2b4353['data']);if(_0x2f683e['type']==='data'&&typeof _0x2f683e['data']==='string')term['write'](_0x2f683e['data']),!hasReceivedOutput&&_0x2f683e['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(_0x2f683e['type']==='status'&&_0x2f683e['status']){if(_0x2f683e['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'+_0x2f683e['status'],_0x2f683e['status']==='connected'?'success':'info');}else _0x2f683e['type']==='error'&&_0x2f683e['message']&&updateStatus(_0x2f683e['message'],'error');}}catch(_0x2dc81a){console['error']('Failed\x20to\x20parse\x20terminal\x20message',_0x2dc81a);}}),socket['addEventListener']('close',_0x207d61=>{const _0x37ec2a=_0x207d61['reason']||'Connection\x20closed';updateStatus(_0x37ec2a,_0x207d61['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',_0x5d0114=>{console['error']('Terminal\x20websocket\x20error',_0x5d0114),updateStatus('Connection\x20error','error');});function sendResize(){if(socket['readyState']!==WebSocket['OPEN'])return;const _0x25364f=term['cols'],_0x1b6a16=term['rows'];socket['send'](JSON['stringify']({'type':'resize','cols':_0x25364f,'rows':_0x1b6a16}));}function updateStatus(_0xeaa682,_0x4e5d13='info'){if(!statusEl)return;statusEl['textContent']=_0xeaa682,statusEl['dataset']['variant']=_0x4e5d13;}async function enrichContainerDetails(_0x56daed){try{const _0x4811bf=await API['getContainer'](_0x56daed);updateTerminalDetails(_0x4811bf);}catch{try{const _0x2248d4=await API['getContainers'](),_0x3197d3=(_0x2248d4['containers']||[])['find'](_0x210a34=>_0x210a34['containerId']===_0x56daed||_0x210a34['name']===_0x56daed||_0x210a34['fullContainerId']?.['startsWith'](_0x56daed));if(_0x3197d3){updateTerminalDetails(_0x3197d3);return;}subtitleEl['textContent']='Container\x20'+_0x56daed['substring'](0x0,0xc);}catch{subtitleEl['textContent']='Container\x20'+_0x56daed['substring'](0x0,0xc);}}}function updateTerminalDetails(_0x25491d){const _0x584c37=_0x25491d['containerId']||_0x25491d['name']||_0x25491d['fullContainerId']||containerId,_0x2d3ff4=_0x25491d['environment']?'Environment\x20'+_0x25491d['environment']:'Environment\x20unknown',_0x7d28ee=_0x25491d['defaultAgent']?'\x20·\x20Agent\x20'+_0x25491d['defaultAgent']:'',_0x8ca2ab=_0x25491d['createdAt']?'\x20·\x20Started\x20'+Utils['formatRelativeTime'](_0x25491d['createdAt']):'';titleEl['textContent']='Terminal\x20·\x20'+_0x584c37['substring'](0x0,0xc);const _0x2fb215=command?'\x20·\x20Command\x20'+command:'';subtitleEl['textContent']=''+_0x2d3ff4+_0x7d28ee+_0x8ca2ab+_0x2fb215;}
|
|
@@ -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
|
|
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 _0x304b51=localStorage['getItem'](THEME_STORAGE_KEY);if(_0x304b51&&VALID_THEMES['has'](_0x304b51))return _0x304b51;}catch(_0x1797d4){console['warn']('[Theme]\x20Failed\x20to\x20read\x20stored\x20theme\x20preference:',_0x1797d4);}return null;}export function getPreferredTheme(){const _0x25875a=readStoredTheme();if(_0x25875a)return _0x25875a;const _0x5b740a=window['matchMedia']&&window['matchMedia']('(prefers-color-scheme:\x20dark)')['matches'];return _0x5b740a?'dark':'light';}export function getCurrentTheme(){const _0x3e4146=document['documentElement']['dataset']['theme'];if(_0x3e4146&&VALID_THEMES['has'](_0x3e4146))return _0x3e4146;return getPreferredTheme();}export function applyTheme(_0x5d8d63,{persist:persist=!![],emitEvent:emitEvent=!![]}={}){const _0x551373=VALID_THEMES['has'](_0x5d8d63)?_0x5d8d63:'light';document['documentElement']['dataset']['theme']=_0x551373,document['documentElement']['style']['colorScheme']=_0x551373==='dark'?'dark':'light';if(persist)try{localStorage['setItem'](THEME_STORAGE_KEY,_0x551373);}catch(_0x62b319){console['warn']('[Theme]\x20Failed\x20to\x20persist\x20theme\x20preference:',_0x62b319);}return emitEvent&&window['dispatchEvent'](new CustomEvent(THEME_CHANGE_EVENT,{'detail':{'theme':_0x551373}})),_0x551373;}export function initTheme(_0x203d8e={}){const {emitEvent:emitEvent=![]}=_0x203d8e;return applyTheme(getPreferredTheme(),{'persist':![],'emitEvent':emitEvent});}export function toggleTheme(){const _0xdda9ae=getCurrentTheme()==='dark'?'light':'dark';return applyTheme(_0xdda9ae);}export function onThemeChange(_0x3bcbf4,{runImmediately:runImmediately=![]}={}){const _0x17a8f3=_0x4d5c02=>{_0x3bcbf4(_0x4d5c02['detail']['theme']);};return window['addEventListener'](THEME_CHANGE_EVENT,_0x17a8f3),runImmediately&&_0x3bcbf4(getCurrentTheme()),()=>window['removeEventListener'](THEME_CHANGE_EVENT,_0x17a8f3);}export function mountThemeToggle(_0x4fff19={}){const {targetSelectors:targetSelectors=DEFAULT_TARGET_SELECTORS}=_0x4fff19,_0x149267=targetSelectors['map'](_0x5df914=>document['querySelector'](_0x5df914))['find'](Boolean),_0x1ee7a0=document['createElement']('button');_0x1ee7a0['type']='button',_0x1ee7a0['className']='btn-ghost\x20theme-toggle-btn',_0x1ee7a0['id']='theme-toggle-btn',_0x1ee7a0['setAttribute']('aria-pressed','false'),_0x1ee7a0['style']['padding']='8px',_0x1ee7a0['style']['lineHeight']='0',_0x1ee7a0['style']['width']='36px',_0x1ee7a0['style']['height']='36px',_0x1ee7a0['style']['display']='flex',_0x1ee7a0['style']['alignItems']='center',_0x1ee7a0['style']['justifyContent']='center';const _0x5f5daf=document['createElement']('span');_0x5f5daf['className']='theme-icon',_0x5f5daf['style']['display']='flex',_0x1ee7a0['append'](_0x5f5daf);const _0x1103ff='<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>',_0x1ffb81='<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>',_0x4ced6e=_0xaa8ab6=>{const _0x1b7259=_0xaa8ab6==='dark';_0x5f5daf['innerHTML']=_0x1b7259?_0x1103ff:_0x1ffb81,_0x1ee7a0['title']=_0x1b7259?'Switch\x20to\x20light\x20mode':'Switch\x20to\x20dark\x20mode',_0x1ee7a0['dataset']['theme']=_0xaa8ab6,_0x1ee7a0['setAttribute']('aria-pressed',String(_0x1b7259));};return _0x1ee7a0['addEventListener']('click',()=>{const _0x4ad10c=getCurrentTheme()==='dark'?'light':'dark';applyTheme(_0x4ad10c);}),_0x149267?_0x149267['appendChild'](_0x1ee7a0):(_0x1ee7a0['classList']['add']('theme-toggle-floating'),document['body']['appendChild'](_0x1ee7a0)),_0x4ced6e(initTheme()),onThemeChange(_0x4ced6e),_0x1ee7a0;}export{THEME_STORAGE_KEY,THEME_CHANGE_EVENT};
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
</div>
|
|
127
127
|
</div>
|
|
128
128
|
|
|
129
|
-
<div id="users-loading" class="loading">Loading users
|
|
129
|
+
<div id="users-loading" class="loading">Loading users</div>
|
|
130
130
|
<div id="users-error" class="empty-state" hidden>
|
|
131
131
|
<h3>Failed to load users</h3>
|
|
132
132
|
<p id="users-error-message" class="text-muted"></p>
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
<button class="modal-close" id="close-bindings-modal">×</button>
|
|
247
247
|
</div>
|
|
248
248
|
<div class="modal-body">
|
|
249
|
-
<div id="user-bindings-loading" class="loading" hidden>Loading bindings
|
|
249
|
+
<div id="user-bindings-loading" class="loading" hidden>Loading bindings</div>
|
|
250
250
|
<div id="user-bindings-empty" hidden style="padding: 1.5rem 0; text-align: center; color: var(--color-text-secondary);">
|
|
251
251
|
No direct user bindings.
|
|
252
252
|
</div>
|
|
@@ -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 _0x453d64=await API['getCurrentUser']();state['currentUser']=_0x453d64;if(!Permissions['hasServerPermission'](_0x453d64,'*')&&!Permissions['hasServerPermission'](_0x453d64,'users:create')){Utils['showToast']('Access\x20denied:\x20Server\x20admin\x20privileges\x20required','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}}catch(_0x140c1a){window['location']['href']='login.html';}}async function checkEmailConfig(){try{const _0x1f576b=await API['getEmailConfig']();state['emailConfigured']=_0x1f576b['configured'];}catch(_0x5c1515){console['error']('Failed\x20to\x20check\x20email\x20config',_0x5c1515),state['emailConfigured']=![];}}async function loadRoles(){try{const {roles:_0x5dbdf5}=await API['getRoleDefinitions']();state['roles']=_0x5dbdf5||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x540b89=await API['getEnvironments']();state['environments']=_0x540b89['environments']||[];}catch{state['environments']=[];}}async function loadTeams(){try{const {teams:_0x583c4a}=await API['getTeams']();state['teams']=_0x583c4a||[];}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 _0x118008=document['getElementById']('users-loading'),_0x59247f=document['getElementById']('users-error'),_0x470399=document['getElementById']('users-content');try{_0x118008['hidden']=![],_0x59247f['hidden']=!![],_0x470399['hidden']=!![];const _0x3cc86a=await API['getUsers']();state['users']=_0x3cc86a['users']||[],renderUsers(),_0x118008['hidden']=!![],_0x470399['hidden']=![];}catch(_0x3bb41a){console['error']('Failed\x20to\x20load\x20users',_0x3bb41a),_0x118008['hidden']=!![],_0x59247f['hidden']=![],document['getElementById']('users-error-message')['textContent']=_0x3bb41a['message'];}}function renderUsers(){const _0x102ab5=document['getElementById']('users-table-body'),_0xc290a5=document['getElementById']('user-count');if(!_0x102ab5)return;_0xc290a5&&(_0xc290a5['textContent']=state['users']['length']+'\x20user'+(state['users']['length']===0x1?'':'s'));const _0xfff11d=[...state['users']]['sort']((_0x4db115,_0x5912fe)=>{const _0x1a8dc0=new Date(_0x4db115['created_at'])['getTime'](),_0x5090ca=new Date(_0x5912fe['created_at'])['getTime']();return _0x5090ca-_0x1a8dc0;});_0x102ab5['innerHTML']=_0xfff11d['map'](_0x479c1e=>'\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'](_0x479c1e['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'](_0x479c1e['name'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x479c1e['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'+(_0x479c1e['isServerAdmin']?'<span\x20class=\x22role-badge\x20role-admin\x22>Server\x20Admin</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x479c1e['hasUserBinding']?'<span\x20class=\x22role-badge\x20role-user-binding\x22>User\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x479c1e['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'](_0x479c1e['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'+_0x479c1e['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'+_0x479c1e['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'+_0x479c1e['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'+_0x479c1e['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(_0x4a7a3e){const _0xae4aaf=state['users']['find'](_0x2baf85=>_0x2baf85['id']===_0x4a7a3e);if(!_0xae4aaf)return;state['bindingsUserId']=_0x4a7a3e,state['bindingsDirty']=![];const _0x5958ef=document['getElementById']('bindings-modal'),_0x17245b=document['getElementById']('bindings-modal-title');_0x17245b['textContent']='Access\x20Bindings\x20—\x20'+_0xae4aaf['name'],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],_0x5958ef['hidden']=![],loadUserBindings(_0x4a7a3e);};function hasUnsavedBindingChanges(){const _0x486c6d=document['getElementById']('add-user-binding-form');return _0x486c6d&&!_0x486c6d['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 _0x18cffd=document['getElementById']('bindings-modal');_0x18cffd['hidden']=!![];const _0x4885f5=state['bindingsDirty'];state['bindingsUserId']=null,state['userBindings']=[],state['bindingsDirty']=![],_0x4885f5&&await loadUsers();}async function loadUserBindings(_0x1e01ca){const _0x3660b3=document['getElementById']('user-bindings-loading'),_0x4120d2=document['getElementById']('user-bindings-empty'),_0x2ce5bf=document['getElementById']('user-bindings-list-container'),_0x5913f5=document['getElementById']('add-user-binding-btn'),_0x54241a=document['getElementById']('user-team-bindings-note'),_0x3cc8c2=document['getElementById']('user-team-bindings-text');_0x3660b3['hidden']=![],_0x4120d2['hidden']=!![],_0x2ce5bf['style']['display']='none',_0x5913f5['hidden']=!![],_0x54241a['hidden']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![];try{const [_0x1ac35d,_0x2af5d2]=await Promise['all']([API['getBindings']({'subject_type':'user','subject_id':_0x1e01ca}),API['getTeams']()]);state['userBindings']=_0x1ac35d['bindings']||[];const _0x5d647f=(_0x2af5d2['teams']||[])['filter'](_0xf39a11=>(_0xf39a11['members']||[])['includes'](_0x1e01ca)),_0x40c6b1=[];if(_0x5d647f['length']>0x0){const _0x40c562=await Promise['all'](_0x5d647f['map'](_0x2e19d0=>API['getBindings']({'subject_type':'team','subject_id':_0x2e19d0['id']})));for(let _0x3d0770=0x0;_0x3d0770<_0x5d647f['length'];_0x3d0770++){const _0x434199=_0x40c562[_0x3d0770]['bindings']||[];_0x434199['length']>0x0&&_0x40c6b1['push'](_0x5d647f[_0x3d0770]);}}_0x3660b3['hidden']=!![];state['userBindings']['length']===0x0?_0x4120d2['hidden']=![]:(_0x2ce5bf['style']['display']='',renderUserBindingsTable());if(_0x40c6b1['length']>0x0){const _0x1c30c8=_0x40c6b1['map'](_0x519867=>_0x519867['name']),_0x23151f=_0x1c30c8['length']<=0x3?_0x1c30c8['join'](',\x20'):_0x1c30c8['slice'](0x0,0x3)['join'](',\x20')+(',\x20and\x20'+(_0x1c30c8['length']-0x3)+'\x20more');_0x3cc8c2['textContent']='This\x20user\x20also\x20has\x20access\x20via\x20team\x20memberships\x20('+_0x23151f+').';}else _0x3cc8c2['textContent']='This\x20user\x20has\x20no\x20access\x20via\x20team\x20memberships.';_0x54241a['hidden']=![],_0x5913f5['hidden']=![];}catch(_0x26382f){_0x3660b3['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x26382f['message'],'error');}}function renderUserBindingsTable(){const _0x41c762=document['getElementById']('user-bindings-table-body');if(!_0x41c762)return;_0x41c762['innerHTML']=state['userBindings']['map'](_0x40a945=>{const _0xa3d9a=_0x40a945['resource_type']==='server'?'Server':_0x40a945['resource_id']==='*'?'All\x20'+_0x40a945['resource_type']+'s':Utils['escapeHtml'](_0x40a945['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0xa3d9a+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x40a945['role_name']||_0x40a945['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'+_0x40a945['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 _0x53d068=document['getElementById']('user-binding-resource-type');_0x53d068['value']='environment',updateUserBindingFormForResourceType('environment');}function onUserBindingResourceTypeChange(){const _0x4e67b7=document['getElementById']('user-binding-resource-type')['value'];updateUserBindingFormForResourceType(_0x4e67b7);}function updateUserBindingFormForResourceType(_0x42077d){const _0x4b6d7a=document['getElementById']('user-binding-resource-container'),_0x506cf2=document['getElementById']('user-binding-resource'),_0x4c9992=document['getElementById']('user-binding-role');if(_0x42077d==='server')_0x4b6d7a['style']['display']='none';else{_0x4b6d7a['style']['display']='';if(_0x42077d==='environment'){const _0xe0a755=new Set(state['userBindings']['filter'](_0x1dcfa6=>_0x1dcfa6['resource_type']==='environment')['map'](_0x108954=>_0x108954['resource_id'])),_0x55e526=state['environments']['filter'](_0x556544=>!_0xe0a755['has'](_0x556544['name']));_0x506cf2['innerHTML']=_0x55e526['length']?_0x55e526['map'](_0x521004=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x521004['name'])+'\x22>'+Utils['escapeHtml'](_0x521004['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x42077d==='team'){const _0x57f0eb=new Set(state['userBindings']['filter'](_0x693be0=>_0x693be0['resource_type']==='team')['map'](_0x25899f=>_0x25899f['resource_id'])),_0x1e81c9=state['teams']['filter'](_0x4670d4=>!_0x57f0eb['has'](_0x4670d4['id']));_0x506cf2['innerHTML']=_0x1e81c9['length']?_0x1e81c9['map'](_0x4b08d5=>'<option\x20value=\x22'+_0x4b08d5['id']+'\x22>'+Utils['escapeHtml'](_0x4b08d5['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x5bc07b=state['roles']['filter'](_0x3f0f5d=>_0x3f0f5d['resource_type']===_0x42077d);_0x4c9992['innerHTML']=_0x5bc07b['length']?_0x5bc07b['filter'](_0x5c2f93=>{const _0x4cb005=_0x42077d==='server'?undefined:_0x506cf2['value'];return!state['userBindings']['some'](_0x434a6a=>_0x434a6a['resource_type']===_0x42077d&&_0x434a6a['role_id']===_0x5c2f93['id']&&(_0x42077d==='server'||_0x434a6a['resource_id']===_0x4cb005));})['map'](_0x5e0275=>'<option\x20value=\x22'+_0x5e0275['id']+'\x22>'+Utils['escapeHtml'](_0x5e0275['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 _0xf26dd3=document['getElementById']('user-binding-resource-type')['value'],_0x4eb735=document['getElementById']('user-binding-role')['value'];if(!_0x4eb735||!state['bindingsUserId'])return;const _0x365e42=_0xf26dd3==='server'?undefined:document['getElementById']('user-binding-resource')['value'];if(_0xf26dd3!=='server'&&!_0x365e42)return;const _0xf5d5ed=document['getElementById']('save-user-binding-btn');_0xf5d5ed['disabled']=!![],_0xf5d5ed['textContent']='Adding…';try{const _0x5afa89={'subject_type':'user','subject_id':state['bindingsUserId'],'role_id':_0x4eb735,'resource_type':_0xf26dd3};if(_0x365e42)_0x5afa89['resource_id']=_0x365e42;await API['createBinding'](_0x5afa89),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(_0x6c834b){Utils['showToast'](_0x6c834b['message'],'error');}finally{_0xf5d5ed['disabled']=![],_0xf5d5ed['textContent']='Add\x20Binding';}}window['deleteUserBindingClick']=async function(_0x3a96cc){try{await API['deleteBinding'](_0x3a96cc),Utils['showToast']('Binding\x20removed','success'),state['bindingsDirty']=!![],await loadUserBindings(state['bindingsUserId']);}catch(_0x4cf718){Utils['showToast'](_0x4cf718['message'],'error');}};function showCreateUserModal(){state['editingUserId']=null;const _0x286b83=document['getElementById']('user-modal'),_0x543883=document['getElementById']('modal-title'),_0x1ec8ff=document['getElementById']('user-password'),_0x260d2d=document['getElementById']('password-required'),_0x3c49c6=document['getElementById']('password-hint'),_0x27ff2e=document['getElementById']('skip-password-container'),_0x4fbb1c=document['getElementById']('skip-password');_0x543883['textContent']='Create\x20User',document['getElementById']('user-form')['reset'](),_0x1ec8ff['required']=!![];if(_0x260d2d)_0x260d2d['textContent']='*';_0x27ff2e&&(_0x27ff2e['style']['display']='block',_0x4fbb1c['checked']=![]),_0x3c49c6&&(_0x3c49c6['textContent']='Minimum\x208\x20characters'),_0x286b83['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);}window['editUser']=function(_0x4f1b15){const _0x579c0f=state['users']['find'](_0x4b288d=>_0x4b288d['id']===_0x4f1b15);if(!_0x579c0f)return;state['editingUserId']=_0x4f1b15;const _0x10f2a9=document['getElementById']('user-modal'),_0x4b667d=document['getElementById']('modal-title'),_0x176e65=document['getElementById']('user-password'),_0xea6c4c=document['getElementById']('password-required'),_0x2787af=document['getElementById']('password-hint'),_0x773359=document['getElementById']('skip-password-container');_0x4b667d['textContent']='Edit\x20User',document['getElementById']('user-username')['value']=_0x579c0f['username'],document['getElementById']('user-name')['value']=_0x579c0f['name'],document['getElementById']('user-email')['value']=_0x579c0f['email'],_0x176e65['value']='',_0x176e65['required']=![];if(_0xea6c4c)_0xea6c4c['textContent']='';_0x773359&&(_0x773359['style']['display']='none'),_0x2787af&&(_0x2787af['textContent']='Leave\x20blank\x20to\x20keep\x20current\x20password'),_0x10f2a9['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);};function hideUserModal(){const _0x1c053a=document['getElementById']('user-modal'),_0x18737e=document['getElementById']('form-error'),_0x5284f8=document['getElementById']('save-user');_0x1c053a['hidden']=!![],_0x18737e['hidden']=!![],state['editingUserId']=null,_0x5284f8&&(_0x5284f8['disabled']=![],_0x5284f8['textContent']='Save\x20User');}async function saveUser(){const _0x4161f4=document['getElementById']('user-form'),_0x16ffea=document['getElementById']('skip-password')?.['checked']||![];if(!_0x16ffea&&!_0x4161f4['checkValidity']()){_0x4161f4['reportValidity']();return;}const _0x4549fa=document['getElementById']('form-error'),_0x5c438b=document['getElementById']('save-user'),_0x400729=document['getElementById']('user-username')['value']['trim'](),_0x12a866=document['getElementById']('user-name')['value']['trim'](),_0x5f0ba5=document['getElementById']('user-email')['value']['trim'](),_0x2e492a=document['getElementById']('user-password')['value'];if(!_0x400729||!_0x12a866||!_0x5f0ba5){_0x4549fa['textContent']='Please\x20fill\x20in\x20all\x20required\x20fields',_0x4549fa['hidden']=![],_0x4549fa['scrollIntoView']({'behavior':'smooth','block':'nearest'});return;}_0x4549fa['hidden']=!![];const _0x577816=_0x5c438b['textContent'];_0x5c438b['disabled']=!![],_0x5c438b['textContent']=state['editingUserId']?'Updating...':'Creating...';try{if(state['editingUserId']){const _0x1925e9={'username':_0x400729,'name':_0x12a866,'email':_0x5f0ba5};_0x2e492a&&(_0x1925e9['password']=_0x2e492a),await API['updateUser'](state['editingUserId'],_0x1925e9),Utils['showToast']('User\x20updated\x20successfully','success'),await loadUsers(),hideUserModal();}else{const _0x456873={'username':_0x400729,'name':_0x12a866,'email':_0x5f0ba5};if(!_0x16ffea){if(!_0x2e492a)throw new Error('Password\x20is\x20required\x20for\x20new\x20users');_0x456873['password']=_0x2e492a;}const _0x4c2784=await API['createUser'](_0x456873),_0x4e3bd4=_0x4c2784['user'];if(_0x16ffea||!_0x2e492a){const _0x2deacd=await API['createPasswordToken'](_0x4e3bd4['id'],'setup',![]);state['setupLinkData']={'username':_0x4e3bd4['username'],'email':_0x4e3bd4['email'],'url':_0x2deacd['token']['setupUrl'],'userId':_0x4e3bd4['id'],'type':'setup','emailSent':![]},await loadUsers(),hideUserModal(),showSetupLinkModal();}else Utils['showToast']('User\x20created\x20successfully','success'),await loadUsers(),hideUserModal();}}catch(_0x25d033){console['error']('Failed\x20to\x20save\x20user',_0x25d033),_0x4549fa['textContent']=_0x25d033['message'],_0x4549fa['hidden']=![],_0x4549fa['scrollIntoView']({'behavior':'smooth','block':'nearest'}),_0x5c438b['disabled']=![],_0x5c438b['textContent']=_0x577816;}}window['deleteUser']=function(_0x3dbc23){const _0x543034=state['users']['find'](_0x156d02=>_0x156d02['id']===_0x3dbc23);if(!_0x543034)return;state['deletingUserId']=_0x3dbc23;const _0x2ca9d4=document['getElementById']('delete-modal'),_0x541386=document['getElementById']('delete-user-name');_0x541386['textContent']=_0x543034['name']+'\x20('+_0x543034['username']+')',_0x2ca9d4['hidden']=![];};function hideDeleteModal(){const _0x503bd2=document['getElementById']('delete-modal');_0x503bd2['hidden']=!![],state['deletingUserId']=null;const _0x2177f1=document['getElementById']('confirm-delete');_0x2177f1&&(_0x2177f1['disabled']=![],_0x2177f1['textContent']='Delete\x20User');}async function confirmDeleteUser(){if(!state['deletingUserId'])return;const _0x559a54=document['getElementById']('confirm-delete'),_0x463413=_0x559a54['textContent'];_0x559a54['disabled']=!![],_0x559a54['textContent']='Deleting...';try{await API['deleteUser'](state['deletingUserId']),Utils['showToast']('User\x20deleted\x20successfully','success'),await loadUsers(),hideDeleteModal();}catch(_0x10c896){console['error']('Failed\x20to\x20delete\x20user',_0x10c896),Utils['showToast']('Failed\x20to\x20delete\x20user:\x20'+_0x10c896['message'],'error'),_0x559a54['disabled']=![],_0x559a54['textContent']=_0x463413;}}function handleSkipPasswordChange(_0x2701ae){const _0x336564=document['getElementById']('user-password'),_0x5c8fd1=_0x2701ae['target']['checked'];_0x5c8fd1?(_0x336564['required']=![],_0x336564['disabled']=!![],_0x336564['value']=''):(_0x336564['required']=!![],_0x336564['disabled']=![]);}function showSetupLinkModal(){if(!state['setupLinkData'])return;const _0x39a901=document['getElementById']('setup-link-modal'),_0x37fb96=document['getElementById']('setup-link-username'),_0x117cb0=document['getElementById']('setup-link-url'),_0x1dfa2d=document['getElementById']('email-setup-link'),_0x26b7bd=document['getElementById']('email-button-text');_0x37fb96['textContent']=state['setupLinkData']['username'],_0x117cb0['textContent']=state['setupLinkData']['url'],_0x1dfa2d&&_0x26b7bd&&(_0x1dfa2d['disabled']=![],_0x26b7bd['textContent']='Email\x20Link',state['emailConfigured']&&!state['setupLinkData']['emailSent']?_0x1dfa2d['style']['display']='inline-block':_0x1dfa2d['style']['display']='none'),_0x39a901['hidden']=![];}function hideSetupLinkModal(){const _0x24eedd=document['getElementById']('setup-link-modal');_0x24eedd['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(_0x34fa01){console['error']('Failed\x20to\x20copy\x20link',_0x34fa01),Utils['showToast']('Failed\x20to\x20copy\x20link','error');}}async function emailSetupLink(){if(!state['setupLinkData'])return;const _0x30f63b=document['getElementById']('email-setup-link'),_0x3400c7=document['getElementById']('email-button-text');if(!_0x30f63b||!_0x3400c7)return;const _0x474f50=_0x3400c7['textContent'];_0x30f63b['disabled']=!![],_0x3400c7['textContent']='Sending...';try{const _0x468130=await API['createPasswordToken'](state['setupLinkData']['userId'],state['setupLinkData']['type'],!![]);if(_0x468130['emailSent'])Utils['showToast']('Email\x20sent\x20to\x20'+state['setupLinkData']['email'],'success'),state['setupLinkData']['emailSent']=!![],_0x30f63b['style']['display']='none';else{const _0x52d48d=_0x468130['emailError']||'Failed\x20to\x20send\x20email';Utils['showToast'](_0x52d48d,'error'),_0x30f63b['disabled']=![],_0x3400c7['textContent']=_0x474f50;}}catch(_0x6f0724){console['error']('Failed\x20to\x20email\x20setup\x20link',_0x6f0724),Utils['showToast']('Failed\x20to\x20send\x20email:\x20'+_0x6f0724['message'],'error'),_0x30f63b['disabled']=![],_0x3400c7['textContent']=_0x474f50;}}window['resetPassword']=async function(_0x5c4469){const _0x27d839=state['users']['find'](_0x334809=>_0x334809['id']===_0x5c4469);if(!_0x27d839)return;const _0x3e4277=await ConfirmDialog['show']({'title':'Reset\x20Password','message':'Generate\x20a\x20password\x20reset\x20link\x20for\x20'+_0x27d839['name']+'\x20('+_0x27d839['username']+')?\x20This\x20will\x20create\x20a\x20link\x20that\x20they\x20can\x20use\x20to\x20set\x20a\x20new\x20password.','confirmText':'Generate\x20Link'});if(!_0x3e4277)return;try{const _0x2bc7fb=await API['createPasswordToken'](_0x5c4469,'reset',![]);state['setupLinkData']={'username':_0x27d839['username'],'email':_0x27d839['email'],'url':_0x2bc7fb['token']['setupUrl'],'userId':_0x27d839['id'],'type':'reset','emailSent':![]},showSetupLinkModal();}catch(_0x1c2c12){console['error']('Failed\x20to\x20create\x20password\x20reset\x20link',_0x1c2c12),Utils['showToast']('Failed\x20to\x20create\x20password\x20reset\x20link:\x20'+_0x1c2c12['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 _0x533838=await API['getCurrentUser']();state['currentUser']=_0x533838;if(!Permissions['hasServerPermission'](_0x533838,'*')&&!Permissions['hasServerPermission'](_0x533838,'users:create')){Utils['showToast']('Access\x20denied:\x20Server\x20admin\x20privileges\x20required','error'),setTimeout(()=>{window['location']['href']='index.html';},0x7d0);return;}}catch(_0x847fe7){window['location']['href']='login.html';}}async function checkEmailConfig(){try{const _0x5c340b=await API['getEmailConfig']();state['emailConfigured']=_0x5c340b['configured'];}catch(_0x42699b){console['error']('Failed\x20to\x20check\x20email\x20config',_0x42699b),state['emailConfigured']=![];}}async function loadRoles(){try{const {roles:_0x47bbe5}=await API['getRoleDefinitions']();state['roles']=_0x47bbe5||[];}catch{state['roles']=[];}}async function loadEnvironments(){try{const _0x3e1006=await API['getEnvironments']();state['environments']=_0x3e1006['environments']||[];}catch{state['environments']=[];}}async function loadTeams(){try{const {teams:_0x2a1515}=await API['getTeams']();state['teams']=_0x2a1515||[];}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 _0x53469c=document['getElementById']('users-loading'),_0xbc7b6f=document['getElementById']('users-error'),_0x58f3e5=document['getElementById']('users-content');try{_0x53469c['hidden']=![],_0xbc7b6f['hidden']=!![],_0x58f3e5['hidden']=!![];const _0xc38ae=await API['getUsers']();state['users']=_0xc38ae['users']||[],renderUsers(),_0x53469c['hidden']=!![],_0x58f3e5['hidden']=![];}catch(_0x2d7f87){console['error']('Failed\x20to\x20load\x20users',_0x2d7f87),_0x53469c['hidden']=!![],_0xbc7b6f['hidden']=![],document['getElementById']('users-error-message')['textContent']=_0x2d7f87['message'];}}function renderUsers(){const _0x5eaf92=document['getElementById']('users-table-body'),_0x30d299=document['getElementById']('user-count');if(!_0x5eaf92)return;_0x30d299&&(_0x30d299['textContent']=state['users']['length']+'\x20user'+(state['users']['length']===0x1?'':'s'));const _0x376f6a=[...state['users']]['sort']((_0xadd05,_0x277193)=>{const _0x364d3f=new Date(_0xadd05['created_at'])['getTime'](),_0xf90ecf=new Date(_0x277193['created_at'])['getTime']();return _0xf90ecf-_0x364d3f;});_0x5eaf92['innerHTML']=_0x376f6a['map'](_0x1056bb=>'\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'](_0x1056bb['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'](_0x1056bb['name'])+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x1056bb['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'+(_0x1056bb['isServerAdmin']?'<span\x20class=\x22role-badge\x20role-admin\x22>Server\x20Admin</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x1056bb['hasUserBinding']?'<span\x20class=\x22role-badge\x20role-user-binding\x22>User\x20Binding</span>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x1056bb['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'](_0x1056bb['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'+_0x1056bb['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'+_0x1056bb['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'+_0x1056bb['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'+_0x1056bb['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(_0x233a9c){const _0x5e3192=state['users']['find'](_0x3d5c4b=>_0x3d5c4b['id']===_0x233a9c);if(!_0x5e3192)return;state['bindingsUserId']=_0x233a9c,state['bindingsDirty']=![];const _0x539d50=document['getElementById']('bindings-modal'),_0x537d5c=document['getElementById']('bindings-modal-title');_0x537d5c['textContent']='Access\x20Bindings\x20—\x20'+_0x5e3192['name'],document['getElementById']('add-user-binding-form')['hidden']=!![],document['getElementById']('add-user-binding-btn')['hidden']=![],_0x539d50['hidden']=![],loadUserBindings(_0x233a9c);};function hasUnsavedBindingChanges(){const _0x42250d=document['getElementById']('add-user-binding-form');return _0x42250d&&!_0x42250d['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 _0x3cc119=document['getElementById']('bindings-modal');_0x3cc119['hidden']=!![];const _0xd1d762=state['bindingsDirty'];state['bindingsUserId']=null,state['userBindings']=[],state['bindingsDirty']=![],_0xd1d762&&await loadUsers();}async function loadUserBindings(_0x53a42b){const _0x1f0d5c=document['getElementById']('user-bindings-loading'),_0x4bab69=document['getElementById']('user-bindings-empty'),_0x2c1c0d=document['getElementById']('user-bindings-list-container'),_0x20f92b=document['getElementById']('add-user-binding-btn'),_0x3799aa=document['getElementById']('user-team-bindings-note'),_0x680370=document['getElementById']('user-team-bindings-text');_0x1f0d5c['hidden']=![],_0x4bab69['hidden']=!![],_0x2c1c0d['style']['display']='none',_0x20f92b['hidden']=!![],_0x3799aa['hidden']=!![],document['getElementById']('add-user-binding-form')['hidden']=!![];try{const [_0xde08ff,_0x5ddea7]=await Promise['all']([API['getBindings']({'subject_type':'user','subject_id':_0x53a42b}),API['getTeams']()]);state['userBindings']=_0xde08ff['bindings']||[];const _0x3233b7=(_0x5ddea7['teams']||[])['filter'](_0x548e13=>(_0x548e13['members']||[])['includes'](_0x53a42b)),_0x1bdad7=[];if(_0x3233b7['length']>0x0){const _0x419241=await Promise['all'](_0x3233b7['map'](_0x1eb6ac=>API['getBindings']({'subject_type':'team','subject_id':_0x1eb6ac['id']})));for(let _0x35508d=0x0;_0x35508d<_0x3233b7['length'];_0x35508d++){const _0x204cf4=_0x419241[_0x35508d]['bindings']||[];_0x204cf4['length']>0x0&&_0x1bdad7['push'](_0x3233b7[_0x35508d]);}}_0x1f0d5c['hidden']=!![];state['userBindings']['length']===0x0?_0x4bab69['hidden']=![]:(_0x2c1c0d['style']['display']='',renderUserBindingsTable());if(_0x1bdad7['length']>0x0){const _0x4d80e6=_0x1bdad7['map'](_0x30dcf0=>_0x30dcf0['name']),_0x8e872b=_0x4d80e6['length']<=0x3?_0x4d80e6['join'](',\x20'):_0x4d80e6['slice'](0x0,0x3)['join'](',\x20')+(',\x20and\x20'+(_0x4d80e6['length']-0x3)+'\x20more');_0x680370['textContent']='This\x20user\x20also\x20has\x20access\x20via\x20team\x20memberships\x20('+_0x8e872b+').';}else _0x680370['textContent']='This\x20user\x20has\x20no\x20access\x20via\x20team\x20memberships.';_0x3799aa['hidden']=![],_0x20f92b['hidden']=![];}catch(_0x32655b){_0x1f0d5c['hidden']=!![],Utils['showToast']('Failed\x20to\x20load\x20bindings:\x20'+_0x32655b['message'],'error');}}function renderUserBindingsTable(){const _0xf9f21b=document['getElementById']('user-bindings-table-body');if(!_0xf9f21b)return;_0xf9f21b['innerHTML']=state['userBindings']['map'](_0x428c1e=>{const _0x5273c8=_0x428c1e['resource_type']==='server'?'Server':_0x428c1e['resource_id']==='*'?'All\x20'+_0x428c1e['resource_type']+'s':Utils['escapeHtml'](_0x428c1e['resource_id']||'');return'\x0a\x20\x20\x20\x20<tr>\x0a\x20\x20\x20\x20\x20\x20<td>'+_0x5273c8+'</td>\x0a\x20\x20\x20\x20\x20\x20<td>'+Utils['escapeHtml'](_0x428c1e['role_name']||_0x428c1e['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'+_0x428c1e['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 _0x18a702=document['getElementById']('user-binding-resource-type');_0x18a702['value']='environment',updateUserBindingFormForResourceType('environment');}function onUserBindingResourceTypeChange(){const _0x5d0829=document['getElementById']('user-binding-resource-type')['value'];updateUserBindingFormForResourceType(_0x5d0829);}function updateUserBindingFormForResourceType(_0x1467c7){const _0x16e940=document['getElementById']('user-binding-resource-container'),_0x221edb=document['getElementById']('user-binding-resource'),_0x485ac5=document['getElementById']('user-binding-role');if(_0x1467c7==='server')_0x16e940['style']['display']='none';else{_0x16e940['style']['display']='';if(_0x1467c7==='environment'){const _0x3d73e9=new Set(state['userBindings']['filter'](_0x1dcbc6=>_0x1dcbc6['resource_type']==='environment')['map'](_0x30dd06=>_0x30dd06['resource_id'])),_0x958faf=state['environments']['filter'](_0x4aad86=>!_0x3d73e9['has'](_0x4aad86['name']));_0x221edb['innerHTML']=_0x958faf['length']?_0x958faf['map'](_0x1d8de4=>'<option\x20value=\x22'+Utils['escapeHtml'](_0x1d8de4['name'])+'\x22>'+Utils['escapeHtml'](_0x1d8de4['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20environments\x20already\x20bound</option>';}else{if(_0x1467c7==='team'){const _0x28854b=new Set(state['userBindings']['filter'](_0x2ccbc3=>_0x2ccbc3['resource_type']==='team')['map'](_0x9fd471=>_0x9fd471['resource_id'])),_0x570ad1=state['teams']['filter'](_0x54200c=>!_0x28854b['has'](_0x54200c['id']));_0x221edb['innerHTML']=_0x570ad1['length']?_0x570ad1['map'](_0x5c9bd2=>'<option\x20value=\x22'+_0x5c9bd2['id']+'\x22>'+Utils['escapeHtml'](_0x5c9bd2['name'])+'</option>')['join'](''):'<option\x20value=\x22\x22>All\x20teams\x20already\x20bound</option>';}}}const _0x4b4d3c=state['roles']['filter'](_0x284112=>_0x284112['resource_type']===_0x1467c7);_0x485ac5['innerHTML']=_0x4b4d3c['length']?_0x4b4d3c['filter'](_0x35d8b3=>{const _0x4089bb=_0x1467c7==='server'?undefined:_0x221edb['value'];return!state['userBindings']['some'](_0x517d38=>_0x517d38['resource_type']===_0x1467c7&&_0x517d38['role_id']===_0x35d8b3['id']&&(_0x1467c7==='server'||_0x517d38['resource_id']===_0x4089bb));})['map'](_0xef7d9b=>'<option\x20value=\x22'+_0xef7d9b['id']+'\x22>'+Utils['escapeHtml'](_0xef7d9b['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 _0x56da2b=document['getElementById']('user-binding-resource-type')['value'],_0x4b76ef=document['getElementById']('user-binding-role')['value'];if(!_0x4b76ef||!state['bindingsUserId'])return;const _0x30edd5=_0x56da2b==='server'?undefined:document['getElementById']('user-binding-resource')['value'];if(_0x56da2b!=='server'&&!_0x30edd5)return;const _0x16ae16=document['getElementById']('save-user-binding-btn');_0x16ae16['disabled']=!![],_0x16ae16['textContent']='Adding…';try{const _0x452272={'subject_type':'user','subject_id':state['bindingsUserId'],'role_id':_0x4b76ef,'resource_type':_0x56da2b};if(_0x30edd5)_0x452272['resource_id']=_0x30edd5;await API['createBinding'](_0x452272),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(_0x5710e1){Utils['showToast'](_0x5710e1['message'],'error');}finally{_0x16ae16['disabled']=![],_0x16ae16['textContent']='Add\x20Binding';}}window['deleteUserBindingClick']=async function(_0x4a2faf){try{await API['deleteBinding'](_0x4a2faf),Utils['showToast']('Binding\x20removed','success'),state['bindingsDirty']=!![],await loadUserBindings(state['bindingsUserId']);}catch(_0x451712){Utils['showToast'](_0x451712['message'],'error');}};function showCreateUserModal(){state['editingUserId']=null;const _0x4251bf=document['getElementById']('user-modal'),_0x504e88=document['getElementById']('modal-title'),_0x388888=document['getElementById']('user-password'),_0x3dda4d=document['getElementById']('password-required'),_0x1680e0=document['getElementById']('password-hint'),_0x200143=document['getElementById']('skip-password-container'),_0x122f1d=document['getElementById']('skip-password');_0x504e88['textContent']='Create\x20User',document['getElementById']('user-form')['reset'](),_0x388888['required']=!![];if(_0x3dda4d)_0x3dda4d['textContent']='*';_0x200143&&(_0x200143['style']['display']='block',_0x122f1d['checked']=![]),_0x1680e0&&(_0x1680e0['textContent']='Minimum\x208\x20characters'),_0x4251bf['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);}window['editUser']=function(_0x4bc6d7){const _0x26cbe1=state['users']['find'](_0x137082=>_0x137082['id']===_0x4bc6d7);if(!_0x26cbe1)return;state['editingUserId']=_0x4bc6d7;const _0x269ad8=document['getElementById']('user-modal'),_0x47633d=document['getElementById']('modal-title'),_0xc07588=document['getElementById']('user-password'),_0x8fb42c=document['getElementById']('password-required'),_0x50e8fb=document['getElementById']('password-hint'),_0x39bfe0=document['getElementById']('skip-password-container');_0x47633d['textContent']='Edit\x20User',document['getElementById']('user-username')['value']=_0x26cbe1['username'],document['getElementById']('user-name')['value']=_0x26cbe1['name'],document['getElementById']('user-email')['value']=_0x26cbe1['email'],_0xc07588['value']='',_0xc07588['required']=![];if(_0x8fb42c)_0x8fb42c['textContent']='';_0x39bfe0&&(_0x39bfe0['style']['display']='none'),_0x50e8fb&&(_0x50e8fb['textContent']='Leave\x20blank\x20to\x20keep\x20current\x20password'),_0x269ad8['hidden']=![],setTimeout(()=>{document['getElementById']('user-username')['focus']();},0x64);};function hideUserModal(){const _0x120220=document['getElementById']('user-modal'),_0x5237b8=document['getElementById']('form-error'),_0x400f33=document['getElementById']('save-user');_0x120220['hidden']=!![],_0x5237b8['hidden']=!![],state['editingUserId']=null,_0x400f33&&(_0x400f33['disabled']=![],_0x400f33['textContent']='Save\x20User');}async function saveUser(){const _0x2ca16c=document['getElementById']('user-form'),_0x1a9edb=document['getElementById']('skip-password')?.['checked']||![];if(!_0x1a9edb&&!_0x2ca16c['checkValidity']()){_0x2ca16c['reportValidity']();return;}const _0x2368b5=document['getElementById']('form-error'),_0x246dd2=document['getElementById']('save-user'),_0x4d6166=document['getElementById']('user-username')['value']['trim'](),_0x16f66b=document['getElementById']('user-name')['value']['trim'](),_0xd6cd53=document['getElementById']('user-email')['value']['trim'](),_0x327300=document['getElementById']('user-password')['value'];if(!_0x4d6166||!_0x16f66b||!_0xd6cd53){_0x2368b5['textContent']='Please\x20fill\x20in\x20all\x20required\x20fields',_0x2368b5['hidden']=![],_0x2368b5['scrollIntoView']({'behavior':'smooth','block':'nearest'});return;}_0x2368b5['hidden']=!![];const _0x5d9f0b=_0x246dd2['textContent'];_0x246dd2['disabled']=!![],_0x246dd2['textContent']=state['editingUserId']?'Updating...':'Creating...';try{if(state['editingUserId']){const _0x30a69c={'username':_0x4d6166,'name':_0x16f66b,'email':_0xd6cd53};_0x327300&&(_0x30a69c['password']=_0x327300),await API['updateUser'](state['editingUserId'],_0x30a69c),Utils['showToast']('User\x20updated\x20successfully','success'),await loadUsers(),hideUserModal();}else{const _0x1dc43f={'username':_0x4d6166,'name':_0x16f66b,'email':_0xd6cd53};if(!_0x1a9edb){if(!_0x327300)throw new Error('Password\x20is\x20required\x20for\x20new\x20users');_0x1dc43f['password']=_0x327300;}const _0x1f994b=await API['createUser'](_0x1dc43f),_0x499536=_0x1f994b['user'];if(_0x1a9edb||!_0x327300){const _0x21a279=await API['createPasswordToken'](_0x499536['id'],'setup',![]);state['setupLinkData']={'username':_0x499536['username'],'email':_0x499536['email'],'url':_0x21a279['token']['setupUrl'],'userId':_0x499536['id'],'type':'setup','emailSent':![]},await loadUsers(),hideUserModal(),showSetupLinkModal();}else Utils['showToast']('User\x20created\x20successfully','success'),await loadUsers(),hideUserModal();}}catch(_0x304396){console['error']('Failed\x20to\x20save\x20user',_0x304396),_0x2368b5['textContent']=_0x304396['message'],_0x2368b5['hidden']=![],_0x2368b5['scrollIntoView']({'behavior':'smooth','block':'nearest'}),_0x246dd2['disabled']=![],_0x246dd2['textContent']=_0x5d9f0b;}}window['deleteUser']=function(_0xd07e14){const _0x18888f=state['users']['find'](_0x238f35=>_0x238f35['id']===_0xd07e14);if(!_0x18888f)return;state['deletingUserId']=_0xd07e14;const _0x7e4bd=document['getElementById']('delete-modal'),_0xaef7e0=document['getElementById']('delete-user-name');_0xaef7e0['textContent']=_0x18888f['name']+'\x20('+_0x18888f['username']+')',_0x7e4bd['hidden']=![];};function hideDeleteModal(){const _0x3fe6de=document['getElementById']('delete-modal');_0x3fe6de['hidden']=!![],state['deletingUserId']=null;const _0xd02645=document['getElementById']('confirm-delete');_0xd02645&&(_0xd02645['disabled']=![],_0xd02645['textContent']='Delete\x20User');}async function confirmDeleteUser(){if(!state['deletingUserId'])return;const _0x56a546=document['getElementById']('confirm-delete'),_0xd422ab=_0x56a546['textContent'];_0x56a546['disabled']=!![],_0x56a546['textContent']='Deleting...';try{await API['deleteUser'](state['deletingUserId']),Utils['showToast']('User\x20deleted\x20successfully','success'),await loadUsers(),hideDeleteModal();}catch(_0x43f2cb){console['error']('Failed\x20to\x20delete\x20user',_0x43f2cb),Utils['showToast']('Failed\x20to\x20delete\x20user:\x20'+_0x43f2cb['message'],'error'),_0x56a546['disabled']=![],_0x56a546['textContent']=_0xd422ab;}}function handleSkipPasswordChange(_0x531cf1){const _0x1a31a3=document['getElementById']('user-password'),_0x3c3c0d=_0x531cf1['target']['checked'];_0x3c3c0d?(_0x1a31a3['required']=![],_0x1a31a3['disabled']=!![],_0x1a31a3['value']=''):(_0x1a31a3['required']=!![],_0x1a31a3['disabled']=![]);}function showSetupLinkModal(){if(!state['setupLinkData'])return;const _0x28a791=document['getElementById']('setup-link-modal'),_0x1212dc=document['getElementById']('setup-link-username'),_0x49a635=document['getElementById']('setup-link-url'),_0x2efe3e=document['getElementById']('email-setup-link'),_0x11a202=document['getElementById']('email-button-text');_0x1212dc['textContent']=state['setupLinkData']['username'],_0x49a635['textContent']=state['setupLinkData']['url'],_0x2efe3e&&_0x11a202&&(_0x2efe3e['disabled']=![],_0x11a202['textContent']='Email\x20Link',state['emailConfigured']&&!state['setupLinkData']['emailSent']?_0x2efe3e['style']['display']='inline-block':_0x2efe3e['style']['display']='none'),_0x28a791['hidden']=![];}function hideSetupLinkModal(){const _0x1d4cd7=document['getElementById']('setup-link-modal');_0x1d4cd7['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(_0x16bc39){console['error']('Failed\x20to\x20copy\x20link',_0x16bc39),Utils['showToast']('Failed\x20to\x20copy\x20link','error');}}async function emailSetupLink(){if(!state['setupLinkData'])return;const _0x5ade3b=document['getElementById']('email-setup-link'),_0x1c7f04=document['getElementById']('email-button-text');if(!_0x5ade3b||!_0x1c7f04)return;const _0x296079=_0x1c7f04['textContent'];_0x5ade3b['disabled']=!![],_0x1c7f04['textContent']='Sending...';try{const _0x4a87e6=await API['createPasswordToken'](state['setupLinkData']['userId'],state['setupLinkData']['type'],!![]);if(_0x4a87e6['emailSent'])Utils['showToast']('Email\x20sent\x20to\x20'+state['setupLinkData']['email'],'success'),state['setupLinkData']['emailSent']=!![],_0x5ade3b['style']['display']='none';else{const _0x184ef2=_0x4a87e6['emailError']||'Failed\x20to\x20send\x20email';Utils['showToast'](_0x184ef2,'error'),_0x5ade3b['disabled']=![],_0x1c7f04['textContent']=_0x296079;}}catch(_0x94896e){console['error']('Failed\x20to\x20email\x20setup\x20link',_0x94896e),Utils['showToast']('Failed\x20to\x20send\x20email:\x20'+_0x94896e['message'],'error'),_0x5ade3b['disabled']=![],_0x1c7f04['textContent']=_0x296079;}}window['resetPassword']=async function(_0x54e81c){const _0x5ed01c=state['users']['find'](_0x5782a1=>_0x5782a1['id']===_0x54e81c);if(!_0x5ed01c)return;const _0x3e4792=await ConfirmDialog['show']({'title':'Reset\x20Password','message':'Generate\x20a\x20password\x20reset\x20link\x20for\x20'+_0x5ed01c['name']+'\x20('+_0x5ed01c['username']+')?\x20This\x20will\x20create\x20a\x20link\x20that\x20they\x20can\x20use\x20to\x20set\x20a\x20new\x20password.','confirmText':'Generate\x20Link'});if(!_0x3e4792)return;try{const _0x235b34=await API['createPasswordToken'](_0x54e81c,'reset',![]);state['setupLinkData']={'username':_0x5ed01c['username'],'email':_0x5ed01c['email'],'url':_0x235b34['token']['setupUrl'],'userId':_0x5ed01c['id'],'type':'reset','emailSent':![]},showSetupLinkModal();}catch(_0x593617){console['error']('Failed\x20to\x20create\x20password\x20reset\x20link',_0x593617),Utils['showToast']('Failed\x20to\x20create\x20password\x20reset\x20link:\x20'+_0x593617['message'],'error');}};
|