@profoundlogic/coderflow-server 0.8.6 → 0.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-image/Dockerfile +3 -2
- package/dist/base-image/agent-wrapper.sh +7 -2
- package/dist/coder-server.js +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/setup-repo-git-auth.js +1 -1
- package/dist/lib/slack-service.js +1 -0
- 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-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 -0
- 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.css +476 -0
- package/dist/web-ui/public/admin.html +96 -17
- 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/_sidebar.md +1 -0
- package/dist/web-ui/public/docs/admin/container-lifecycle.md +102 -0
- package/dist/web-ui/public/docs/admin/jira.md +20 -3
- package/dist/web-ui/public/docs/docsify-proxy-helper.js +1 -0
- package/dist/web-ui/public/docs/index.html +25 -18
- package/dist/web-ui/public/environments.html +1 -0
- 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.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.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.js +1 -1
- package/dist/web-ui/public/settings.html +245 -0
- 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.js +1 -1
- package/dist/web-ui/public/sse-client.js +1 -1
- package/dist/web-ui/public/sse-client.transport-warning.js +1 -0
- 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.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.js +1 -1
- package/dist/web-ui/public/variant-grouping.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
let monacoLoadPromise=null;async function ensureMonacoLoaded(){if(typeof monaco!=='undefined')return;if(monacoLoadPromise)return monacoLoadPromise;const
|
|
1
|
+
let monacoLoadPromise=null;async function ensureMonacoLoaded(){if(typeof monaco!=='undefined')return;if(monacoLoadPromise)return monacoLoadPromise;const _0x48a364=document['querySelector']('script[src*=\x22monaco-editor\x22][src*=\x22loader.js\x22]');if(_0x48a364)return monacoLoadPromise=new Promise((_0x4fa501,_0x5b0072)=>{const _0x1c3290=setInterval(()=>{typeof monaco!=='undefined'&&(clearInterval(_0x1c3290),_0x4fa501());},0x32);setTimeout(()=>{clearInterval(_0x1c3290),_0x5b0072(new Error('Monaco\x20loading\x20timeout'));},0x2710);}),monacoLoadPromise;return monacoLoadPromise=new Promise((_0x27392b,_0x1c40b2)=>{const _0x3f77af=document['createElement']('script');_0x3f77af['src']='/vendor/monaco-editor/0.45.0/min/vs/loader.js',_0x3f77af['onload']=()=>{require['config']({'paths':{'vs':'/vendor/monaco-editor/0.45.0/min/vs'}}),require(['vs/editor/editor.main'],()=>{_0x27392b();});},_0x3f77af['onerror']=()=>_0x1c40b2(new Error('Failed\x20to\x20load\x20Monaco\x20Editor')),document['head']['appendChild'](_0x3f77af);}),monacoLoadPromise;}function getMonacoTheme(){const _0x4ba6f2=document['documentElement']['getAttribute']('data-theme')==='dark';return _0x4ba6f2?'vs-dark':'vs';}function isMarkdownFile(_0x4539b2){if(!_0x4539b2)return![];const _0x3bc5b0=_0x4539b2['split']('.')['pop']()['toLowerCase']();return _0x3bc5b0==='md'||_0x3bc5b0==='markdown';}function createMarkdownFileEditor(_0x1cb5e8){const {container:_0xd5567a,content:content='',readOnly:readOnly=![],height:height='400px',onChange:onChange=null,placeholder:placeholder='Enter\x20markdown\x20content...',enableModeToggle:enableModeToggle=!![],initialMode:initialMode='visual'}=_0x1cb5e8;_0xd5567a['innerHTML']='';const _0x10999e=document['createElement']('div');_0x10999e['className']='markdown-file-editor-wrapper',_0x10999e['style']['height']=height,_0x10999e['style']['display']='flex',_0x10999e['style']['flexDirection']='column',_0x10999e['style']['border']='1px\x20solid\x20var(--color-border)',_0x10999e['style']['borderRadius']='var(--radius-small)',_0x10999e['style']['overflow']='hidden';const _0x408220=document['createElement']('textarea');_0x408220['style']['display']='none',_0x408220['value']=content,_0x10999e['appendChild'](_0x408220),_0xd5567a['appendChild'](_0x10999e);const _0xfae5da=new window['MarkdownEditor'](_0x408220,{'placeholder':placeholder,'editable':!readOnly,'minHeight':'100%','toolbar':!readOnly,'sourceToggle':!readOnly&&enableModeToggle!==![],'sourceLineNumbers':!![],'onChange':_0x11f76e=>{onChange&&onChange(_0x11f76e);}});_0xfae5da['container']&&(_0xfae5da['container']['style']['flex']='1',_0xfae5da['container']['style']['display']='flex',_0xfae5da['container']['style']['flexDirection']='column',_0xfae5da['container']['style']['overflow']='hidden');_0xfae5da['editor']&&(_0xfae5da['editor']['style']['flex']='1',_0xfae5da['editor']['style']['overflow']='auto',_0xfae5da['editor']['style']['minHeight']='0',_0xfae5da['editor']['style']['border']='none',_0xfae5da['editor']['style']['borderRadius']='0',_0xfae5da['editor']['style']['padding']='16px',_0xfae5da['editor']['style']['fontSize']='14px',_0xfae5da['editor']['style']['lineHeight']='1.6');_0xfae5da['toolbar']&&(_0xfae5da['toolbar']['style']['borderRadius']='0',_0xfae5da['toolbar']['style']['flexShrink']='0');content&&_0xfae5da['setMarkdown'](content);initialMode==='source'&&!readOnly&&enableModeToggle!==![]&&setTimeout(()=>_0xfae5da['setMode']('source'),0x0);const _0x10285b={'getValue':()=>_0xfae5da['getValue'](),'setValue':_0x31855c=>_0xfae5da['setValue'](_0x31855c||''),'focus':()=>_0xfae5da['focus'](),'setEditable':_0x4a0564=>_0xfae5da['setEditable'](_0x4a0564),'destroy':()=>{_0xfae5da['destroy'](),_0xd5567a['innerHTML']='';},'getMode':()=>_0xfae5da['getMode'](),'setMode':_0x18fca9=>_0xfae5da['setMode'](_0x18fca9),'toggleMode':()=>_0xfae5da['toggleMode'](),'_visualEditor':_0xfae5da,'_getSourceEditor':()=>_0xfae5da['_monacoEditor'],'_container':_0xd5567a,'_isMarkdownFileEditor':!![],'_hasModeToggle':enableModeToggle};return _0x10285b;}const markdownFileEditors=new Map();function getOrCreateMarkdownFileEditor(_0x3c53a1,_0x2d34a7,_0x568131=![],_0x57afdb='400px',_0x572aa8=null,_0x23d76f={}){const _0x18a8d5=document['getElementById'](_0x3c53a1);if(!_0x18a8d5)return console['error']('Container\x20not\x20found:\x20'+_0x3c53a1),null;const _0x5f1a15=markdownFileEditors['get'](_0x3c53a1);if(_0x5f1a15){try{_0x5f1a15['destroy']();}catch(_0x18222c){console['warn']('Failed\x20to\x20destroy\x20existing\x20markdown\x20editor:',_0x18222c);}markdownFileEditors['delete'](_0x3c53a1);}const _0x5e6e4a=createMarkdownFileEditor({'container':_0x18a8d5,'content':_0x2d34a7,'readOnly':_0x568131,'height':_0x57afdb,'onChange':_0x572aa8,..._0x23d76f});return markdownFileEditors['set'](_0x3c53a1,_0x5e6e4a),_0x5e6e4a;}function getMarkdownFileEditorValue(_0x39891a){const _0x5b0da0=markdownFileEditors['get'](_0x39891a);if(!_0x5b0da0)return null;return _0x5b0da0['getValue']();}function setMarkdownFileEditorValue(_0x1e29d0,_0x4cfe37){const _0x1051dd=markdownFileEditors['get'](_0x1e29d0);_0x1051dd&&_0x1051dd['setValue'](_0x4cfe37||'');}function disposeMarkdownFileEditor(_0x5b9b74){const _0x290039=markdownFileEditors['get'](_0x5b9b74);if(_0x290039){try{_0x290039['destroy']();}catch(_0x11d3e7){console['warn']('Failed\x20to\x20dispose\x20markdown\x20editor:',_0x11d3e7);}markdownFileEditors['delete'](_0x5b9b74);}}function hasMarkdownFileEditor(_0x39dd38){return markdownFileEditors['has'](_0x39dd38);}function getMarkdownFileEditorMode(_0x5e4478){const _0x50d911=markdownFileEditors['get'](_0x5e4478);if(!_0x50d911||!_0x50d911['getMode'])return null;return _0x50d911['getMode']();}function setMarkdownFileEditorMode(_0x31fefb,_0x1c2818){const _0x1fd66e=markdownFileEditors['get'](_0x31fefb);_0x1fd66e&&_0x1fd66e['setMode']&&_0x1fd66e['setMode'](_0x1c2818);}typeof window!=='undefined'&&(window['MarkdownFileEditor']={'isMarkdownFile':isMarkdownFile,'create':createMarkdownFileEditor,'getOrCreate':getOrCreateMarkdownFileEditor,'getValue':getMarkdownFileEditorValue,'setValue':setMarkdownFileEditorValue,'dispose':disposeMarkdownFileEditor,'has':hasMarkdownFileEditor,'getMode':getMarkdownFileEditorMode,'setMode':setMarkdownFileEditorMode,'editors':markdownFileEditors,'ensureMonacoLoaded':ensureMonacoLoaded});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const DEFAULT_DURATION_MS=0xfa;function prefersReducedMotion(){try{return window['matchMedia']&&window['matchMedia']('(prefers-reduced-motion:\x20reduce)')['matches'];}catch{return![];}}function safeCancelAnimations(
|
|
1
|
+
const DEFAULT_DURATION_MS=0xfa;function prefersReducedMotion(){try{return window['matchMedia']&&window['matchMedia']('(prefers-reduced-motion:\x20reduce)')['matches'];}catch{return![];}}function safeCancelAnimations(_0x281e4b){if(!_0x281e4b||typeof _0x281e4b['getAnimations']!=='function')return;try{_0x281e4b['getAnimations']()['forEach'](_0x79c78a=>_0x79c78a['cancel']());}catch{}}function animateRestoreFlip({contentEl:_0x3c08a7,fromRect:_0x70508,toRect:_0x356262,durationMs:_0x3d096a}){if(!_0x3c08a7)return;if(!_0x70508||!_0x356262)return;if(prefersReducedMotion())return;const _0x41e096=_0x356262['width']||0x0,_0x473698=_0x356262['height']||0x0,_0x2034a7=_0x70508['width']||0x0,_0x3e8483=_0x70508['height']||0x0;if(_0x41e096<=0x0||_0x473698<=0x0||_0x2034a7<=0x0||_0x3e8483<=0x0)return;const _0x1bff6e=_0x70508['left']-_0x356262['left'],_0x21e4f6=_0x70508['top']-_0x356262['top'],_0x3e127c=_0x2034a7/_0x41e096,_0x1b54a1=_0x3e8483/_0x473698;if(!Number['isFinite'](_0x1bff6e)||!Number['isFinite'](_0x21e4f6)||!Number['isFinite'](_0x3e127c)||!Number['isFinite'](_0x1b54a1))return;safeCancelAnimations(_0x3c08a7);const _0x37f092=_0x3c08a7['style']['transition'],_0x2fe6a1=_0x3c08a7['style']['transformOrigin'],_0x528ba8=_0x3c08a7['style']['willChange'];_0x3c08a7['style']['transition']='none',_0x3c08a7['style']['transformOrigin']='top\x20left',_0x3c08a7['style']['willChange']='transform';const _0x4462d8='translate('+_0x1bff6e+'px,\x20'+_0x21e4f6+'px)\x20scale('+_0x3e127c+',\x20'+_0x1b54a1+')',_0x16ebb6=_0x3c08a7['animate']([{'transform':_0x4462d8},{'transform':'none'}],{'duration':_0x3d096a,'easing':'ease','fill':'both'}),_0x4661c2=()=>{_0x3c08a7['style']['transition']=_0x37f092,_0x3c08a7['style']['transformOrigin']=_0x2fe6a1,_0x3c08a7['style']['willChange']=_0x528ba8;};_0x16ebb6['addEventListener']('finish',_0x4661c2,{'once':!![]}),_0x16ebb6['addEventListener']('cancel',_0x4661c2,{'once':!![]});}export function toggleModalMaximize(_0xa23e15,_0x10abe2={}){if(!_0xa23e15)return;const {storageKey:_0x34d5e8,updateIcon:_0x217b7d,onAfterToggle:_0xac1b79,durationMs:durationMs=DEFAULT_DURATION_MS}=_0x10abe2,_0x1c95a8=_0xa23e15['querySelector']('.modal-content'),_0x270cac=_0xa23e15['classList']['contains']('maximized'),_0x3035ea=!_0x270cac;if(!_0x1c95a8){_0xa23e15['classList']['toggle']('maximized'),_0x217b7d?.(_0x3035ea),_0xac1b79?.(_0x3035ea);if(_0x34d5e8)try{localStorage['setItem'](_0x34d5e8,String(_0x3035ea));}catch{}return;}if(_0x270cac&&!prefersReducedMotion()){const _0x1bb22f=_0x1c95a8['getBoundingClientRect']();_0xa23e15['classList']['remove']('maximized');const _0x4a3fbf=_0x1c95a8['getBoundingClientRect']();animateRestoreFlip({'contentEl':_0x1c95a8,'fromRect':_0x1bb22f,'toRect':_0x4a3fbf,'durationMs':durationMs});}else _0xa23e15['classList']['toggle']('maximized');_0x217b7d?.(_0x3035ea),_0xac1b79?.(_0x3035ea);if(_0x34d5e8)try{localStorage['setItem'](_0x34d5e8,String(_0x3035ea));}catch{}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const NotificationManager={'isSupported'(){return'Notification'in window;},'isEnabled'(){if(!this['isSupported']())return![];return localStorage['getItem']('notifications-enabled')==='true';},'setEnabled'(
|
|
1
|
+
export const NotificationManager={'isSupported'(){return'Notification'in window;},'isEnabled'(){if(!this['isSupported']())return![];return localStorage['getItem']('notifications-enabled')==='true';},'setEnabled'(_0x19fa78){localStorage['setItem']('notifications-enabled',_0x19fa78?'true':'false');},'getPermission'(){if(!this['isSupported']())return'unsupported';return Notification['permission'];},async 'requestPermission'(){if(!this['isSupported']())return'unsupported';if(Notification['permission']==='granted')return'granted';if(Notification['permission']==='denied')return'denied';try{const _0x292bfe=await Notification['requestPermission']();return _0x292bfe;}catch(_0x4660a1){return console['error']('Failed\x20to\x20request\x20notification\x20permission:',_0x4660a1),'denied';}},async 'show'(_0x185f7b,_0x12411f={}){if(!this['isEnabled']())return null;if(!this['isSupported']())return console['warn']('Notifications\x20are\x20not\x20supported\x20in\x20this\x20browser'),null;if(Notification['permission']!=='granted')return console['warn']('Notification\x20permission\x20not\x20granted'),null;try{const _0x3e74c6=new Notification(_0x185f7b,{'icon':_0x12411f['icon']||'/favicon.ico','badge':_0x12411f['badge']||'/favicon.ico','body':_0x12411f['body']||'','tag':_0x12411f['tag']||'','requireInteraction':_0x12411f['requireInteraction']||![],'silent':_0x12411f['silent']||![],'data':_0x12411f['data']||{}});_0x12411f['onClick']&&(_0x3e74c6['onclick']=_0x42e94e=>{_0x42e94e['preventDefault'](),window['focus'](),_0x12411f['onClick'](_0x42e94e,_0x3e74c6),_0x3e74c6['close']();});if(!_0x12411f['requireInteraction']){const _0x36f956=_0x12411f['duration']||0x1388;setTimeout(()=>{_0x3e74c6['close']();},_0x36f956);}return _0x3e74c6;}catch(_0x3880ef){return console['error']('Failed\x20to\x20show\x20notification:',_0x3880ef),null;}},async 'notifyTaskComplete'(_0xe6f90){const _0x368da2=_0xe6f90['exitCode']!==undefined?_0xe6f90['exitCode']:_0xe6f90['exit_code'],_0x11a257=_0xe6f90['status']==='completed'&&_0x368da2===0x0,_0x440b64=_0xe6f90['status']==='interrupted',_0x1a00a2=_0x11a257?'✅\x20Task\x20Completed\x20Successfully':_0x440b64?'⏹️\x20Task\x20Interrupted':'❌\x20Task\x20Failed';let _0x28b553;if(_0xe6f90['taskType']==='test'){const _0x245f90=_0xe6f90['testName']||'Test',_0x3476fc=_0xe6f90['testDescription']||_0xe6f90['description']||'';if(_0x3476fc&&_0x3476fc['length']>0x0){let _0xa2d01=_0x3476fc;_0x3476fc['length']>0x50&&(_0xa2d01=_0x3476fc['substring'](0x0,0x4d)+'...'),_0x28b553='Test:\x20'+_0x245f90+'\x20-\x20'+_0xa2d01;}else _0x28b553='Test:\x20'+_0x245f90;}else{if(_0xe6f90['taskType']==='deploy'){const _0x56c28a=_0xe6f90['deployProfile']||'Deploy',_0x539b89=_0xe6f90['deployDescription']||_0xe6f90['description']||'';if(_0x539b89&&_0x539b89['length']>0x0){let _0x122a67=_0x539b89;_0x539b89['length']>0x50&&(_0x122a67=_0x539b89['substring'](0x0,0x4d)+'...'),_0x28b553='Deploy:\x20'+_0x56c28a+'\x20-\x20'+_0x122a67;}else _0x28b553='Deploy:\x20'+_0x56c28a;}else{const _0x38c154=_0xe6f90['name']?_0xe6f90['name']['trim']():null,_0x593113=_0xe6f90['envVars']?.['CODER_AGENT']||_0xe6f90['envVars']?.['default_agent']||'Unknown',_0x374a52=_0x593113['charAt'](0x0)['toUpperCase']()+_0x593113['slice'](0x1);let _0x52939e,_0x2726b6=![];if(_0xe6f90['followUpHistory']&&Array['isArray'](_0xe6f90['followUpHistory'])&&_0xe6f90['followUpHistory']['length']>0x0){const _0x555afc=_0xe6f90['followUpHistory'][_0xe6f90['followUpHistory']['length']-0x1];_0x52939e=_0x555afc['instructions'],_0x2726b6=!![];}else _0x52939e=_0xe6f90['description']||_0xe6f90['instructions']||_0xe6f90['taskId'];_0x52939e['length']>0x64&&(_0x52939e=_0x52939e['substring'](0x0,0x61)+'...');const _0x3db0ea=_0x2726b6?'[Follow-up]\x20':'';_0x38c154?_0x28b553=_0x38c154+'\x0a'+_0x374a52+':\x20'+_0x3db0ea+_0x52939e:_0x28b553=_0x374a52+':\x20'+_0x3db0ea+_0x52939e;}}return this['show'](_0x1a00a2,{'body':_0x28b553,'tag':'task-'+_0xe6f90['taskId'],'requireInteraction':![],'duration':0x1f40,'data':{'taskId':_0xe6f90['taskId']},'onClick':(_0x416791,_0x62da23)=>{window['open']('task.html?id='+_0xe6f90['taskId'],'_blank');}});},'shouldNotify'(_0x521e02,_0x2d2505){if(!this['isEnabled']())return![];if(_0x521e02['status']!=='completed'&&_0x521e02['status']!=='failed'&&_0x521e02['status']!=='interrupted')return![];if(!_0x2d2505['has'](_0x521e02['taskId']))return![];const _0x296e4d='notified-'+_0x521e02['taskId'];if(sessionStorage['getItem'](_0x296e4d)==='true')return![];return!![];},'markNotified'(_0x4e5b9e){sessionStorage['setItem']('notified-'+_0x4e5b9e,'true');},'clearNotificationHistory'(){const _0x22ae40=[];for(let _0x99c58f=0x0;_0x99c58f<sessionStorage['length'];_0x99c58f++){const _0x2677c0=sessionStorage['key'](_0x99c58f);_0x2677c0['startsWith']('notified-')&&_0x22ae40['push'](_0x2677c0);}_0x22ae40['forEach'](_0x791584=>sessionStorage['removeItem'](_0x791584));}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function permissionInSet(
|
|
1
|
+
function permissionInSet(_0x5a1a13,_0x16d04d){if(!_0x5a1a13||!_0x16d04d)return![];if(_0x5a1a13['includes']('*'))return!![];if(_0x5a1a13['includes'](_0x16d04d))return!![];const [_0x5b34fa]=_0x16d04d['split'](':');if(_0x5a1a13['includes'](_0x5b34fa+':*'))return!![];return![];}function hasServerPermission(_0x53d84f,_0x4b67ac){const _0x4e23cd=_0x53d84f?.['permissions']?.['server'];if(!_0x4e23cd)return![];return permissionInSet(_0x4e23cd,_0x4b67ac);}function hasEnvPermission(_0x44b8af,_0x40e13d){if(hasServerPermission(_0x44b8af,'*'))return!![];const _0x341d43=_0x44b8af?.['permissions']?.['environments'];if(!_0x341d43)return![];for(const _0x55b8cc of Object['values'](_0x341d43)){if(permissionInSet(_0x55b8cc,_0x40e13d))return!![];}return![];}function hasEnvPermissionOn(_0x5bdb88,_0xe85d2d,_0x10f322){if(hasServerPermission(_0x5bdb88,'*'))return!![];const _0x7bc9e7=_0x5bdb88?.['permissions']?.['environments']?.[_0xe85d2d];if(!_0x7bc9e7)return![];return permissionInSet(_0x7bc9e7,_0x10f322);}function hasTeamPermission(_0x132547,_0x292404){if(hasServerPermission(_0x132547,'*'))return!![];const _0x23fcda=_0x132547?.['permissions']?.['teams'];if(!_0x23fcda)return![];for(const _0x67fa33 of Object['values'](_0x23fcda)){if(permissionInSet(_0x67fa33,_0x292404))return!![];}return![];}function hasAnyEnvironment(_0x4bcd47){if(hasServerPermission(_0x4bcd47,'*'))return!![];const _0x3a5e0c=_0x4bcd47?.['permissions']?.['environments'];return _0x3a5e0c!=null&&Object['keys'](_0x3a5e0c)['length']>0x0;}window['Permissions']={'hasServerPermission':hasServerPermission,'hasEnvPermission':hasEnvPermission,'hasEnvPermissionOn':hasEnvPermissionOn,'hasTeamPermission':hasTeamPermission,'hasAnyEnvironment':hasAnyEnvironment};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function createPRDialogHTML(
|
|
1
|
+
export function createPRDialogHTML(_0x186fca='',_0x4b1692={}){const _0x30acc5=_0x186fca,_0x4f1336=_0x4b1692['useTaskPageStyles']?'modal\x20profound-pr-modal':'profound-feedback-modal\x20profound-pr-modal',_0xcbc6a9=_0x4b1692['useTaskPageStyles']?'modal-warning':'pr-modal-warning',_0x4e2d9d=_0x4b1692['useTaskPageStyles']?'modal-error':'pr-modal-error';return'\x0a\x20\x20\x20\x20<div\x20id=\x22'+_0x30acc5+'pr-modal\x22\x20class=\x22'+_0x4f1336+'\x22\x20hidden>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-overlay\x22></div>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-content\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-header\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<h2>Create\x20Pull\x20Request</h2>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22modal-close\x22\x20id=\x22'+_0x30acc5+'close-pr-modal\x22>×</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-body\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20id=\x22'+_0x30acc5+'pr-error\x22\x20class=\x22'+_0x4e2d9d+'\x22\x20hidden>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22error-icon\x22>!</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20id=\x22'+_0x30acc5+'pr-error-text\x22></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20id=\x22'+_0x30acc5+'pr-form-section\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-section\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20for=\x22'+_0x30acc5+'pr-title\x22>Title:</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22text\x22\x20id=\x22'+_0x30acc5+'pr-title\x22\x20class=\x22pr-title-input\x22\x20placeholder=\x22Enter\x20pull\x20request\x20title...\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-section\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20for=\x22'+_0x30acc5+'pr-body\x22>Description:</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<textarea\x20id=\x22'+_0x30acc5+'pr-body\x22\x20class=\x22pr-body-input\x22\x20rows=\x226\x22\x20placeholder=\x22Enter\x20pull\x20request\x20description...\x22></textarea>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20id=\x22'+_0x30acc5+'pr-repos-section\x22\x20class=\x22modal-section\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label>Target\x20Branches</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20id=\x22'+_0x30acc5+'pr-repos-list\x22\x20class=\x22pr-repos-list\x22></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22modal-footer\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-ghost\x22\x20id=\x22'+_0x30acc5+'cancel-pr\x22>Cancel</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-primary\x22\x20id=\x22'+_0x30acc5+'confirm-pr\x22>Create\x20Pull\x20Request</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20';}export class PRDialog{constructor(_0x1bba2e={}){this['prefix']=_0x1bba2e['prefix']||'',this['onSubmit']=_0x1bba2e['onSubmit'],this['onCancel']=_0x1bba2e['onCancel'],this['showToast']=_0x1bba2e['showToast']||(()=>{}),this['container']=_0x1bba2e['container']||document['body'],this['useTaskPageStyles']=_0x1bba2e['useTaskPageStyles']||![],this['baseUrl']=_0x1bba2e['baseUrl']||'',this['prData']=null,this['initialized']=![],this['isSubmitting']=![];}['init'](){if(this['initialized'])return;const _0x1fca41=document['createElement']('div');_0x1fca41['innerHTML']=createPRDialogHTML(this['prefix'],{'useTaskPageStyles':this['useTaskPageStyles']}),this['container']['appendChild'](_0x1fca41['firstElementChild']),this['_bindEvents'](),this['initialized']=!![];}['_el'](_0x28e6eb){return document['getElementById'](''+this['prefix']+_0x28e6eb);}['_bindEvents'](){this['_el']('close-pr-modal')?.['addEventListener']('click',()=>this['hide']()),this['_el']('cancel-pr')?.['addEventListener']('click',()=>this['hide']()),this['_el']('confirm-pr')?.['addEventListener']('click',()=>this['_handleSubmit']()),this['_el']('pr-modal')?.['addEventListener']('click',_0x233e56=>{_0x233e56['target']['id']===this['prefix']+'pr-modal'&&this['hide']();}),document['addEventListener']('keydown',_0x294c27=>{_0x294c27['key']==='Escape'&&!this['_el']('pr-modal')['hidden']&&this['hide']();});}async['show'](_0x422a01){if(!this['initialized'])this['init']();this['prData']=_0x422a01;const {taskId:_0x1b9a7c,repos:_0x53ef76,suggestedTitle:_0x11cc93,suggestedBody:_0xe37602}=_0x422a01;return this['_el']('pr-title')['value']=_0x11cc93||'',this['_el']('pr-body')['value']=_0xe37602||'',this['_el']('pr-error')['hidden']=!![],await this['_renderRepoSelectors'](_0x53ef76),this['_el']('pr-modal')['hidden']=![],new Promise(_0x1a5c57=>{this['_dismissResolve']=_0x1a5c57;});}async['_renderRepoSelectors'](_0x283785){const _0x4d8c8c=this['_el']('pr-repos-list');_0x4d8c8c['innerHTML']='';for(const _0x1d4534 of _0x283785){if(!_0x1d4534['supportsPR'])continue;const _0x434095=document['createElement']('div');_0x434095['className']='pr-repo-selector';const _0x5288f8=document['createElement']('span');_0x5288f8['className']='pr-repo-name',_0x5288f8['textContent']=_0x1d4534['name'];const _0xabc781=document['createElement']('span');_0xabc781['className']='pr-base-branch',_0xabc781['textContent']=_0x1d4534['base']||_0x1d4534['defaultBranch']||'main',_0xabc781['dataset']['repo']=_0x1d4534['name'],_0xabc781['dataset']['base']=_0x1d4534['base']||_0x1d4534['defaultBranch']||'main';const _0x53a581=document['createElement']('span');_0x53a581['className']='pr-arrow',_0x53a581['textContent']='←';const _0x110c3a=document['createElement']('span');_0x110c3a['className']='pr-source-branch',_0x110c3a['textContent']=_0x1d4534['head']||'(head\x20branch)',_0x434095['appendChild'](_0x5288f8),_0x434095['appendChild'](_0xabc781),_0x434095['appendChild'](_0x53a581),_0x434095['appendChild'](_0x110c3a),_0x4d8c8c['appendChild'](_0x434095);}}['hide'](){if(this['isSubmitting'])return;this['_el']('pr-modal')['hidden']=!![],this['onCancel']&&this['onCancel'](),this['_dismissResolve']&&(this['_dismissResolve'](),this['_dismissResolve']=null);}async['_handleSubmit'](){if(this['isSubmitting'])return;const _0x2bd16d=this['_el']('pr-title')['value']['trim'](),_0x1467e0=this['_el']('pr-body')['value']['trim']();if(!_0x2bd16d){this['_showError']('Pull\x20request\x20title\x20is\x20required');return;}const _0x890022=[],_0x14ad71=this['_el']('pr-repos-list')['querySelectorAll']('.pr-base-branch');for(const _0x4cd5e4 of _0x14ad71){const _0x16f99a=_0x4cd5e4['dataset']['repo'],_0xd108c8=_0x4cd5e4['dataset']['base'],_0x1f43b6=this['prData']['repos']['find'](_0x222bdd=>_0x222bdd['name']===_0x16f99a);if(!_0x1f43b6)continue;_0x890022['push']({'name':_0x16f99a,'title':_0x2bd16d,'body':_0x1467e0,'head':_0x1f43b6['head'],'base':_0xd108c8});}if(_0x890022['length']===0x0){this['_showError']('No\x20repositories\x20selected');return;}this['isSubmitting']=!![],this['_el']('confirm-pr')['disabled']=!![],this['_el']('confirm-pr')['textContent']='Creating...';try{const _0x249a65=await this['onSubmit'](this['prData']['taskId'],_0x890022),_0xff413e=_0x249a65['results']['every'](_0x4553c8=>_0x4553c8['success']),_0x3279c8=_0x249a65['results']['some'](_0x1127e4=>_0x1127e4['success']);if(_0xff413e)this['showToast']('Pull\x20requests\x20created\x20successfully','success');else{if(_0x3279c8)this['showToast']('Some\x20pull\x20requests\x20created\x20successfully','warning');else throw new Error('All\x20pull\x20request\x20creations\x20failed');}this['isSubmitting']=![],this['_el']('confirm-pr')['disabled']=![],this['_el']('confirm-pr')['textContent']='Create\x20Pull\x20Request',this['hide'](),window['refreshTask']&&window['refreshTask']({'withSpinner':![]});}catch(_0x56288b){console['error']('PR\x20creation\x20failed:',_0x56288b),this['_showError'](_0x56288b['message']||'Failed\x20to\x20create\x20pull\x20requests'),this['isSubmitting']=![],this['_el']('confirm-pr')['disabled']=![],this['_el']('confirm-pr')['textContent']='Create\x20Pull\x20Request';}}['_showError'](_0x1cda57){this['_el']('pr-error-text')['textContent']=_0x1cda57,this['_el']('pr-error')['hidden']=![];}static['checkOAuthRedirect'](_0x34d8c3){if(_0x34d8c3['get']('source')==='pr'&&_0x34d8c3['get']('git_connection')){const _0x2efe3e=sessionStorage['getItem']('pendingPRData');if(_0x2efe3e)try{const _0x255929=JSON['parse'](_0x2efe3e);if(Date['now']()-_0x255929['timestamp']<0xa*0x3c*0x3e8)return sessionStorage['removeItem']('pendingPRData'),_0x255929;}catch(_0x4c7f55){console['error']('Failed\x20to\x20parse\x20pending\x20PR\x20data:',_0x4c7f55);}}return null;}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{API,Utils,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const PERMISSION_CATEGORIES={'tasks':'Tasks','environments':'Environments','objectives':'Objectives','users':'Users','settings':'Settings','server':'Server','deployments':'Deployments','apikeys':'API\x20Keys','skills':'Skills','bindings':'Access\x20Bindings','containers':'Containers','tests':'Tests','jira':'JIRA','git-oauth':'Git\x20OAuth','qa':'QA','visualizations':'Visualizations'},SCOPE_CONFIG={'environment':{'label':'Env','color':'#3b82f6','bg':'rgba(59,130,246,0.12)'},'server':{'label':'Server','color':'#f59e0b','bg':'rgba(245,158,11,0.12)'},'team':{'label':'Team','color':'#10b981','bg':'rgba(16,185,129,0.12)'},'user':{'label':'User','color':'#8b5cf6','bg':'rgba(139,92,246,0.12)'}},state={'roles':[],'availablePermissions':[],'currentUser':null,'editingRoleId':null,'deletingRoleId':null,'editModalSnapshot':null};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle();try{state['currentUser']=await API['getCurrentUser']();}catch{window['location']['href']='login.html';return;}await initializeAdminMenu(state['currentUser']);if(!Permissions['hasServerPermission'](state['currentUser'],'*')){window['location']['href']='index.html';return;}document['getElementById']('create-role-btn')['hidden']=![],bindEventListeners(),await loadAvailablePermissions(),await loadRoles();});async function loadRoles(){const _0x56a466=document['getElementById']('roles-loading'),_0x1d723c=document['getElementById']('roles-error'),_0x4b106a=document['getElementById']('roles-content');try{_0x56a466['hidden']=![],_0x1d723c['hidden']=!![],_0x4b106a['hidden']=!![];const {roles:_0x882125}=await API['getRoleDefinitions']();state['roles']=_0x882125||[],renderRoles(),_0x56a466['hidden']=!![],_0x4b106a['hidden']=![];}catch(_0x37cb33){_0x56a466['hidden']=!![],_0x1d723c['hidden']=![],document['getElementById']('roles-error-message')['textContent']=_0x37cb33['message'];}}async function loadAvailablePermissions(){try{const {permissions:_0x2a0e29}=await API['getAvailablePermissions']();state['availablePermissions']=_0x2a0e29||[];}catch{state['availablePermissions']=[];}}function getPermissionScopeMap(){const _0x1be1fd={};for(const _0xfed65a of state['availablePermissions']){_0xfed65a['scope']&&(_0x1be1fd[_0xfed65a['key']]=_0xfed65a['scope']);}return _0x1be1fd;}function getRoleScopeTags(_0x56c396){if(!_0x56c396||_0x56c396['length']===0x0)return'<span\x20style=\x22color:\x20var(--color-text-secondary);\x22>—</span>';if(_0x56c396['includes']('*'))return Object['values'](SCOPE_CONFIG)['map'](_0x517f61=>'<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x517f61['bg']+';\x20color:\x20'+_0x517f61['color']+';\x20font-size:\x200.75rem;\x20margin-right:\x200.25rem;\x22>'+_0x517f61['label']+'</span>')['join']('');const _0xd0bfbf=getPermissionScopeMap(),_0x343200=new Set();for(const _0x366215 of _0x56c396){const _0x33c435=_0xd0bfbf[_0x366215];if(_0x33c435)_0x343200['add'](_0x33c435);}if(_0x343200['size']===0x0)return'<span\x20style=\x22color:\x20var(--color-text-secondary);\x22>—</span>';const _0x435ea1=['environment','server','team','user'];return _0x435ea1['filter'](_0x58c05b=>_0x343200['has'](_0x58c05b))['map'](_0x2b2ba9=>{const _0x2756c2=SCOPE_CONFIG[_0x2b2ba9];return'<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x2756c2['bg']+';\x20color:\x20'+_0x2756c2['color']+';\x20font-size:\x200.75rem;\x20margin-right:\x200.25rem;\x22>'+_0x2756c2['label']+'</span>';})['join']('');}function renderRoles(){const _0xbb5425=document['getElementById']('roles-table-body'),_0x3724cd=document['getElementById']('role-count');if(!_0xbb5425)return;_0x3724cd&&(_0x3724cd['textContent']=state['roles']['length']+'\x20role'+(state['roles']['length']===0x1?'':'s'));const _0x25acce=Permissions['hasServerPermission'](state['currentUser'],'*');_0xbb5425['innerHTML']=state['roles']['map'](_0x46d5ef=>{const _0x410749=_0x46d5ef['permissions']?.['length']??0x0,_0x5128bb=_0x46d5ef['predefined']?'Predefined':'Custom',_0x57d07e=_0x46d5ef['predefined']?'background:\x20var(--color-surface);\x20color:\x20var(--color-text-secondary);':'background:\x20rgba(0,100,200,0.1);\x20color:\x20var(--color-primary);',_0x405461=getRoleScopeTags(_0x46d5ef['permissions']);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<button\x20class=\x22btn-ghost\x20btn-small\x22\x20style=\x22font-weight:\x20600;\x20padding:\x200;\x20text-decoration:\x20underline;\x20text-decoration-style:\x20dotted;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20onclick=\x22window.openRoleModal(\x27'+_0x46d5ef['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+Utils['escapeHtml'](_0x46d5ef['name'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x46d5ef['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x46d5ef['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td><span\x20class=\x22tag\x22\x20style=\x22'+_0x57d07e+'\x22>'+_0x5128bb+'</span></td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x405461+'</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+(_0x410749===0x1&&_0x46d5ef['permissions'][0x0]==='*'?'All\x20permissions':_0x410749+'\x20permission'+(_0x410749===0x1?'':'s'))+'</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>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-secondary\x20btn-small\x22\x20onclick=\x22window.openRoleModal(\x27'+_0x46d5ef['id']+'\x27)\x22>View'+(_0x25acce?'/Edit':'')+'</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x25acce&&!_0x46d5ef['predefined']?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteRole(\x27'+_0x46d5ef['id']+'\x27)\x22>Delete</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']('');}window['openRoleModal']=function(_0x376835){const _0x5f36d1=state['roles']['find'](_0x2fac1e=>_0x2fac1e['id']===_0x376835);if(!_0x5f36d1)return;const _0x2fc1d8=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x17f9d5=_0x2fc1d8&&!_0x5f36d1['predefined'];state['editingRoleId']=_0x376835,document['getElementById']('role-modal-title')['textContent']=_0x5f36d1['name'],document['getElementById']('role-name')['value']=_0x5f36d1['name'],document['getElementById']('role-name')['disabled']=!_0x17f9d5,document['getElementById']('role-description')['value']=_0x5f36d1['description']||'',document['getElementById']('role-description')['disabled']=!_0x17f9d5,document['getElementById']('role-form-error')['hidden']=!![],document['getElementById']('save-role')['hidden']=!_0x17f9d5;const _0x2826fd=document['getElementById']('role-readonly-notice');_0x2826fd['hidden']=_0x17f9d5,renderPermissionsChecklist('permissions-checklist',_0x5f36d1['permissions'],_0x17f9d5),_0x17f9d5?state['editModalSnapshot']={'name':_0x5f36d1['name'],'description':_0x5f36d1['description']||'','permissions':[..._0x5f36d1['permissions']||[]]['sort']()}:state['editModalSnapshot']=null,document['getElementById']('role-modal')['hidden']=![];};function isRoleModalDirty(){if(!state['editModalSnapshot'])return![];const _0x3f5b04=document['getElementById']('role-name')['value']['trim'](),_0x5bd644=document['getElementById']('role-description')['value']['trim'](),_0x1a1af2=getCheckedPermissions('permissions-checklist')['sort']();return _0x3f5b04!==state['editModalSnapshot']['name']||_0x5bd644!==state['editModalSnapshot']['description']||JSON['stringify'](_0x1a1af2)!==JSON['stringify'](state['editModalSnapshot']['permissions']);}function requestHideRoleModal(){if(isRoleModalDirty()){if(!confirm('You\x20have\x20unsaved\x20changes.\x20Discard\x20them?'))return;}hideRoleModal();}function hideRoleModal(){document['getElementById']('role-modal')['hidden']=!![],state['editingRoleId']=null,state['editModalSnapshot']=null;const _0x2e57b2=document['getElementById']('save-role');_0x2e57b2['disabled']=![],_0x2e57b2['textContent']='Save\x20Role';}function showCreateRoleModal(){document['getElementById']('new-role-name')['value']='',document['getElementById']('new-role-description')['value']='',document['getElementById']('create-role-error')['hidden']=!![],renderPermissionsChecklist('new-permissions-checklist',[],!![]),document['getElementById']('create-role-modal')['hidden']=![],setTimeout(()=>document['getElementById']('new-role-name')['focus'](),0x64);}function hideCreateRoleModal(){document['getElementById']('create-role-modal')['hidden']=!![];const _0x5861ba=document['getElementById']('save-new-role');_0x5861ba['disabled']=![],_0x5861ba['textContent']='Create\x20Role';}function renderPermissionsChecklist(_0x5f5ce6,_0x2d385a,_0x13d982){const _0x41691a=document['getElementById'](_0x5f5ce6);if(!_0x41691a)return;const _0x324b7d=_0x2d385a['includes']('*');if(_0x324b7d){_0x41691a['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x22>This\x20role\x20has\x20<strong>all\x20permissions</strong>\x20(wildcard).</p>';return;}const _0x58af84=['environment','server','team','user'],_0x31fc50={'environment':'Environment-Scoped','server':'Server-Scoped','team':'Team-Scoped','user':'User-Scoped'},_0x4b24c4={'environment':'These\x20permissions\x20are\x20granted\x20via\x20bindings\x20and\x20apply\x20only\x20to\x20bound\x20environments.','server':'These\x20permissions\x20apply\x20server-wide\x20and\x20are\x20typically\x20for\x20admin\x20functions.','team':'These\x20permissions\x20apply\x20to\x20team\x20management.','user':'These\x20permissions\x20apply\x20to\x20the\x20user\x27s\x20own\x20resources\x20regardless\x20of\x20bindings.'},_0x52b066={};for(const _0x40084b of state['availablePermissions']){const _0x40f6a9=_0x40084b['scope']||'environment',_0x3546e1=_0x40084b['category']||_0x40084b['key']['split'](':')[0x0];if(!_0x52b066[_0x40f6a9])_0x52b066[_0x40f6a9]={};if(!_0x52b066[_0x40f6a9][_0x3546e1])_0x52b066[_0x40f6a9][_0x3546e1]=[];_0x52b066[_0x40f6a9][_0x3546e1]['push'](_0x40084b);}const _0xe072a9=new Set(_0x2d385a),_0x273acc='\x0a\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.8rem;\x20color:\x20var(--color-text-secondary);\x20background:\x20var(--color-surface);\x20border:\x201px\x20solid\x20var(--color-border);\x20border-radius:\x206px;\x20padding:\x200.6rem\x200.75rem;\x20margin-bottom:\x201rem;\x22>\x0a\x20\x20\x20\x20\x20\x20<strong\x20style=\x22color:\x20var(--color-text);\x22>Scope\x20mixing:</strong>\x0a\x20\x20\x20\x20\x20\x20A\x20role\x20can\x20mix\x20permissions\x20of\x20each\x20scope\x20type—environment,\x20user,\x20server,\x20team—with\x20one\x20exception:\x20a\x20role\x20cannot\x20include\x20both\x20a\x20team\x20permission\x20and\x20an\x20environment\x20permission.\x0a\x20\x20\x20\x20</div>',_0x48c3ed=_0x58af84['filter'](_0x1defa5=>_0x52b066[_0x1defa5])['map'](_0x3c8c47=>{const _0x2d40c0=_0x52b066[_0x3c8c47],_0x392d4f=SCOPE_CONFIG[_0x3c8c47],_0x274a78=Object['entries'](_0x2d40c0)['map'](([_0xf8b1bd,_0x4a70ef])=>{const _0x4cd047=PERMISSION_CATEGORIES[_0xf8b1bd]||_0xf8b1bd,_0x4502e2=_0x4a70ef['map'](_0x24652f=>{const _0x26ae6b=_0xe072a9['has'](_0x24652f['key'])?'checked':'',_0x29082a=_0x13d982?'':'disabled';return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20style=\x22display:\x20flex;\x20align-items:\x20flex-start;\x20gap:\x200.5rem;\x20padding:\x200.2rem\x200;\x20cursor:\x20'+(_0x13d982?'pointer':'default')+';\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20value=\x22'+_0x24652f['key']+'\x22\x20'+_0x26ae6b+'\x20'+_0x29082a+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22margin-top:\x200.2rem;\x20flex-shrink:\x200;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22perm-checkbox\x22\x20data-container=\x22'+_0x5f5ce6+'\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.8rem;\x20font-family:\x20monospace;\x20color:\x20var(--color-primary);\x22>'+Utils['escapeHtml'](_0x24652f['key'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.78rem;\x20color:\x20var(--color-text-secondary);\x20margin-left:\x200.5rem;\x22>'+Utils['escapeHtml'](_0x24652f['description'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>';})['join']('');return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-bottom:\x200.75rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.75rem;\x20font-weight:\x20700;\x20text-transform:\x20uppercase;\x20letter-spacing:\x200.05em;\x20color:\x20var(--color-text-secondary);\x20margin-bottom:\x200.35rem;\x22>'+Utils['escapeHtml'](_0x4cd047)+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x4502e2+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>';})['join']('');return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-bottom:\x201.25rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20align-items:\x20center;\x20gap:\x200.5rem;\x20margin-bottom:\x200.15rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.8rem;\x20font-weight:\x20700;\x20color:\x20'+_0x392d4f['color']+';\x22>'+_0x31fc50[_0x3c8c47]+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x392d4f['bg']+';\x20color:\x20'+_0x392d4f['color']+';\x20font-size:\x200.65rem;\x22>'+_0x392d4f['label']+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.75rem;\x20color:\x20var(--color-text-secondary);\x20margin-bottom:\x200.5rem;\x22>'+_0x4b24c4[_0x3c8c47]+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22border-left:\x202px\x20solid\x20'+_0x392d4f['color']+';\x20padding-left:\x200.75rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x274a78+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>';})['join']('');_0x41691a['innerHTML']=_0x273acc+_0x48c3ed;}function getCheckedPermissions(_0x423144){const _0x221b06=document['getElementById'](_0x423144);if(!_0x221b06)return[];return Array['from'](_0x221b06['querySelectorAll']('.perm-checkbox:checked'))['map'](_0x1b6570=>_0x1b6570['value']);}async function saveRole(){const _0xb65672=document['getElementById']('role-name')['value']['trim'](),_0x1b4892=document['getElementById']('role-description')['value']['trim'](),_0x4c8e21=getCheckedPermissions('permissions-checklist'),_0x5b0af6=document['getElementById']('role-form-error'),_0x1481e4=document['getElementById']('save-role');if(!_0xb65672){_0x5b0af6['textContent']='Role\x20name\x20is\x20required',_0x5b0af6['hidden']=![];return;}if(_0x4c8e21['length']===0x0){_0x5b0af6['textContent']='Select\x20at\x20least\x20one\x20permission',_0x5b0af6['hidden']=![];return;}_0x5b0af6['hidden']=!![];const _0xcf83c6=_0x1481e4['textContent'];_0x1481e4['disabled']=!![],_0x1481e4['textContent']='Saving…';try{const {role:_0x4ba240}=await API['updateRoleDefinition'](state['editingRoleId'],{'name':_0xb65672,'description':_0x1b4892,'permissions':_0x4c8e21}),_0x3f0a1b=state['roles']['findIndex'](_0x28caaa=>_0x28caaa['id']===_0x4ba240['id']);if(_0x3f0a1b>=0x0)state['roles'][_0x3f0a1b]=_0x4ba240;renderRoles(),Utils['showToast']('Role\x20updated','success'),hideRoleModal();}catch(_0x4c87ee){_0x5b0af6['textContent']=_0x4c87ee['message'],_0x5b0af6['hidden']=![],_0x1481e4['disabled']=![],_0x1481e4['textContent']=_0xcf83c6;}}async function createRole(){const _0x385baf=document['getElementById']('new-role-name')['value']['trim'](),_0x40a0b2=document['getElementById']('new-role-description')['value']['trim'](),_0xbabf85=getCheckedPermissions('new-permissions-checklist'),_0x4dac13=document['getElementById']('create-role-error'),_0x11a20f=document['getElementById']('save-new-role');if(!_0x385baf){_0x4dac13['textContent']='Role\x20name\x20is\x20required',_0x4dac13['hidden']=![];return;}if(_0xbabf85['length']===0x0){_0x4dac13['textContent']='Select\x20at\x20least\x20one\x20permission',_0x4dac13['hidden']=![];return;}_0x4dac13['hidden']=!![];const _0x2e614c=_0x11a20f['textContent'];_0x11a20f['disabled']=!![],_0x11a20f['textContent']='Creating…';try{const {role:_0x3fcee8}=await API['createRoleDefinition']({'name':_0x385baf,'description':_0x40a0b2,'permissions':_0xbabf85});state['roles']['push'](_0x3fcee8),renderRoles(),Utils['showToast']('Role\x20created','success'),hideCreateRoleModal();}catch(_0x4ac9ad){_0x4dac13['textContent']=_0x4ac9ad['message'],_0x4dac13['hidden']=![],_0x11a20f['disabled']=![],_0x11a20f['textContent']=_0x2e614c;}}window['deleteRole']=function(_0x25e411){const _0x2a50fb=state['roles']['find'](_0x4dfdec=>_0x4dfdec['id']===_0x25e411);if(!_0x2a50fb)return;state['deletingRoleId']=_0x25e411,document['getElementById']('delete-role-name')['textContent']=_0x2a50fb['name'],document['getElementById']('delete-role-modal')['hidden']=![];};function hideDeleteRoleModal(){document['getElementById']('delete-role-modal')['hidden']=!![],state['deletingRoleId']=null;const _0x41b1f0=document['getElementById']('confirm-delete-role');_0x41b1f0['disabled']=![],_0x41b1f0['textContent']='Delete\x20Role';}async function confirmDeleteRole(){if(!state['deletingRoleId'])return;const _0x4f62d2=document['getElementById']('confirm-delete-role');_0x4f62d2['disabled']=!![],_0x4f62d2['textContent']='Deleting…';try{await API['deleteRoleDefinition'](state['deletingRoleId']),state['roles']=state['roles']['filter'](_0x2f2136=>_0x2f2136['id']!==state['deletingRoleId']),renderRoles(),Utils['showToast']('Role\x20deleted','success'),hideDeleteRoleModal();}catch(_0x34cd4e){Utils['showToast']('Failed\x20to\x20delete\x20role:\x20'+_0x34cd4e['message'],'error'),_0x4f62d2['disabled']=![],_0x4f62d2['textContent']='Delete\x20Role';}}function bindEventListeners(){document['getElementById']('create-role-btn')?.['addEventListener']('click',showCreateRoleModal),document['getElementById']('retry-roles-btn')?.['addEventListener']('click',loadRoles),document['getElementById']('close-role-modal')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('cancel-role')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('save-role')?.['addEventListener']('click',saveRole),document['querySelector']('#role-modal\x20.modal-overlay')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('close-create-role-modal')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('cancel-create-role')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('save-new-role')?.['addEventListener']('click',createRole),document['querySelector']('#create-role-modal\x20.modal-overlay')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('close-delete-role-modal')?.['addEventListener']('click',hideDeleteRoleModal),document['getElementById']('cancel-delete-role')?.['addEventListener']('click',hideDeleteRoleModal),document['getElementById']('confirm-delete-role')?.['addEventListener']('click',confirmDeleteRole),document['querySelector']('#delete-role-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteRoleModal);}
|
|
1
|
+
import{API,Utils,initializeAdminMenu}from'./app.js';import{initTheme,mountThemeToggle}from'./theme.js';const PERMISSION_CATEGORIES={'tasks':'Tasks','environments':'Environments','objectives':'Objectives','users':'Users','settings':'Settings','server':'Server','deployments':'Deployments','apikeys':'API\x20Keys','skills':'Skills','bindings':'Access\x20Bindings','containers':'Containers','tests':'Tests','jira':'JIRA','git-oauth':'Git\x20OAuth','qa':'QA','visualizations':'Visualizations'},SCOPE_CONFIG={'environment':{'label':'Env','color':'#3b82f6','bg':'rgba(59,130,246,0.12)'},'server':{'label':'Server','color':'#f59e0b','bg':'rgba(245,158,11,0.12)'},'team':{'label':'Team','color':'#10b981','bg':'rgba(16,185,129,0.12)'},'user':{'label':'User','color':'#8b5cf6','bg':'rgba(139,92,246,0.12)'}},state={'roles':[],'availablePermissions':[],'currentUser':null,'editingRoleId':null,'deletingRoleId':null,'editModalSnapshot':null};document['addEventListener']('DOMContentLoaded',async()=>{initTheme(),mountThemeToggle();try{state['currentUser']=await API['getCurrentUser']();}catch{window['location']['href']='login.html';return;}await initializeAdminMenu(state['currentUser']);if(!Permissions['hasServerPermission'](state['currentUser'],'*')){window['location']['href']='index.html';return;}document['getElementById']('create-role-btn')['hidden']=![],bindEventListeners(),await loadAvailablePermissions(),await loadRoles();});async function loadRoles(){const _0x1e1775=document['getElementById']('roles-loading'),_0xab65b4=document['getElementById']('roles-error'),_0x106452=document['getElementById']('roles-content');try{_0x1e1775['hidden']=![],_0xab65b4['hidden']=!![],_0x106452['hidden']=!![];const {roles:_0x42d67a}=await API['getRoleDefinitions']();state['roles']=_0x42d67a||[],renderRoles(),_0x1e1775['hidden']=!![],_0x106452['hidden']=![];}catch(_0x3d4086){_0x1e1775['hidden']=!![],_0xab65b4['hidden']=![],document['getElementById']('roles-error-message')['textContent']=_0x3d4086['message'];}}async function loadAvailablePermissions(){try{const {permissions:_0x3ef1e2}=await API['getAvailablePermissions']();state['availablePermissions']=_0x3ef1e2||[];}catch{state['availablePermissions']=[];}}function getPermissionScopeMap(){const _0x20cd8e={};for(const _0x846814 of state['availablePermissions']){_0x846814['scope']&&(_0x20cd8e[_0x846814['key']]=_0x846814['scope']);}return _0x20cd8e;}function getRoleScopeTags(_0x20330a){if(!_0x20330a||_0x20330a['length']===0x0)return'<span\x20style=\x22color:\x20var(--color-text-secondary);\x22>—</span>';if(_0x20330a['includes']('*'))return Object['values'](SCOPE_CONFIG)['map'](_0x18c4ef=>'<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x18c4ef['bg']+';\x20color:\x20'+_0x18c4ef['color']+';\x20font-size:\x200.75rem;\x20margin-right:\x200.25rem;\x22>'+_0x18c4ef['label']+'</span>')['join']('');const _0x3980b2=getPermissionScopeMap(),_0x2e49b1=new Set();for(const _0x29e048 of _0x20330a){const _0x5973f9=_0x3980b2[_0x29e048];if(_0x5973f9)_0x2e49b1['add'](_0x5973f9);}if(_0x2e49b1['size']===0x0)return'<span\x20style=\x22color:\x20var(--color-text-secondary);\x22>—</span>';const _0x342033=['environment','server','team','user'];return _0x342033['filter'](_0xd4d87e=>_0x2e49b1['has'](_0xd4d87e))['map'](_0x42112d=>{const _0x5cf42b=SCOPE_CONFIG[_0x42112d];return'<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x5cf42b['bg']+';\x20color:\x20'+_0x5cf42b['color']+';\x20font-size:\x200.75rem;\x20margin-right:\x200.25rem;\x22>'+_0x5cf42b['label']+'</span>';})['join']('');}function renderRoles(){const _0x2b03bf=document['getElementById']('roles-table-body'),_0x5caf21=document['getElementById']('role-count');if(!_0x2b03bf)return;_0x5caf21&&(_0x5caf21['textContent']=state['roles']['length']+'\x20role'+(state['roles']['length']===0x1?'':'s'));const _0x16342e=Permissions['hasServerPermission'](state['currentUser'],'*');_0x2b03bf['innerHTML']=state['roles']['map'](_0x355ec7=>{const _0x32f889=_0x355ec7['permissions']?.['length']??0x0,_0x51d5d6=_0x355ec7['predefined']?'Predefined':'Custom',_0x477e90=_0x355ec7['predefined']?'background:\x20var(--color-surface);\x20color:\x20var(--color-text-secondary);':'background:\x20rgba(0,100,200,0.1);\x20color:\x20var(--color-primary);',_0x3e5d63=getRoleScopeTags(_0x355ec7['permissions']);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<button\x20class=\x22btn-ghost\x20btn-small\x22\x20style=\x22font-weight:\x20600;\x20padding:\x200;\x20text-decoration:\x20underline;\x20text-decoration-style:\x20dotted;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20onclick=\x22window.openRoleModal(\x27'+_0x355ec7['id']+'\x27)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+Utils['escapeHtml'](_0x355ec7['name'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x355ec7['description']?'<div\x20style=\x22font-size:\x200.8em;\x20color:\x20var(--color-text-secondary);\x20margin-top:\x200.15rem;\x22>'+Utils['escapeHtml'](_0x355ec7['description'])+'</div>':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td><span\x20class=\x22tag\x22\x20style=\x22'+_0x477e90+'\x22>'+_0x51d5d6+'</span></td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+_0x3e5d63+'</td>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<td>'+(_0x32f889===0x1&&_0x355ec7['permissions'][0x0]==='*'?'All\x20permissions':_0x32f889+'\x20permission'+(_0x32f889===0x1?'':'s'))+'</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>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20class=\x22btn-secondary\x20btn-small\x22\x20onclick=\x22window.openRoleModal(\x27'+_0x355ec7['id']+'\x27)\x22>View'+(_0x16342e?'/Edit':'')+'</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(_0x16342e&&!_0x355ec7['predefined']?'<button\x20class=\x22btn-ghost\x20btn-small\x22\x20onclick=\x22window.deleteRole(\x27'+_0x355ec7['id']+'\x27)\x22>Delete</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']('');}window['openRoleModal']=function(_0x5f1782){const _0x3b7073=state['roles']['find'](_0x185826=>_0x185826['id']===_0x5f1782);if(!_0x3b7073)return;const _0x32ec11=Permissions['hasServerPermission'](state['currentUser'],'*'),_0x3e9a8a=_0x32ec11&&!_0x3b7073['predefined'];state['editingRoleId']=_0x5f1782,document['getElementById']('role-modal-title')['textContent']=_0x3b7073['name'],document['getElementById']('role-name')['value']=_0x3b7073['name'],document['getElementById']('role-name')['disabled']=!_0x3e9a8a,document['getElementById']('role-description')['value']=_0x3b7073['description']||'',document['getElementById']('role-description')['disabled']=!_0x3e9a8a,document['getElementById']('role-form-error')['hidden']=!![],document['getElementById']('save-role')['hidden']=!_0x3e9a8a;const _0x617fa2=document['getElementById']('role-readonly-notice');_0x617fa2['hidden']=_0x3e9a8a,renderPermissionsChecklist('permissions-checklist',_0x3b7073['permissions'],_0x3e9a8a),_0x3e9a8a?state['editModalSnapshot']={'name':_0x3b7073['name'],'description':_0x3b7073['description']||'','permissions':[..._0x3b7073['permissions']||[]]['sort']()}:state['editModalSnapshot']=null,document['getElementById']('role-modal')['hidden']=![];};function isRoleModalDirty(){if(!state['editModalSnapshot'])return![];const _0x128aac=document['getElementById']('role-name')['value']['trim'](),_0x49d25e=document['getElementById']('role-description')['value']['trim'](),_0xd5e30c=getCheckedPermissions('permissions-checklist')['sort']();return _0x128aac!==state['editModalSnapshot']['name']||_0x49d25e!==state['editModalSnapshot']['description']||JSON['stringify'](_0xd5e30c)!==JSON['stringify'](state['editModalSnapshot']['permissions']);}function requestHideRoleModal(){if(isRoleModalDirty()){if(!confirm('You\x20have\x20unsaved\x20changes.\x20Discard\x20them?'))return;}hideRoleModal();}function hideRoleModal(){document['getElementById']('role-modal')['hidden']=!![],state['editingRoleId']=null,state['editModalSnapshot']=null;const _0x365f01=document['getElementById']('save-role');_0x365f01['disabled']=![],_0x365f01['textContent']='Save\x20Role';}function showCreateRoleModal(){document['getElementById']('new-role-name')['value']='',document['getElementById']('new-role-description')['value']='',document['getElementById']('create-role-error')['hidden']=!![],renderPermissionsChecklist('new-permissions-checklist',[],!![]),document['getElementById']('create-role-modal')['hidden']=![],setTimeout(()=>document['getElementById']('new-role-name')['focus'](),0x64);}function hideCreateRoleModal(){document['getElementById']('create-role-modal')['hidden']=!![];const _0x3ef28c=document['getElementById']('save-new-role');_0x3ef28c['disabled']=![],_0x3ef28c['textContent']='Create\x20Role';}function renderPermissionsChecklist(_0x102037,_0x4f22b9,_0x1f851a){const _0x2bac45=document['getElementById'](_0x102037);if(!_0x2bac45)return;const _0xe33759=_0x4f22b9['includes']('*');if(_0xe33759){_0x2bac45['innerHTML']='<p\x20style=\x22font-size:\x200.875rem;\x20color:\x20var(--color-text-secondary);\x22>This\x20role\x20has\x20<strong>all\x20permissions</strong>\x20(wildcard).</p>';return;}const _0x27e971=['environment','server','team','user'],_0x5af2a9={'environment':'Environment-Scoped','server':'Server-Scoped','team':'Team-Scoped','user':'User-Scoped'},_0x2eab72={'environment':'These\x20permissions\x20are\x20granted\x20via\x20bindings\x20and\x20apply\x20only\x20to\x20bound\x20environments.','server':'These\x20permissions\x20apply\x20server-wide\x20and\x20are\x20typically\x20for\x20admin\x20functions.','team':'These\x20permissions\x20apply\x20to\x20team\x20management.','user':'These\x20permissions\x20apply\x20to\x20the\x20user\x27s\x20own\x20resources\x20regardless\x20of\x20bindings.'},_0x17eebf={};for(const _0x4ed7c7 of state['availablePermissions']){const _0x4600f6=_0x4ed7c7['scope']||'environment',_0xdde6a5=_0x4ed7c7['category']||_0x4ed7c7['key']['split'](':')[0x0];if(!_0x17eebf[_0x4600f6])_0x17eebf[_0x4600f6]={};if(!_0x17eebf[_0x4600f6][_0xdde6a5])_0x17eebf[_0x4600f6][_0xdde6a5]=[];_0x17eebf[_0x4600f6][_0xdde6a5]['push'](_0x4ed7c7);}const _0x47a147=new Set(_0x4f22b9),_0x54103d='\x0a\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.8rem;\x20color:\x20var(--color-text-secondary);\x20background:\x20var(--color-surface);\x20border:\x201px\x20solid\x20var(--color-border);\x20border-radius:\x206px;\x20padding:\x200.6rem\x200.75rem;\x20margin-bottom:\x201rem;\x22>\x0a\x20\x20\x20\x20\x20\x20<strong\x20style=\x22color:\x20var(--color-text);\x22>Scope\x20mixing:</strong>\x0a\x20\x20\x20\x20\x20\x20A\x20role\x20can\x20mix\x20permissions\x20of\x20each\x20scope\x20type—environment,\x20user,\x20server,\x20team—with\x20one\x20exception:\x20a\x20role\x20cannot\x20include\x20both\x20a\x20team\x20permission\x20and\x20an\x20environment\x20permission.\x0a\x20\x20\x20\x20</div>',_0x130b58=_0x27e971['filter'](_0x4306fc=>_0x17eebf[_0x4306fc])['map'](_0xff02c9=>{const _0x383f74=_0x17eebf[_0xff02c9],_0x2a5f51=SCOPE_CONFIG[_0xff02c9],_0x1b38a9=Object['entries'](_0x383f74)['map'](([_0x3cd9f7,_0x3cded8])=>{const _0x11453a=PERMISSION_CATEGORIES[_0x3cd9f7]||_0x3cd9f7,_0x1bb19d=_0x3cded8['map'](_0x30e25e=>{const _0x24e84f=_0x47a147['has'](_0x30e25e['key'])?'checked':'',_0x4b6a01=_0x1f851a?'':'disabled';return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20style=\x22display:\x20flex;\x20align-items:\x20flex-start;\x20gap:\x200.5rem;\x20padding:\x200.2rem\x200;\x20cursor:\x20'+(_0x1f851a?'pointer':'default')+';\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20value=\x22'+_0x30e25e['key']+'\x22\x20'+_0x24e84f+'\x20'+_0x4b6a01+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22margin-top:\x200.2rem;\x20flex-shrink:\x200;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22perm-checkbox\x22\x20data-container=\x22'+_0x102037+'\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.8rem;\x20font-family:\x20monospace;\x20color:\x20var(--color-primary);\x22>'+Utils['escapeHtml'](_0x30e25e['key'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.78rem;\x20color:\x20var(--color-text-secondary);\x20margin-left:\x200.5rem;\x22>'+Utils['escapeHtml'](_0x30e25e['description'])+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>';})['join']('');return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-bottom:\x200.75rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.75rem;\x20font-weight:\x20700;\x20text-transform:\x20uppercase;\x20letter-spacing:\x200.05em;\x20color:\x20var(--color-text-secondary);\x20margin-bottom:\x200.35rem;\x22>'+Utils['escapeHtml'](_0x11453a)+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x1bb19d+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>';})['join']('');return'\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-bottom:\x201.25rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20align-items:\x20center;\x20gap:\x200.5rem;\x20margin-bottom:\x200.15rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:\x200.8rem;\x20font-weight:\x20700;\x20color:\x20'+_0x2a5f51['color']+';\x22>'+_0x5af2a9[_0xff02c9]+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22tag\x22\x20style=\x22background:\x20'+_0x2a5f51['bg']+';\x20color:\x20'+_0x2a5f51['color']+';\x20font-size:\x200.65rem;\x22>'+_0x2a5f51['label']+'</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x200.75rem;\x20color:\x20var(--color-text-secondary);\x20margin-bottom:\x200.5rem;\x22>'+_0x2eab72[_0xff02c9]+'</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22border-left:\x202px\x20solid\x20'+_0x2a5f51['color']+';\x20padding-left:\x200.75rem;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x1b38a9+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>';})['join']('');_0x2bac45['innerHTML']=_0x54103d+_0x130b58;}function getCheckedPermissions(_0x57e599){const _0x610896=document['getElementById'](_0x57e599);if(!_0x610896)return[];return Array['from'](_0x610896['querySelectorAll']('.perm-checkbox:checked'))['map'](_0xaa6745=>_0xaa6745['value']);}async function saveRole(){const _0x22357e=document['getElementById']('role-name')['value']['trim'](),_0x258cdf=document['getElementById']('role-description')['value']['trim'](),_0x3383b7=getCheckedPermissions('permissions-checklist'),_0x16e64d=document['getElementById']('role-form-error'),_0x911692=document['getElementById']('save-role');if(!_0x22357e){_0x16e64d['textContent']='Role\x20name\x20is\x20required',_0x16e64d['hidden']=![];return;}if(_0x3383b7['length']===0x0){_0x16e64d['textContent']='Select\x20at\x20least\x20one\x20permission',_0x16e64d['hidden']=![];return;}_0x16e64d['hidden']=!![];const _0x24f270=_0x911692['textContent'];_0x911692['disabled']=!![],_0x911692['textContent']='Saving…';try{const {role:_0x2fc12f}=await API['updateRoleDefinition'](state['editingRoleId'],{'name':_0x22357e,'description':_0x258cdf,'permissions':_0x3383b7}),_0x1ddd91=state['roles']['findIndex'](_0x458649=>_0x458649['id']===_0x2fc12f['id']);if(_0x1ddd91>=0x0)state['roles'][_0x1ddd91]=_0x2fc12f;renderRoles(),Utils['showToast']('Role\x20updated','success'),hideRoleModal();}catch(_0x1ce430){_0x16e64d['textContent']=_0x1ce430['message'],_0x16e64d['hidden']=![],_0x911692['disabled']=![],_0x911692['textContent']=_0x24f270;}}async function createRole(){const _0x1dac75=document['getElementById']('new-role-name')['value']['trim'](),_0x589e43=document['getElementById']('new-role-description')['value']['trim'](),_0x574ae6=getCheckedPermissions('new-permissions-checklist'),_0x46c357=document['getElementById']('create-role-error'),_0xfc5346=document['getElementById']('save-new-role');if(!_0x1dac75){_0x46c357['textContent']='Role\x20name\x20is\x20required',_0x46c357['hidden']=![];return;}if(_0x574ae6['length']===0x0){_0x46c357['textContent']='Select\x20at\x20least\x20one\x20permission',_0x46c357['hidden']=![];return;}_0x46c357['hidden']=!![];const _0x475cf8=_0xfc5346['textContent'];_0xfc5346['disabled']=!![],_0xfc5346['textContent']='Creating…';try{const {role:_0x558a06}=await API['createRoleDefinition']({'name':_0x1dac75,'description':_0x589e43,'permissions':_0x574ae6});state['roles']['push'](_0x558a06),renderRoles(),Utils['showToast']('Role\x20created','success'),hideCreateRoleModal();}catch(_0x1fcc02){_0x46c357['textContent']=_0x1fcc02['message'],_0x46c357['hidden']=![],_0xfc5346['disabled']=![],_0xfc5346['textContent']=_0x475cf8;}}window['deleteRole']=function(_0x18fac6){const _0x1458c0=state['roles']['find'](_0xe4499a=>_0xe4499a['id']===_0x18fac6);if(!_0x1458c0)return;state['deletingRoleId']=_0x18fac6,document['getElementById']('delete-role-name')['textContent']=_0x1458c0['name'],document['getElementById']('delete-role-modal')['hidden']=![];};function hideDeleteRoleModal(){document['getElementById']('delete-role-modal')['hidden']=!![],state['deletingRoleId']=null;const _0x3a58dd=document['getElementById']('confirm-delete-role');_0x3a58dd['disabled']=![],_0x3a58dd['textContent']='Delete\x20Role';}async function confirmDeleteRole(){if(!state['deletingRoleId'])return;const _0x5b18d8=document['getElementById']('confirm-delete-role');_0x5b18d8['disabled']=!![],_0x5b18d8['textContent']='Deleting…';try{await API['deleteRoleDefinition'](state['deletingRoleId']),state['roles']=state['roles']['filter'](_0x5f08cd=>_0x5f08cd['id']!==state['deletingRoleId']),renderRoles(),Utils['showToast']('Role\x20deleted','success'),hideDeleteRoleModal();}catch(_0xb6995a){Utils['showToast']('Failed\x20to\x20delete\x20role:\x20'+_0xb6995a['message'],'error'),_0x5b18d8['disabled']=![],_0x5b18d8['textContent']='Delete\x20Role';}}function bindEventListeners(){document['getElementById']('create-role-btn')?.['addEventListener']('click',showCreateRoleModal),document['getElementById']('retry-roles-btn')?.['addEventListener']('click',loadRoles),document['getElementById']('close-role-modal')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('cancel-role')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('save-role')?.['addEventListener']('click',saveRole),document['querySelector']('#role-modal\x20.modal-overlay')?.['addEventListener']('click',requestHideRoleModal),document['getElementById']('close-create-role-modal')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('cancel-create-role')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('save-new-role')?.['addEventListener']('click',createRole),document['querySelector']('#create-role-modal\x20.modal-overlay')?.['addEventListener']('click',hideCreateRoleModal),document['getElementById']('close-delete-role-modal')?.['addEventListener']('click',hideDeleteRoleModal),document['getElementById']('cancel-delete-role')?.['addEventListener']('click',hideDeleteRoleModal),document['getElementById']('confirm-delete-role')?.['addEventListener']('click',confirmDeleteRole),document['querySelector']('#delete-role-modal\x20.modal-overlay')?.['addEventListener']('click',hideDeleteRoleModal);}
|
|
@@ -179,6 +179,25 @@
|
|
|
179
179
|
</svg>
|
|
180
180
|
Email (SMTP)
|
|
181
181
|
</button>
|
|
182
|
+
<button class="settings-nav-item" data-section="slack" role="tab">
|
|
183
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
184
|
+
<path d="M14.5 10c-.83 0-1.5-.67-1.5-1.5v-5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5v5c0 .83-.67 1.5-1.5 1.5z"></path>
|
|
185
|
+
<path d="M20.5 10H19V8.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path>
|
|
186
|
+
<path d="M9.5 14c.83 0 1.5.67 1.5 1.5v5c0 .83-.67 1.5-1.5 1.5S8 21.33 8 20.5v-5c0-.83.67-1.5 1.5-1.5z"></path>
|
|
187
|
+
<path d="M3.5 14H5v1.5c0 .83-.67 1.5-1.5 1.5S2 16.33 2 15.5 2.67 14 3.5 14z"></path>
|
|
188
|
+
<path d="M14 14.5c0-.83.67-1.5 1.5-1.5h5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-5c-.83 0-1.5-.67-1.5-1.5z"></path>
|
|
189
|
+
<path d="M15.5 19H14v1.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></path>
|
|
190
|
+
<path d="M10 9.5C10 10.33 9.33 11 8.5 11h-5C2.67 11 2 10.33 2 9.5S2.67 8 3.5 8h5c.83 0 1.5.67 1.5 1.5z"></path>
|
|
191
|
+
<path d="M8.5 5H10V3.5C10 2.67 9.33 2 8.5 2S7 2.67 7 3.5 7.67 5 8.5 5z"></path>
|
|
192
|
+
</svg>
|
|
193
|
+
Slack
|
|
194
|
+
</button>
|
|
195
|
+
<button class="settings-nav-item" data-section="jira" role="tab">
|
|
196
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
197
|
+
<path d="M11.571 11.513H0a5.218 5.218 0 0 0 5.232 5.215h2.13v2.057A5.215 5.215 0 0 0 12.575 24V12.518a1.005 1.005 0 0 0-1.005-1.005zm5.723-5.756H5.736a5.215 5.215 0 0 0 5.215 5.214h2.129v2.058a5.218 5.218 0 0 0 5.215 5.214V6.758a1.001 1.001 0 0 0-1.001-1.001zM23.013 0H11.455a5.215 5.215 0 0 0 5.215 5.215h2.129v2.057A5.215 5.215 0 0 0 24 12.483V1.005A1.001 1.001 0 0 0 23.013 0z"></path>
|
|
198
|
+
</svg>
|
|
199
|
+
Jira
|
|
200
|
+
</button>
|
|
182
201
|
<button class="settings-nav-item" data-section="git-providers" role="tab">
|
|
183
202
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
184
203
|
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
|
@@ -564,6 +583,232 @@
|
|
|
564
583
|
</div>
|
|
565
584
|
</div>
|
|
566
585
|
|
|
586
|
+
<!-- Slack Settings -->
|
|
587
|
+
<div id="section-slack" class="settings-panel" role="tabpanel" hidden>
|
|
588
|
+
<div class="content-card">
|
|
589
|
+
<div class="card-header">
|
|
590
|
+
<h3>Slack Integration</h3>
|
|
591
|
+
</div>
|
|
592
|
+
<div class="card-body">
|
|
593
|
+
<div id="slack-inline-message" class="inline-message" hidden></div>
|
|
594
|
+
<p class="text-muted" style="margin-bottom: 8px;">Connect a Slack bot so users can @mention CoderFlow to create tasks directly from Slack.</p>
|
|
595
|
+
|
|
596
|
+
<!-- App Manifest Helper -->
|
|
597
|
+
<details id="slack-manifest-details" style="margin-bottom: 16px; border: 1px solid var(--color-border); border-radius: 6px; padding: 0;">
|
|
598
|
+
<summary style="padding: 10px 14px; cursor: pointer; font-weight: 500; font-size: 13px; user-select: none; list-style: none; display: flex; align-items: center; gap: 8px;">
|
|
599
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink: 0; transition: transform 0.2s;">
|
|
600
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
601
|
+
</svg>
|
|
602
|
+
Quick Setup: Create Slack App from Manifest
|
|
603
|
+
</summary>
|
|
604
|
+
<div style="padding: 0 14px 14px 14px; font-size: 13px;">
|
|
605
|
+
<ol style="margin: 8px 0 12px 0; padding-left: 20px; line-height: 1.8;">
|
|
606
|
+
<li>Go to <a href="https://api.slack.com/apps" target="_blank" rel="noopener">api.slack.com/apps</a> and click <strong>Create New App</strong> → <strong>From an app manifest</strong></li>
|
|
607
|
+
<li>Select your workspace, click <strong>Next</strong>, choose the <strong>JSON</strong> tab</li>
|
|
608
|
+
<li>Copy the manifest below and paste it in</li>
|
|
609
|
+
<li>Click <strong>Next</strong>, review, and <strong>Create</strong></li>
|
|
610
|
+
<li>Copy <strong>Signing Secret</strong> from Basic Information, and <strong>Bot Token</strong> from OAuth & Permissions (install the app first)</li>
|
|
611
|
+
</ol>
|
|
612
|
+
<div style="position: relative;">
|
|
613
|
+
<pre id="slack-manifest-pre" style="background: var(--color-surface-muted); color: var(--color-text); border: 1px solid var(--color-border); padding: 12px; border-radius: 4px; font-size: 12px; line-height: 1.5; overflow-x: auto; margin: 0; white-space: pre;"></pre>
|
|
614
|
+
<button type="button" id="slack-copy-manifest-btn" style="position: absolute; top: 8px; right: 8px; padding: 4px 10px; font-size: 12px; border-radius: 4px; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-text); cursor: pointer; opacity: 0.8; transition: opacity 0.15s;" title="Copy manifest to clipboard">Copy</button>
|
|
615
|
+
</div>
|
|
616
|
+
<p class="text-muted" style="margin-top: 8px; font-size: 12px;">The manifest uses the Task Link Base URL below as the server URL. Update that field first if needed.</p>
|
|
617
|
+
</div>
|
|
618
|
+
</details>
|
|
619
|
+
<div class="form-single-column">
|
|
620
|
+
<div class="form-row">
|
|
621
|
+
<label for="slack-enabled">Enabled</label>
|
|
622
|
+
<label class="toggle-switch">
|
|
623
|
+
<input type="checkbox" id="slack-enabled">
|
|
624
|
+
<span class="toggle-slider"></span>
|
|
625
|
+
</label>
|
|
626
|
+
</div>
|
|
627
|
+
<div class="form-row">
|
|
628
|
+
<label for="slack-bot-token">Bot Token</label>
|
|
629
|
+
<div class="apikey-input-group">
|
|
630
|
+
<input type="password" id="slack-bot-token" class="form-input" placeholder="xoxb-...">
|
|
631
|
+
<button type="button" class="btn-icon apikey-toggle-visibility" data-target="slack-bot-token" title="Toggle visibility">
|
|
632
|
+
<svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
633
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
|
634
|
+
<circle cx="12" cy="12" r="3"></circle>
|
|
635
|
+
</svg>
|
|
636
|
+
<svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
|
637
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
|
|
638
|
+
<line x1="1" y1="1" x2="23" y2="23"></line>
|
|
639
|
+
</svg>
|
|
640
|
+
</button>
|
|
641
|
+
</div>
|
|
642
|
+
<span id="slack-bot-token-status" class="form-hint"></span>
|
|
643
|
+
</div>
|
|
644
|
+
<div class="form-row">
|
|
645
|
+
<label for="slack-signing-secret">Signing Secret</label>
|
|
646
|
+
<div class="apikey-input-group">
|
|
647
|
+
<input type="password" id="slack-signing-secret" class="form-input" placeholder="Enter signing secret">
|
|
648
|
+
<button type="button" class="btn-icon apikey-toggle-visibility" data-target="slack-signing-secret" title="Toggle visibility">
|
|
649
|
+
<svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
650
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
|
651
|
+
<circle cx="12" cy="12" r="3"></circle>
|
|
652
|
+
</svg>
|
|
653
|
+
<svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
|
654
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
|
|
655
|
+
<line x1="1" y1="1" x2="23" y2="23"></line>
|
|
656
|
+
</svg>
|
|
657
|
+
</button>
|
|
658
|
+
</div>
|
|
659
|
+
<span id="slack-signing-secret-status" class="form-hint"></span>
|
|
660
|
+
</div>
|
|
661
|
+
<div class="form-row">
|
|
662
|
+
<label for="slack-app-id">App ID</label>
|
|
663
|
+
<input type="text" id="slack-app-id" class="form-input" placeholder="A0123456789" style="max-width: 200px;">
|
|
664
|
+
<span class="form-hint">Found in your Slack app's Basic Information page</span>
|
|
665
|
+
</div>
|
|
666
|
+
<div class="form-row">
|
|
667
|
+
<label for="slack-default-environment">Default Environment</label>
|
|
668
|
+
<select id="slack-default-environment" class="form-input" style="max-width: 300px;">
|
|
669
|
+
<option value="">None (require env: prefix or channel mapping)</option>
|
|
670
|
+
</select>
|
|
671
|
+
<span class="form-hint">Used when no channel mapping or env: prefix is specified</span>
|
|
672
|
+
</div>
|
|
673
|
+
<div class="form-row">
|
|
674
|
+
<label for="slack-task-link-base-url">Task Link Base URL</label>
|
|
675
|
+
<input type="text" id="slack-task-link-base-url" class="form-input" placeholder="Leave blank to use current server URL">
|
|
676
|
+
<span class="form-hint">Base URL for task links posted in Slack (defaults to this server's URL if blank)</span>
|
|
677
|
+
</div>
|
|
678
|
+
</div>
|
|
679
|
+
|
|
680
|
+
<!-- Channel Mappings -->
|
|
681
|
+
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
|
|
682
|
+
<div class="subsection-header" style="margin-bottom: 12px;">
|
|
683
|
+
<h4 style="margin: 0;">Channel Mappings</h4>
|
|
684
|
+
</div>
|
|
685
|
+
<p class="text-muted" style="margin-bottom: 12px;">Map Slack channels to specific environments. Messages in mapped channels auto-select the configured environment.</p>
|
|
686
|
+
<div id="slack-channel-mappings-container">
|
|
687
|
+
<!-- Dynamic rows inserted here -->
|
|
688
|
+
</div>
|
|
689
|
+
<button type="button" class="btn-secondary btn-small" id="slack-add-mapping-btn" style="margin-top: 8px;">
|
|
690
|
+
+ Add Channel Mapping
|
|
691
|
+
</button>
|
|
692
|
+
</div>
|
|
693
|
+
|
|
694
|
+
<!-- Test Connection -->
|
|
695
|
+
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
|
|
696
|
+
<div class="subsection-header" style="margin-bottom: 12px;">
|
|
697
|
+
<h4 style="margin: 0;">Test Configuration</h4>
|
|
698
|
+
</div>
|
|
699
|
+
<div class="form-single-column">
|
|
700
|
+
<div class="form-row">
|
|
701
|
+
<label></label>
|
|
702
|
+
<button type="button" class="btn-secondary btn-small" id="slack-test-connection-btn">
|
|
703
|
+
Test Connection
|
|
704
|
+
</button>
|
|
705
|
+
</div>
|
|
706
|
+
<div class="form-row" id="slack-test-result-row" hidden>
|
|
707
|
+
<label></label>
|
|
708
|
+
<div id="slack-test-result" class="email-test-result"></div>
|
|
709
|
+
</div>
|
|
710
|
+
</div>
|
|
711
|
+
</div>
|
|
712
|
+
</div>
|
|
713
|
+
<div class="card-actions">
|
|
714
|
+
<button type="button" class="btn-primary" id="save-slack-btn">Save</button>
|
|
715
|
+
</div>
|
|
716
|
+
</div>
|
|
717
|
+
</div>
|
|
718
|
+
|
|
719
|
+
<!-- Jira Settings -->
|
|
720
|
+
<div id="section-jira" class="settings-panel" role="tabpanel" hidden>
|
|
721
|
+
<div class="content-card">
|
|
722
|
+
<div class="card-header">
|
|
723
|
+
<h3>Jira Integration</h3>
|
|
724
|
+
</div>
|
|
725
|
+
<div class="card-body">
|
|
726
|
+
<div id="jira-inline-message" class="inline-message" hidden></div>
|
|
727
|
+
<p class="text-muted" style="margin-bottom: 16px;">Connect to Jira so users can import issues as tasks and post results back as comments.</p>
|
|
728
|
+
|
|
729
|
+
<div class="form-single-column">
|
|
730
|
+
<div class="form-row">
|
|
731
|
+
<label for="jira-enabled">Enabled</label>
|
|
732
|
+
<label class="toggle-switch">
|
|
733
|
+
<input type="checkbox" id="jira-enabled">
|
|
734
|
+
<span class="toggle-slider"></span>
|
|
735
|
+
</label>
|
|
736
|
+
</div>
|
|
737
|
+
<div class="form-row">
|
|
738
|
+
<label for="jira-account-type">Account Type</label>
|
|
739
|
+
<select id="jira-account-type" class="form-input" style="max-width: 300px;">
|
|
740
|
+
<option value="personal">Personal account</option>
|
|
741
|
+
<option value="service">Service account (Cloud ID)</option>
|
|
742
|
+
</select>
|
|
743
|
+
<span class="form-hint">Service accounts use api.atlassian.com with a Cloud ID for API routing</span>
|
|
744
|
+
</div>
|
|
745
|
+
<div class="form-row">
|
|
746
|
+
<label for="jira-base-url">Jira Site URL</label>
|
|
747
|
+
<input type="text" id="jira-base-url" class="form-input" placeholder="https://your-company.atlassian.net">
|
|
748
|
+
<span class="form-hint">Your Jira instance URL (used for browse links and API calls)</span>
|
|
749
|
+
</div>
|
|
750
|
+
<div class="form-row" id="jira-cloud-id-row" hidden>
|
|
751
|
+
<label for="jira-cloud-id">Cloud ID</label>
|
|
752
|
+
<div style="display: flex; gap: 8px; align-items: center;">
|
|
753
|
+
<input type="text" id="jira-cloud-id" class="form-input" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" style="max-width: 400px;">
|
|
754
|
+
<button type="button" class="btn-secondary btn-small" id="jira-fetch-cloud-id-btn">Fetch</button>
|
|
755
|
+
</div>
|
|
756
|
+
<span id="jira-cloud-id-hint" class="form-hint">Enter the Site URL above, then click <strong>Fetch</strong> to auto-detect, or enter manually</span>
|
|
757
|
+
</div>
|
|
758
|
+
<div class="form-row">
|
|
759
|
+
<label for="jira-email">Email</label>
|
|
760
|
+
<input type="email" id="jira-email" class="form-input" placeholder="account@example.com">
|
|
761
|
+
<span class="form-hint">The email address associated with the Jira account</span>
|
|
762
|
+
</div>
|
|
763
|
+
<div class="form-row">
|
|
764
|
+
<label for="jira-api-token">API Token</label>
|
|
765
|
+
<div class="apikey-input-group">
|
|
766
|
+
<input type="password" id="jira-api-token" class="form-input" placeholder="Enter API token">
|
|
767
|
+
<button type="button" class="btn-icon apikey-toggle-visibility" data-target="jira-api-token" title="Toggle visibility">
|
|
768
|
+
<svg class="eye-open" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
769
|
+
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
|
770
|
+
<circle cx="12" cy="12" r="3"></circle>
|
|
771
|
+
</svg>
|
|
772
|
+
<svg class="eye-closed" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
|
773
|
+
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
|
|
774
|
+
<line x1="1" y1="1" x2="23" y2="23"></line>
|
|
775
|
+
</svg>
|
|
776
|
+
</button>
|
|
777
|
+
</div>
|
|
778
|
+
<span id="jira-api-token-status" class="form-hint"></span>
|
|
779
|
+
</div>
|
|
780
|
+
</div>
|
|
781
|
+
|
|
782
|
+
<!-- Test Connection -->
|
|
783
|
+
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
|
|
784
|
+
<div class="subsection-header" style="margin-bottom: 12px;">
|
|
785
|
+
<h4 style="margin: 0;">Test Configuration</h4>
|
|
786
|
+
</div>
|
|
787
|
+
<div class="form-single-column">
|
|
788
|
+
<div class="form-row">
|
|
789
|
+
<label></label>
|
|
790
|
+
<div style="display: flex; gap: 8px;">
|
|
791
|
+
<button type="button" class="btn-secondary btn-small" id="jira-test-connection-btn">
|
|
792
|
+
Test Connection
|
|
793
|
+
</button>
|
|
794
|
+
<button type="button" class="btn-secondary btn-small" id="jira-disconnect-btn" style="color: var(--color-danger, #dc3545);" hidden>
|
|
795
|
+
Disconnect
|
|
796
|
+
</button>
|
|
797
|
+
</div>
|
|
798
|
+
</div>
|
|
799
|
+
<div class="form-row" id="jira-test-result-row" hidden>
|
|
800
|
+
<label></label>
|
|
801
|
+
<div id="jira-test-result" class="email-test-result"></div>
|
|
802
|
+
</div>
|
|
803
|
+
</div>
|
|
804
|
+
</div>
|
|
805
|
+
</div>
|
|
806
|
+
<div class="card-actions">
|
|
807
|
+
<button type="button" class="btn-primary" id="save-jira-btn">Save</button>
|
|
808
|
+
</div>
|
|
809
|
+
</div>
|
|
810
|
+
</div>
|
|
811
|
+
|
|
567
812
|
<!-- Git Providers Settings -->
|
|
568
813
|
<div id="section-git-providers" class="settings-panel" role="tabpanel" hidden>
|
|
569
814
|
<div class="content-card">
|