@sparkelf/dsh-client-ui-skill-center 0.2.1-rc.2.4 → 0.2.2-alpha.2.2
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/lib/client.js +1610 -233
- package/lib/types/client/ConnectorsTab.d.ts +37 -0
- package/lib/types/client/api.d.ts +52 -0
- package/lib/types/client/connectors.d.ts +118 -0
- package/lib/types/client/locales.d.ts +51 -0
- package/lib/types/client/plaza.d.ts +37 -0
- package/lib/types/client/review.d.ts +36 -0
- package/lib/types/client/scope.d.ts +69 -0
- package/package.json +42 -42
- package/LICENSE +0 -21
package/lib/client.js
CHANGED
|
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
//#region \0dsh-css:/root/projects/deepseek-harness-plus/packages/plus/ui-skill-center/src/client/SkillCenterPage.module.css.mjs
|
|
11
|
-
const css = ".DGiSta_page{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex-direction:column;align-items:center;gap:16px;padding:24px clamp(24px,4vw,40px) 40px;display:flex;overflow:auto}.DGiSta_page>*{width:100%;max-width:960px}.DGiSta_pageHead{justify-content:space-between;align-items:center;gap:16px;display:flex}.DGiSta_pageTitle{margin:0;font-size:20px;font-weight:500;line-height:28px}.DGiSta_toolbar{justify-content:flex-end;align-items:center;gap:16px;display:flex}.DGiSta_iconButton{width:28px;height:28px;color:var(--dsw-alias-label-caption);cursor:pointer;background:0 0;border:0;border-radius:28px;justify-content:center;align-items:center;display:inline-flex}.DGiSta_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.DGiSta_iconButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.DGiSta_iconWrap{display:inline-flex}.DGiSta_search{width:100%}.DGiSta_group{min-width:0}.DGiSta_groupTitle{align-items:baseline;gap:8px;margin:0 0 8px;font-size:14px;font-weight:500;line-height:20px;display:flex}.DGiSta_groupCount{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400}.DGiSta_cards{grid-template-columns:repeat(auto-fill,minmax(272px,1fr));align-items:start;gap:12px;margin:0;padding:0;list-style:none;display:grid}.DGiSta_card{border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:10px;flex-direction:column;align-self:start;gap:10px;min-width:0;padding:12px;display:flex}.DGiSta_cardHead{align-items:center;gap:10px;min-width:0;display:flex}.DGiSta_cardIcon{corner-shape:round;background:var(--dsw-alias-bg-layer-2);width:28px;height:28px;color:var(--dsw-alias-label-secondary);border-radius:50%;flex:none;place-items:center;display:grid}.DGiSta_cardForeign{opacity:.72}.DGiSta_workspaceBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);vertical-align:middle;border-radius:4px;margin-left:8px;padding:1px 6px;font-size:11px;font-weight:400;line-height:16px}.DGiSta_cardTitle{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.DGiSta_cardTitleRow{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.DGiSta_cardMarks{flex-wrap:wrap;gap:6px;margin-top:2px;display:flex}.DGiSta_mark{color:var(--dsw-alias-state-business-primary);white-space:nowrap;background:#ecf1fc;border:0;border-radius:4px;padding:2px 7px;font-size:11px;font-weight:500;line-height:16px}.DGiSta_markOff,.DGiSta_markDanger{background:#ecf1fc}.DGiSta_detail{flex-direction:column;gap:12px;margin:0;display:flex}.DGiSta_cardActions{flex:none;align-items:center;gap:4px;display:inline-flex}.DGiSta_detailRow{flex-direction:column;gap:2px;display:flex}.DGiSta_detailLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:16px}.DGiSta_detailValue{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}.DGiSta_cardEnd{flex:none;justify-content:space-between;align-items:center;gap:8px;margin-top:auto;padding-top:2px;display:flex}.DGiSta_cardBody{flex-direction:column;gap:6px;min-width:0;display:flex}.DGiSta_switch{background:var(--dsw-alias-border-l3);cursor:pointer;border:none;border-radius:10px;width:36px;height:20px;transition:background .12s;position:relative}.DGiSta_switch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.DGiSta_switchOn{background:var(--dsw-alias-state-success-primary)}.DGiSta_switch:after{content:\"\";corner-shape:round;background:var(--dsw-alias-bg-layer-1);border-radius:50%;width:16px;height:16px;transition:transform .12s;position:absolute;top:2px;left:2px}.DGiSta_switchOn:after{transform:translate(16px)}.DGiSta_dialog{width:min(560px,100%)}.DGiSta_form{flex-direction:column;gap:12px;display:flex}.DGiSta_field{flex-direction:column;gap:4px;display:flex}.DGiSta_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.DGiSta_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:32px;color:var(--dsw-alias-label-primary);background:0 0;border-radius:8px;padding:0 10px;font-size:13px}.DGiSta_textarea{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);min-height:80px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-code-block-small);resize:vertical;background:0 0;border-radius:8px;padding:8px 10px;font-size:12px}.DGiSta_status{text-align:center;color:var(--dsw-alias-label-tertiary);padding:32px 0;font-size:13px}.DGiSta_statusError{color:var(--dsw-alias-state-error-primary)}.DGiSta_cardSummary{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.DGiSta_body{flex-direction:column;gap:4px;min-width:0;margin-top:16px;display:flex}.DGiSta_bodyLabel{color:var(--dsw-alias-label-caption);margin:0;font-size:11px;font-weight:500;line-height:16px}.DGiSta_bodyPre{background:var(--dsw-alias-markdown-code-block);max-height:46vh;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-code-block-small-font-family);font-size:var(--dsw-font-markdown-code-block-small-font-size);line-height:var(--dsw-font-markdown-code-block-small-line-height);white-space:pre-wrap;overflow-wrap:anywhere;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:8px;margin:0;padding:12px;overflow:auto}.DGiSta_bodyStatus{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.DGiSta_bodyError{color:var(--dsw-alias-state-error-primary);}.DGiSta_progressRow{align-items:center;gap:8px;margin-bottom:12px;display:flex}.DGiSta_progressLabel{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px;line-height:18px}.DGiSta_progressTrack{background:var(--dsw-alias-border-l2);border-radius:2px;flex:1;height:4px;overflow:hidden}.DGiSta_progressFill{background:var(--dsw-alias-label-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.DGiSta_progressCount{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:18px}";
|
|
11
|
+
const css = ".DGiSta_page{box-sizing:border-box;width:100%;height:100%;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);padding:0 0 48px;overflow:auto}.DGiSta_pageContent{width:100%;max-width:960px;margin:0 auto;padding:0 clamp(24px,4vw,48px)}.DGiSta_pageHead{justify-content:space-between;align-items:center;gap:16px;margin-bottom:24px;padding-top:28px;display:flex}.DGiSta_pageTitle{margin:0;font-size:20px;font-weight:500;line-height:28px}.DGiSta_toolbar{justify-content:flex-end;align-items:center;gap:16px;display:flex}.DGiSta_iconButton{width:28px;height:28px;color:var(--dsw-alias-label-caption);cursor:pointer;background:0 0;border:0;border-radius:28px;justify-content:center;align-items:center;display:inline-flex}.DGiSta_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.DGiSta_iconButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.DGiSta_iconWrap{display:inline-flex}.DGiSta_tabs{flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:14px;display:flex}.DGiSta_tab{height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:14px;flex:none;align-items:center;gap:6px;padding:0 10px;font-size:14px;line-height:22px;display:inline-flex}@media (hover:hover){.DGiSta_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}}.DGiSta_tab:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}.DGiSta_tabActive{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.DGiSta_tabCount{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.DGiSta_tabActive .DGiSta_tabCount{color:var(--dsw-alias-label-secondary)}.DGiSta_searchField{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);width:100%;height:36px;color:var(--dsw-alias-label-tertiary);border-radius:12px;align-items:center;gap:4px;margin:0 0 16px;padding:0 10px;transition:border-color .15s;display:flex}@media (hover:hover){.DGiSta_searchField:hover{border-color:var(--dsw-alias-border-l2)}}.DGiSta_searchField:focus-within{border-color:var(--dsw-alias-state-business-primary)}.DGiSta_searchField>:first-child{background:0 0;border:0;border-radius:0;flex:1;min-width:0;height:100%;padding:0}.DGiSta_searchField>:first-child:focus-within{border-color:#0000}.DGiSta_searchField>:first-child svg{width:14px;height:14px}.DGiSta_searchField input::placeholder{color:var(--dsw-alias-label-caption)}.DGiSta_searchField input:focus-visible{outline:none}.DGiSta_searchField input::-webkit-search-cancel-button{display:none}.DGiSta_searchClear{width:28px;height:28px;color:var(--dsw-alias-label-tertiary);flex:none;margin-right:-6px;padding:0}.DGiSta_tabPanel,.DGiSta_plazaPanel,.DGiSta_group{min-width:0}.DGiSta_groupTitle{align-items:baseline;gap:8px;margin:0 0 8px;font-size:14px;font-weight:500;line-height:20px;display:flex}.DGiSta_groupCount{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400}.DGiSta_cards{grid-template-columns:repeat(auto-fill,minmax(272px,1fr));align-content:start;align-items:stretch;gap:12px;margin:0;padding:0;list-style:none;display:grid}.DGiSta_card{border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:10px;flex-direction:column;gap:10px;min-width:0;min-height:0;padding:12px;display:flex}.DGiSta_cardHead{align-items:center;gap:10px;min-width:0;display:flex}.DGiSta_cardIcon{corner-shape:round;background:var(--dsw-alias-bg-layer-2);width:28px;height:28px;color:var(--dsw-alias-label-secondary);border-radius:50%;flex:none;place-items:center;display:grid}.DGiSta_cardForeign{opacity:.72}.DGiSta_workspaceBadge{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);vertical-align:middle;border-radius:4px;margin-left:8px;padding:1px 6px;font-size:11px;font-weight:400;line-height:16px}.DGiSta_cardTitle{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.DGiSta_cardTitleRow{flex:1;align-items:center;gap:8px;min-width:0;min-height:26px;display:flex}.DGiSta_cardMarks{flex-wrap:wrap;gap:6px;min-height:18px;margin-top:2px;display:flex}.DGiSta_mark{color:var(--dsw-alias-state-business-primary);white-space:nowrap;background:#ecf1fc;border:0;border-radius:4px;padding:2px 7px;font-size:11px;font-weight:500;line-height:16px}.DGiSta_markOff,.DGiSta_markDanger{background:#ecf1fc}.DGiSta_detail{flex-direction:column;gap:12px;margin:0;display:flex}.DGiSta_cardActions{flex:none;align-items:center;gap:4px;display:inline-flex}.DGiSta_cardActions button{border-radius:6px;justify-content:center;align-items:center;height:28px;min-height:28px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.DGiSta_detailRow{flex-direction:column;gap:2px;display:flex}.DGiSta_detailLabel{color:var(--dsw-alias-label-caption);font-size:11px;line-height:16px}.DGiSta_detailValue{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0;font-size:12px;line-height:18px}.DGiSta_cardEnd{flex:none;justify-content:space-between;align-items:center;gap:8px;margin-top:auto;padding-top:2px;display:flex}.DGiSta_cardBody{flex-direction:column;gap:6px;min-width:0;display:flex}.DGiSta_switch{background:var(--dsw-alias-border-l3);cursor:pointer;border:none;border-radius:10px;width:36px;height:20px;transition:background .12s;position:relative}.DGiSta_switch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.DGiSta_switchOn{background:var(--dsw-alias-state-success-primary)}.DGiSta_switch:after{content:\"\";corner-shape:round;background:var(--dsw-alias-bg-layer-1);border-radius:50%;width:16px;height:16px;transition:transform .12s;position:absolute;top:2px;left:2px}.DGiSta_switchOn:after{transform:translate(16px)}.DGiSta_dialog{color-scheme:light;width:min(560px,100%)}body[data-ds-dark-theme] .DGiSta_dialog{color-scheme:dark}.DGiSta_publishDialog.DGiSta_publishDialog{color-scheme:light;gap:0;width:min(720px,100vw - 32px);max-width:100%;max-height:min(82vh,760px);padding:0 0 20px}body[data-ds-dark-theme] .DGiSta_publishDialog.DGiSta_publishDialog{color-scheme:dark}.DGiSta_dialogHeader{flex:none;justify-content:space-between;align-items:center;gap:8px;padding:22px 24px 12px;display:flex}.DGiSta_dialogTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.DGiSta_dialogClose{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;display:inline-flex}.DGiSta_dialogClose:hover{background:var(--dsw-alias-interactive-bg-hover)}.DGiSta_dialogClose:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}.DGiSta_dialogBody{overscroll-behavior:contain;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex:1;min-height:0;padding:0 24px;overflow-y:auto}.DGiSta_dialogFooter{flex:none;justify-content:flex-end;align-items:center;gap:8px;padding:16px 24px 0;display:flex}.DGiSta_dialogBody .DGiSta_textarea{min-height:200px}.DGiSta_form{flex-direction:column;gap:12px;display:flex}.DGiSta_field{flex-direction:column;gap:4px;display:flex}.DGiSta_fieldLabel{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.DGiSta_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:32px;color:var(--dsw-alias-label-primary);accent-color:var(--dsw-alias-state-business-primary);background:0 0;border-radius:8px;padding:0 10px;font-size:13px}.DGiSta_input:hover:not(:disabled){border-color:var(--dsw-alias-border-l2)}.DGiSta_input:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px;border-color:var(--dsw-alias-state-business-primary)}.DGiSta_input:disabled{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-secondary);cursor:default}.DGiSta_input option{background-color:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}.DGiSta_input option:disabled{color:var(--dsw-alias-label-caption)}.DGiSta_textarea{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);min-height:80px;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-code-block-small);resize:vertical;background:0 0;border-radius:8px;padding:8px 10px;font-size:12px}.DGiSta_status{text-align:center;color:var(--dsw-alias-label-tertiary);padding:32px 0;font-size:13px}.DGiSta_statusError{color:var(--dsw-alias-state-error-primary)}.DGiSta_cardSummary{color:var(--dsw-alias-label-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:36px;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.DGiSta_body{flex-direction:column;gap:4px;min-width:0;margin-top:16px;display:flex}.DGiSta_bodyLabel{color:var(--dsw-alias-label-caption);margin:0;font-size:11px;font-weight:500;line-height:16px}.DGiSta_bodyPre{background:var(--dsw-alias-markdown-code-block);max-height:46vh;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-code-block-small-font-family);font-size:var(--dsw-font-markdown-code-block-small-font-size);line-height:var(--dsw-font-markdown-code-block-small-line-height);white-space:pre-wrap;overflow-wrap:anywhere;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:8px;margin:0;padding:12px;overflow:auto}.DGiSta_bodyStatus{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.DGiSta_bodyError{color:var(--dsw-alias-state-error-primary);}.DGiSta_progressRow{align-items:center;gap:8px;margin-bottom:12px;display:flex}.DGiSta_progressLabel{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px;line-height:18px}.DGiSta_progressTrack{background:var(--dsw-alias-border-l2);border-radius:2px;flex:1;height:4px;overflow:hidden}.DGiSta_progressFill{background:var(--dsw-alias-label-primary);border-radius:2px;height:100%;transition:width .2s;display:block}.DGiSta_progressCount{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12px;line-height:18px}.DGiSta_plazaBadge{white-space:nowrap;border:.5px solid var(--dsw-alias-border-l2);border-radius:4px;flex:none;padding:0 6px;font-size:11px;line-height:18px}.DGiSta_plazaBadgeLocal{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-secondary)}.DGiSta_plazaBadgePending,.DGiSta_plazaBadgeApproved{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-secondary)}.DGiSta_plazaBadgeRejected{color:var(--dsw-alias-label-error);background:var(--dsw-alias-bg-secondary)}.DGiSta_plazaSharedTag{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-secondary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;line-height:18px}.DGiSta_plazaReason{color:var(--dsw-alias-label-error);margin-top:4px;font-size:12px;line-height:18px}.DGiSta_plazaScopeHint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.DGiSta_connectorTab{flex-direction:column;gap:12px;min-width:0;display:flex}.DGiSta_connectorDemoNote{background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-secondary);border-radius:10px;align-items:center;gap:8px;padding:9px 12px;font-size:12px;line-height:18px;display:flex}.DGiSta_connectorDemoTag{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);border-radius:4px;flex:none;padding:0 6px;font-size:11px;line-height:18px}.DGiSta_connectorGrid{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));align-items:start;gap:12px;display:grid}.DGiSta_connectorCard{border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:12px;flex-direction:column;gap:10px;min-width:0;padding:14px;display:flex}.DGiSta_connectorHead{align-items:center;gap:10px;min-width:0;display:flex}.DGiSta_connectorIcon{background:var(--dsw-alias-bg-module-platform);width:32px;height:32px;color:var(--dsw-alias-state-business-primary);border-radius:9px;flex:none;place-items:center;display:grid}.DGiSta_connectorIdentity{flex:1;min-width:0}.DGiSta_connectorName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.DGiSta_connectorVendor{color:var(--dsw-alias-label-tertiary);margin-top:2px;font-size:11px;line-height:16px}.DGiSta_connectorDescription{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:18px}.DGiSta_connectorError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.DGiSta_connectorToggleRow{justify-content:space-between;align-items:center;gap:12px;min-height:28px;display:flex}.DGiSta_connectorToggleLabel{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.DGiSta_capabilityList{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:2px;padding-top:10px;display:flex}.DGiSta_capabilityTitle{color:var(--dsw-alias-label-tertiary);margin-bottom:4px;font-size:11px;line-height:16px}.DGiSta_capabilityRow{justify-content:space-between;align-items:center;gap:12px;min-height:44px;padding:6px 0;display:flex}.DGiSta_capabilityRow+.DGiSta_capabilityRow{border-top:.5px solid var(--dsw-alias-border-l1)}.DGiSta_capabilityCopy{flex:1;min-width:0}.DGiSta_capabilityName{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.DGiSta_capabilityDescription{color:var(--dsw-alias-label-tertiary);margin-top:1px;font-size:11px;line-height:16px}.DGiSta_capabilityReason{color:var(--dsw-alias-state-warn-primary);margin-top:3px;font-size:11px;line-height:16px}.DGiSta_capabilityEmpty{color:var(--dsw-alias-label-tertiary);padding:8px 0;font-size:12px;line-height:18px}.DGiSta_connectorFailed{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-state-error-primary);border-radius:10px;justify-content:space-between;align-items:center;gap:12px;padding:12px 14px;font-size:12px;line-height:18px;display:flex}";
|
|
12
12
|
const tagId = "@sparkelf/dsh-client-ui-skill-center/SkillCenterPage.module.css";
|
|
13
13
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
14
14
|
const tag = document.createElement("style");
|
|
@@ -23,6 +23,14 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
"bodyLabel": "DGiSta_bodyLabel",
|
|
24
24
|
"bodyPre": "DGiSta_bodyPre",
|
|
25
25
|
"bodyStatus": "DGiSta_bodyStatus",
|
|
26
|
+
"capabilityCopy": "DGiSta_capabilityCopy",
|
|
27
|
+
"capabilityDescription": "DGiSta_capabilityDescription",
|
|
28
|
+
"capabilityEmpty": "DGiSta_capabilityEmpty",
|
|
29
|
+
"capabilityList": "DGiSta_capabilityList",
|
|
30
|
+
"capabilityName": "DGiSta_capabilityName",
|
|
31
|
+
"capabilityReason": "DGiSta_capabilityReason",
|
|
32
|
+
"capabilityRow": "DGiSta_capabilityRow",
|
|
33
|
+
"capabilityTitle": "DGiSta_capabilityTitle",
|
|
26
34
|
"card": "DGiSta_card",
|
|
27
35
|
"cardActions": "DGiSta_cardActions",
|
|
28
36
|
"cardBody": "DGiSta_cardBody",
|
|
@@ -35,11 +43,31 @@ window.__ModuleLoader__.load({
|
|
|
35
43
|
"cardTitle": "DGiSta_cardTitle",
|
|
36
44
|
"cardTitleRow": "DGiSta_cardTitleRow",
|
|
37
45
|
"cards": "DGiSta_cards",
|
|
46
|
+
"connectorCard": "DGiSta_connectorCard",
|
|
47
|
+
"connectorDemoNote": "DGiSta_connectorDemoNote",
|
|
48
|
+
"connectorDemoTag": "DGiSta_connectorDemoTag",
|
|
49
|
+
"connectorDescription": "DGiSta_connectorDescription",
|
|
50
|
+
"connectorError": "DGiSta_connectorError",
|
|
51
|
+
"connectorFailed": "DGiSta_connectorFailed",
|
|
52
|
+
"connectorGrid": "DGiSta_connectorGrid",
|
|
53
|
+
"connectorHead": "DGiSta_connectorHead",
|
|
54
|
+
"connectorIcon": "DGiSta_connectorIcon",
|
|
55
|
+
"connectorIdentity": "DGiSta_connectorIdentity",
|
|
56
|
+
"connectorName": "DGiSta_connectorName",
|
|
57
|
+
"connectorTab": "DGiSta_connectorTab",
|
|
58
|
+
"connectorToggleLabel": "DGiSta_connectorToggleLabel",
|
|
59
|
+
"connectorToggleRow": "DGiSta_connectorToggleRow",
|
|
60
|
+
"connectorVendor": "DGiSta_connectorVendor",
|
|
38
61
|
"detail": "DGiSta_detail",
|
|
39
62
|
"detailLabel": "DGiSta_detailLabel",
|
|
40
63
|
"detailRow": "DGiSta_detailRow",
|
|
41
64
|
"detailValue": "DGiSta_detailValue",
|
|
42
65
|
"dialog": "DGiSta_dialog",
|
|
66
|
+
"dialogBody": "DGiSta_dialogBody",
|
|
67
|
+
"dialogClose": "DGiSta_dialogClose",
|
|
68
|
+
"dialogFooter": "DGiSta_dialogFooter",
|
|
69
|
+
"dialogHeader": "DGiSta_dialogHeader",
|
|
70
|
+
"dialogTitle": "DGiSta_dialogTitle",
|
|
43
71
|
"field": "DGiSta_field",
|
|
44
72
|
"fieldLabel": "DGiSta_fieldLabel",
|
|
45
73
|
"form": "DGiSta_form",
|
|
@@ -53,18 +81,35 @@ window.__ModuleLoader__.load({
|
|
|
53
81
|
"markDanger": "DGiSta_markDanger",
|
|
54
82
|
"markOff": "DGiSta_markOff",
|
|
55
83
|
"page": "DGiSta_page",
|
|
84
|
+
"pageContent": "DGiSta_pageContent",
|
|
56
85
|
"pageHead": "DGiSta_pageHead",
|
|
57
86
|
"pageTitle": "DGiSta_pageTitle",
|
|
87
|
+
"plazaBadge": "DGiSta_plazaBadge",
|
|
88
|
+
"plazaBadgeApproved": "DGiSta_plazaBadgeApproved",
|
|
89
|
+
"plazaBadgeLocal": "DGiSta_plazaBadgeLocal",
|
|
90
|
+
"plazaBadgePending": "DGiSta_plazaBadgePending",
|
|
91
|
+
"plazaBadgeRejected": "DGiSta_plazaBadgeRejected",
|
|
92
|
+
"plazaPanel": "DGiSta_plazaPanel",
|
|
93
|
+
"plazaReason": "DGiSta_plazaReason",
|
|
94
|
+
"plazaScopeHint": "DGiSta_plazaScopeHint",
|
|
95
|
+
"plazaSharedTag": "DGiSta_plazaSharedTag",
|
|
58
96
|
"progressCount": "DGiSta_progressCount",
|
|
59
97
|
"progressFill": "DGiSta_progressFill",
|
|
60
98
|
"progressLabel": "DGiSta_progressLabel",
|
|
61
99
|
"progressRow": "DGiSta_progressRow",
|
|
62
100
|
"progressTrack": "DGiSta_progressTrack",
|
|
63
|
-
"
|
|
101
|
+
"publishDialog": "DGiSta_publishDialog",
|
|
102
|
+
"searchClear": "DGiSta_searchClear",
|
|
103
|
+
"searchField": "DGiSta_searchField",
|
|
64
104
|
"status": "DGiSta_status",
|
|
65
105
|
"statusError": "DGiSta_statusError",
|
|
66
106
|
"switch": "DGiSta_switch",
|
|
67
107
|
"switchOn": "DGiSta_switchOn",
|
|
108
|
+
"tab": "DGiSta_tab",
|
|
109
|
+
"tabActive": "DGiSta_tabActive",
|
|
110
|
+
"tabCount": "DGiSta_tabCount",
|
|
111
|
+
"tabPanel": "DGiSta_tabPanel",
|
|
112
|
+
"tabs": "DGiSta_tabs",
|
|
68
113
|
"textarea": "DGiSta_textarea",
|
|
69
114
|
"toolbar": "DGiSta_toolbar",
|
|
70
115
|
"workspaceBadge": "DGiSta_workspaceBadge"
|
|
@@ -79,25 +124,45 @@ window.__ModuleLoader__.load({
|
|
|
79
124
|
*/
|
|
80
125
|
/** Route paths, mirrored from the host (`src/index.ts` ROUTES). */
|
|
81
126
|
const API = {
|
|
82
|
-
list: "
|
|
83
|
-
setEnabled: "
|
|
84
|
-
create: "
|
|
85
|
-
remove: "
|
|
86
|
-
content: "
|
|
87
|
-
translationProgress: "
|
|
127
|
+
list: "api/dsh-skill-center/list",
|
|
128
|
+
setEnabled: "api/dsh-skill-center/set-enabled",
|
|
129
|
+
create: "api/dsh-skill-center/create",
|
|
130
|
+
remove: "api/dsh-skill-center/delete",
|
|
131
|
+
content: "api/dsh-skill-center/content",
|
|
132
|
+
translationProgress: "api/dsh-skill-center/translation-progress",
|
|
133
|
+
plaza: "integrations/dataops/skill-plaza",
|
|
134
|
+
reviewContext: "integrations/dataops/review-context",
|
|
135
|
+
rbac: "integrations/dataops/rbac"
|
|
88
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* Resolve one host route against the document's base URI.
|
|
139
|
+
*
|
|
140
|
+
* The same plugin is served at the origin root (`http://host/` → `/api/...`) and
|
|
141
|
+
* under the DataOps same-origin gateway (`http://host/dsh/` → `/dsh/api/...`).
|
|
142
|
+
* A leading slash would pin every request to the origin root and 404 inside the
|
|
143
|
+
* iframe; a relative path keeps both deployments on the route family the host
|
|
144
|
+
* registered.
|
|
145
|
+
* @param path - route path relative to the document base.
|
|
146
|
+
* @returns absolute URL for fetch.
|
|
147
|
+
*/
|
|
148
|
+
const routeUrl = (path) => {
|
|
149
|
+
const base = typeof document === "undefined" ? "http://localhost/" : document.baseURI;
|
|
150
|
+
return new URL(path, base).href;
|
|
151
|
+
};
|
|
152
|
+
/** The sharing bridge could not answer (503): show local/disabled, never fake a status. */
|
|
153
|
+
var PlazaUnavailableError = class extends Error {};
|
|
89
154
|
/** One thrown API error carrying the host's message. */
|
|
90
155
|
var ApiError = class extends Error {};
|
|
91
156
|
/** Skill center API client. */
|
|
92
157
|
var SkillApi = class {
|
|
93
158
|
/** Fetch the grouped skill list. */
|
|
94
159
|
async list(cwd) {
|
|
95
|
-
const url = typeof cwd === "string" && cwd.trim() !== "" ? `${API.list}?cwd=${encodeURIComponent(cwd)}` : API.list;
|
|
160
|
+
const url = typeof cwd === "string" && cwd.trim() !== "" ? `${routeUrl(API.list)}?cwd=${encodeURIComponent(cwd)}` : routeUrl(API.list);
|
|
96
161
|
return this.request(url);
|
|
97
162
|
}
|
|
98
163
|
/** Enable or disable a skill by rewriting its frontmatter flag. */
|
|
99
164
|
async setEnabled(name, path, enabled) {
|
|
100
|
-
return this.request(API.setEnabled, {
|
|
165
|
+
return this.request(routeUrl(API.setEnabled), {
|
|
101
166
|
method: "POST",
|
|
102
167
|
body: {
|
|
103
168
|
name,
|
|
@@ -108,14 +173,14 @@ window.__ModuleLoader__.load({
|
|
|
108
173
|
}
|
|
109
174
|
/** Create a skill file under the user or project root. */
|
|
110
175
|
async create(payload) {
|
|
111
|
-
return this.request(API.create, {
|
|
176
|
+
return this.request(routeUrl(API.create), {
|
|
112
177
|
method: "POST",
|
|
113
178
|
body: payload
|
|
114
179
|
});
|
|
115
180
|
}
|
|
116
181
|
/** Delete a skill by moving it into the recoverable trash. */
|
|
117
182
|
async remove(name, path) {
|
|
118
|
-
return this.request(API.remove, {
|
|
183
|
+
return this.request(routeUrl(API.remove), {
|
|
119
184
|
method: "POST",
|
|
120
185
|
body: {
|
|
121
186
|
name,
|
|
@@ -135,14 +200,125 @@ window.__ModuleLoader__.load({
|
|
|
135
200
|
const params = new URLSearchParams({ name });
|
|
136
201
|
if (path !== void 0 && path !== "") params.set("path", path);
|
|
137
202
|
if (cwd !== void 0 && cwd !== "") params.set("cwd", cwd);
|
|
138
|
-
return this.request(API.content + "?" + params.toString());
|
|
203
|
+
return this.request(routeUrl(API.content) + "?" + params.toString());
|
|
139
204
|
}
|
|
140
205
|
/**
|
|
141
206
|
* The translated share of the skill set, or undefined when the host has not
|
|
142
207
|
* been told where the translations live (the route then answers `{}`).
|
|
143
208
|
*/
|
|
144
209
|
async translationProgress() {
|
|
145
|
-
return (await this.request(API.translationProgress)).progress;
|
|
210
|
+
return (await this.request(routeUrl(API.translationProgress))).progress;
|
|
211
|
+
}
|
|
212
|
+
/** The caller's review role and department scope, from the DataOps bridge. */
|
|
213
|
+
async reviewContext() {
|
|
214
|
+
const response = await fetch(routeUrl(API.reviewContext));
|
|
215
|
+
const body = await this.readBody(response);
|
|
216
|
+
if (response.status === 503) throw new PlazaUnavailableError("review context is not active");
|
|
217
|
+
if (!response.ok) throw new ApiError(this.errorOf(body, response.status));
|
|
218
|
+
const record = typeof body === "object" && body !== null ? body : {};
|
|
219
|
+
const review = typeof record.review === "object" && record.review !== null ? record.review : {};
|
|
220
|
+
return {
|
|
221
|
+
canReview: review.canReview === true || record.canReview === true,
|
|
222
|
+
canReviewGlobal: review.canReviewGlobal === true || record.canReviewGlobal === true,
|
|
223
|
+
departmentCode: typeof record.departmentCode === "string" ? record.departmentCode : null,
|
|
224
|
+
departmentPath: Array.isArray(record.departmentPath) ? record.departmentPath.flatMap((row) => {
|
|
225
|
+
if (typeof row !== "object" || row === null) return [];
|
|
226
|
+
const node = row;
|
|
227
|
+
return typeof node.code === "string" && typeof node.name === "string" ? [{
|
|
228
|
+
code: node.code,
|
|
229
|
+
name: node.name
|
|
230
|
+
}] : [];
|
|
231
|
+
}) : [],
|
|
232
|
+
roleCodes: Array.isArray(record.roleCodes) ? record.roleCodes.filter((code) => typeof code === "string") : [],
|
|
233
|
+
...typeof record.primaryRole === "string" ? { primaryRole: record.primaryRole } : {}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/** The department tree, for administrators publishing to any department. */
|
|
237
|
+
async departments() {
|
|
238
|
+
const response = await fetch(routeUrl(API.rbac) + "?section=departments");
|
|
239
|
+
const body = await this.readBody(response);
|
|
240
|
+
if (!response.ok) return [];
|
|
241
|
+
if (typeof body !== "object" || body === null || !Array.isArray(body.items)) return [];
|
|
242
|
+
return body.items.flatMap((row) => {
|
|
243
|
+
if (typeof row !== "object" || row === null) return [];
|
|
244
|
+
const node = row;
|
|
245
|
+
return typeof node.code === "string" && typeof node.name === "string" ? [{
|
|
246
|
+
code: node.code,
|
|
247
|
+
name: node.name,
|
|
248
|
+
parentCode: typeof node.parentCode === "string" ? node.parentCode : null
|
|
249
|
+
}] : [];
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The plaza records this workspace holds (`mine=1`). A 503 means the
|
|
254
|
+
* sharing service is not active yet; the panel then renders every local
|
|
255
|
+
* skill as local with 上架 disabled.
|
|
256
|
+
*/
|
|
257
|
+
async plazaMine() {
|
|
258
|
+
const response = await fetch(routeUrl(API.plaza) + "?mine=1");
|
|
259
|
+
const body = await this.readBody(response);
|
|
260
|
+
if (response.status === 503) throw new PlazaUnavailableError("skill plaza is not active");
|
|
261
|
+
if (!response.ok) throw new ApiError(this.errorOf(body, response.status));
|
|
262
|
+
return (typeof body === "object" && body !== null && Array.isArray(body.skills) ? body.skills : []).filter((row) => typeof row === "object" && row !== null && typeof row.id === "number" && typeof row.name === "string").filter((row) => row.sharedByMe === true || row.reviewStatus !== void 0);
|
|
263
|
+
}
|
|
264
|
+
/** Publish one local skill. The name is the DataOps identity; no path/level leaves the workspace. */
|
|
265
|
+
async plazaSubmit(payload) {
|
|
266
|
+
const response = await fetch(routeUrl(API.plaza), {
|
|
267
|
+
method: "POST",
|
|
268
|
+
headers: { "content-type": "application/json" },
|
|
269
|
+
body: JSON.stringify({
|
|
270
|
+
action: "submit",
|
|
271
|
+
...payload
|
|
272
|
+
})
|
|
273
|
+
});
|
|
274
|
+
let body = await this.readBody(response);
|
|
275
|
+
if (response.status === 503) throw new PlazaUnavailableError("skill plaza is not active");
|
|
276
|
+
if (!response.ok && response.status === 400 && this.errorOf(body, response.status).includes("unknown action")) {
|
|
277
|
+
const legacy = await fetch(routeUrl(API.plaza), {
|
|
278
|
+
method: "POST",
|
|
279
|
+
headers: { "content-type": "application/json" },
|
|
280
|
+
body: JSON.stringify({
|
|
281
|
+
action: "share",
|
|
282
|
+
...payload
|
|
283
|
+
})
|
|
284
|
+
});
|
|
285
|
+
body = await this.readBody(legacy);
|
|
286
|
+
if (legacy.status === 503) throw new PlazaUnavailableError("skill plaza is not active");
|
|
287
|
+
if (!legacy.ok) throw new ApiError(this.errorOf(body, legacy.status));
|
|
288
|
+
} else if (!response.ok) throw new ApiError(this.errorOf(body, response.status));
|
|
289
|
+
const skill = typeof body === "object" && body !== null ? body.skill : void 0;
|
|
290
|
+
if (typeof skill !== "object" || skill === null) throw new ApiError("the sharing service returned no skill");
|
|
291
|
+
const row = skill;
|
|
292
|
+
return {
|
|
293
|
+
id: typeof row.id === "number" ? row.id : 0,
|
|
294
|
+
name: typeof row.name === "string" ? row.name : payload.name,
|
|
295
|
+
reviewStatus: row.reviewStatus ?? "pending",
|
|
296
|
+
...row.sharedByMe === void 0 ? { sharedByMe: true } : { sharedByMe: row.sharedByMe }
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/** Stop sharing one plaza entry owned by this workspace. */
|
|
300
|
+
async plazaUnshare(id) {
|
|
301
|
+
const response = await fetch(routeUrl(API.plaza), {
|
|
302
|
+
method: "POST",
|
|
303
|
+
headers: { "content-type": "application/json" },
|
|
304
|
+
body: JSON.stringify({
|
|
305
|
+
action: "unshare",
|
|
306
|
+
id
|
|
307
|
+
})
|
|
308
|
+
});
|
|
309
|
+
if (response.status === 503) throw new PlazaUnavailableError("skill plaza is not active");
|
|
310
|
+
if (!response.ok) throw new ApiError(this.errorOf(await this.readBody(response), response.status));
|
|
311
|
+
}
|
|
312
|
+
async readBody(response) {
|
|
313
|
+
try {
|
|
314
|
+
return await response.json();
|
|
315
|
+
} catch {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
errorOf(body, status) {
|
|
320
|
+
const reported = typeof body === "object" && body !== null && typeof body.error === "string" ? body.error : "";
|
|
321
|
+
return reported === "" ? "HTTP " + String(status) : reported;
|
|
146
322
|
}
|
|
147
323
|
async request(path, options = {}) {
|
|
148
324
|
const init = { method: options.method ?? "GET" };
|
|
@@ -165,6 +341,563 @@ window.__ModuleLoader__.load({
|
|
|
165
341
|
}
|
|
166
342
|
};
|
|
167
343
|
//#endregion
|
|
344
|
+
//#region src/client/plaza.ts
|
|
345
|
+
/** Map one local skill name to its share state. */
|
|
346
|
+
function shareOf(name, records) {
|
|
347
|
+
const record = records.get(name);
|
|
348
|
+
if (record === void 0) return {
|
|
349
|
+
status: "local",
|
|
350
|
+
sharedByMe: false
|
|
351
|
+
};
|
|
352
|
+
return {
|
|
353
|
+
status: record.reviewStatus ?? (record.sharedByMe === true ? "approved" : "local"),
|
|
354
|
+
record,
|
|
355
|
+
sharedByMe: record.sharedByMe === true
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/** Whether a share state offers the 上架 / 重新提交 action. */
|
|
359
|
+
function canSubmit(status) {
|
|
360
|
+
return status === "local" || status === "rejected";
|
|
361
|
+
}
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region src/client/connectors.ts
|
|
364
|
+
/**
|
|
365
|
+
* Connector catalogue for the skill center's fourth tab.
|
|
366
|
+
*
|
|
367
|
+
* A connector is a client-side description of one external system the profile
|
|
368
|
+
* can talk to: whether it is enabled, and which capabilities that account may
|
|
369
|
+
* use. The backend owns the authoritative list; this module only parses it and
|
|
370
|
+
* keeps a demo catalogue for profiles whose bridge has not shipped the route
|
|
371
|
+
* yet. Capability rows the account may not use are absent from the answer, so
|
|
372
|
+
* the UI never renders a disabled placeholder for a permission it lacks.
|
|
373
|
+
*
|
|
374
|
+
* @module @sparkelf/dsh-client-ui-skill-center/client/connectors
|
|
375
|
+
*/
|
|
376
|
+
/** Same-origin route the host/DataOps bridge may serve the catalogue from. */
|
|
377
|
+
const CONNECTORS_ROUTE = "/api/dsh-skill-center/connectors";
|
|
378
|
+
/** The bridge does not serve the connector route (404/405/501/503). */
|
|
379
|
+
var ConnectorUnavailableError = class extends Error {};
|
|
380
|
+
/** The bridge answered but the request failed for another reason. */
|
|
381
|
+
var ConnectorRequestError = class extends Error {};
|
|
382
|
+
/** Same-origin HTTP source for a backend that supplies the catalogue. */
|
|
383
|
+
var HttpConnectorSource = class {
|
|
384
|
+
route;
|
|
385
|
+
/**
|
|
386
|
+
* @param route - same-origin connector route; overridable for tests.
|
|
387
|
+
*/
|
|
388
|
+
constructor(route = CONNECTORS_ROUTE) {
|
|
389
|
+
this.route = route;
|
|
390
|
+
}
|
|
391
|
+
/** Read the catalogue. */
|
|
392
|
+
async list() {
|
|
393
|
+
return this.read(await this.request(this.route));
|
|
394
|
+
}
|
|
395
|
+
/** Enable or disable one connector. */
|
|
396
|
+
async setEnabled(connectorId, enabled) {
|
|
397
|
+
return this.read(await this.request(this.route, {
|
|
398
|
+
connectorId,
|
|
399
|
+
enabled
|
|
400
|
+
}));
|
|
401
|
+
}
|
|
402
|
+
/** Toggle one capability. */
|
|
403
|
+
async setCapability(connectorId, capabilityId, enabled) {
|
|
404
|
+
return this.read(await this.request(this.route, {
|
|
405
|
+
connectorId,
|
|
406
|
+
capabilityId,
|
|
407
|
+
enabled
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
async request(route, body) {
|
|
411
|
+
const init = body === void 0 ? { headers: { accept: "application/json" } } : {
|
|
412
|
+
method: "POST",
|
|
413
|
+
headers: {
|
|
414
|
+
accept: "application/json",
|
|
415
|
+
"content-type": "application/json"
|
|
416
|
+
},
|
|
417
|
+
body: JSON.stringify(body)
|
|
418
|
+
};
|
|
419
|
+
const response = await fetch(route, init);
|
|
420
|
+
if (response.status === 404 || response.status === 405 || response.status === 501 || response.status === 503) throw new ConnectorUnavailableError("connector catalogue is not served");
|
|
421
|
+
if (!response.ok) {
|
|
422
|
+
let detail = "";
|
|
423
|
+
try {
|
|
424
|
+
const payload = await response.json();
|
|
425
|
+
detail = typeof payload.error === "string" ? payload.error : "";
|
|
426
|
+
} catch {}
|
|
427
|
+
throw new ConnectorRequestError(detail === "" ? "HTTP " + String(response.status) : detail);
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
return await response.json();
|
|
431
|
+
} catch {
|
|
432
|
+
throw new ConnectorUnavailableError("connector catalogue is not JSON");
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
read(value) {
|
|
436
|
+
return parseConnectorList(value);
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
/** Narrow one wire value to a connector capability. */
|
|
440
|
+
function parseCapability(value) {
|
|
441
|
+
if (typeof value !== "object" || value === null) return null;
|
|
442
|
+
const row = value;
|
|
443
|
+
if (typeof row.id !== "string" || row.id === "") return null;
|
|
444
|
+
return {
|
|
445
|
+
id: row.id,
|
|
446
|
+
name: typeof row.name === "string" && row.name !== "" ? row.name : row.id,
|
|
447
|
+
...typeof row.description === "string" ? { description: row.description } : {},
|
|
448
|
+
enabled: row.enabled === true,
|
|
449
|
+
permitted: row.permitted !== false,
|
|
450
|
+
...typeof row.unavailableReason === "string" ? { unavailableReason: row.unavailableReason } : {}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/** Narrow one wire value to a connector. */
|
|
454
|
+
function parseConnector(value) {
|
|
455
|
+
if (typeof value !== "object" || value === null) return null;
|
|
456
|
+
const row = value;
|
|
457
|
+
if (typeof row.id !== "string" || row.id === "" || typeof row.name !== "string" || row.name === "") return null;
|
|
458
|
+
const capabilities = Array.isArray(row.capabilities) ? row.capabilities.flatMap((entry) => parseCapability(entry) ?? []) : [];
|
|
459
|
+
return {
|
|
460
|
+
id: row.id,
|
|
461
|
+
name: row.name,
|
|
462
|
+
...typeof row.vendor === "string" ? { vendor: row.vendor } : {},
|
|
463
|
+
...typeof row.description === "string" ? { description: row.description } : {},
|
|
464
|
+
enabled: row.enabled === true,
|
|
465
|
+
...typeof row.connected === "boolean" ? { connected: row.connected } : {},
|
|
466
|
+
...typeof row.error === "string" ? { error: row.error } : {},
|
|
467
|
+
capabilities
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Parse a catalogue answer. Both a bare array and `{ connectors: [...] }` are
|
|
472
|
+
* accepted, because a bridge may grow the wrapper for counts without breaking
|
|
473
|
+
* the older shape.
|
|
474
|
+
* @param value - decoded JSON body.
|
|
475
|
+
* @returns the connectors the body carries; empty when it carries none.
|
|
476
|
+
*/
|
|
477
|
+
function parseConnectorList(value) {
|
|
478
|
+
if (Array.isArray(value)) return value.flatMap((entry) => parseConnector(entry) ?? []);
|
|
479
|
+
if (typeof value !== "object" || value === null) return [];
|
|
480
|
+
const rows = value.connectors;
|
|
481
|
+
return Array.isArray(rows) ? rows.flatMap((entry) => parseConnector(entry) ?? []) : [];
|
|
482
|
+
}
|
|
483
|
+
/** Capabilities this account may see; a `permitted: false` row never renders. */
|
|
484
|
+
function visibleCapabilities(connector) {
|
|
485
|
+
return connector.capabilities.filter((capability) => capability.permitted);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Derive the card state from the catalogue row.
|
|
489
|
+
* @param connector - one catalogue row.
|
|
490
|
+
* @returns `disabled`, `connected`, or `error`.
|
|
491
|
+
*/
|
|
492
|
+
function connectorState(connector) {
|
|
493
|
+
if (!connector.enabled) return "disabled";
|
|
494
|
+
return connector.connected === false ? "error" : "connected";
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* The demo catalogue used when no bridge serves the route.
|
|
498
|
+
*
|
|
499
|
+
* It describes the connector this profile ships and one generic third-party
|
|
500
|
+
* connector, so the tab still demonstrates enable/disable, per-capability
|
|
501
|
+
* switches, a hidden no-permission capability, and an unavailable reason.
|
|
502
|
+
* @returns a fresh mutable copy on every call.
|
|
503
|
+
*/
|
|
504
|
+
function demoConnectors() {
|
|
505
|
+
return [{
|
|
506
|
+
id: "wanxiang-ai",
|
|
507
|
+
name: "万相AI中台连接器",
|
|
508
|
+
vendor: "DataOps",
|
|
509
|
+
description: "接收万相AI中台的审批任务,并把处理结果回写中台。",
|
|
510
|
+
enabled: false,
|
|
511
|
+
connected: false,
|
|
512
|
+
capabilities: [
|
|
513
|
+
{
|
|
514
|
+
id: "approval.read",
|
|
515
|
+
name: "读取审批任务",
|
|
516
|
+
description: "拉取当前账号可办理的审批任务",
|
|
517
|
+
enabled: true,
|
|
518
|
+
permitted: true
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
id: "approval.handle",
|
|
522
|
+
name: "打开办理",
|
|
523
|
+
description: "跳转到万相AI中台审批详情完成办理",
|
|
524
|
+
enabled: true,
|
|
525
|
+
permitted: true
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: "task.writeback",
|
|
529
|
+
name: "回写任务状态",
|
|
530
|
+
description: "把办理结果回写到万相AI中台",
|
|
531
|
+
enabled: false,
|
|
532
|
+
permitted: true
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
id: "approval.batch",
|
|
536
|
+
name: "批量审批",
|
|
537
|
+
description: "一次处理多条审批任务",
|
|
538
|
+
enabled: false,
|
|
539
|
+
permitted: true,
|
|
540
|
+
unavailableReason: "当前连接未开通批量接口"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: "credential.manage",
|
|
544
|
+
name: "管理连接凭据",
|
|
545
|
+
description: "配置或轮换连接凭据",
|
|
546
|
+
enabled: false,
|
|
547
|
+
permitted: false
|
|
548
|
+
}
|
|
549
|
+
]
|
|
550
|
+
}, {
|
|
551
|
+
id: "work-order",
|
|
552
|
+
name: "通用工单连接器",
|
|
553
|
+
vendor: "第三方系统",
|
|
554
|
+
description: "把外部工单系统的待办接入任务中心。",
|
|
555
|
+
enabled: false,
|
|
556
|
+
connected: false,
|
|
557
|
+
capabilities: [
|
|
558
|
+
{
|
|
559
|
+
id: "ticket.pull",
|
|
560
|
+
name: "拉取工单",
|
|
561
|
+
description: "按账号权限拉取待办工单",
|
|
562
|
+
enabled: true,
|
|
563
|
+
permitted: true
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
id: "ticket.comment",
|
|
567
|
+
name: "回写处理意见",
|
|
568
|
+
description: "把处理意见回写到工单系统",
|
|
569
|
+
enabled: false,
|
|
570
|
+
permitted: true
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
id: "ticket.admin",
|
|
574
|
+
name: "工单配置管理",
|
|
575
|
+
description: "维护工单字段与流转规则",
|
|
576
|
+
enabled: false,
|
|
577
|
+
permitted: false
|
|
578
|
+
}
|
|
579
|
+
]
|
|
580
|
+
}];
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Read the catalogue, falling back to the demo rows when the bridge has no
|
|
584
|
+
* route. Any other failure propagates: a broken bridge is not "no connectors".
|
|
585
|
+
* @param source - the deployed source.
|
|
586
|
+
* @param demo - demo factory (tests pass a fixed list).
|
|
587
|
+
* @returns the catalogue and whether it is the demo fallback.
|
|
588
|
+
*/
|
|
589
|
+
async function readConnectorCatalogue(source, demo = demoConnectors) {
|
|
590
|
+
try {
|
|
591
|
+
return {
|
|
592
|
+
connectors: await source.list(),
|
|
593
|
+
demo: false
|
|
594
|
+
};
|
|
595
|
+
} catch (error) {
|
|
596
|
+
if (error instanceof ConnectorUnavailableError) return {
|
|
597
|
+
connectors: demo(),
|
|
598
|
+
demo: true
|
|
599
|
+
};
|
|
600
|
+
throw error;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
//#endregion
|
|
604
|
+
//#region src/client/ConnectorsTab.tsx
|
|
605
|
+
/** Status label and tone for one connector. */
|
|
606
|
+
function statusOf(connector, t) {
|
|
607
|
+
const state = connectorState(connector);
|
|
608
|
+
if (state === "error") return {
|
|
609
|
+
label: t("connector.error"),
|
|
610
|
+
tone: "danger"
|
|
611
|
+
};
|
|
612
|
+
if (state === "connected") return {
|
|
613
|
+
label: t("connector.connected"),
|
|
614
|
+
tone: "success"
|
|
615
|
+
};
|
|
616
|
+
return {
|
|
617
|
+
label: t("connector.disabled"),
|
|
618
|
+
tone: "neutral"
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
/** Whether the query matches a connector or one of its visible capabilities. */
|
|
622
|
+
function matchesQuery(connector, needle) {
|
|
623
|
+
if (needle === "") return true;
|
|
624
|
+
return [
|
|
625
|
+
connector.name,
|
|
626
|
+
connector.vendor ?? "",
|
|
627
|
+
connector.description ?? "",
|
|
628
|
+
...visibleCapabilities(connector).flatMap((capability) => [capability.name, capability.description ?? ""])
|
|
629
|
+
].some((value) => value.toLowerCase().includes(needle));
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Render one connector card.
|
|
633
|
+
* @param props.connector - the catalogue row.
|
|
634
|
+
* @param props.busy - whether a write for this connector is in flight.
|
|
635
|
+
* @param props.t - dictionary resolver.
|
|
636
|
+
* @param props.onToggleConnector - enable/disable request.
|
|
637
|
+
* @param props.onToggleCapability - capability toggle request.
|
|
638
|
+
* @returns the card.
|
|
639
|
+
*/
|
|
640
|
+
function ConnectorCard({ connector, busy, t, onToggleConnector, onToggleCapability }) {
|
|
641
|
+
const status = statusOf(connector, t);
|
|
642
|
+
const capabilities = visibleCapabilities(connector);
|
|
643
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
644
|
+
className: SkillCenterPage_module_css_default.connectorCard,
|
|
645
|
+
"data-connector-id": connector.id,
|
|
646
|
+
"data-connector-enabled": connector.enabled,
|
|
647
|
+
children: [
|
|
648
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
649
|
+
className: SkillCenterPage_module_css_default.connectorHead,
|
|
650
|
+
children: [
|
|
651
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
652
|
+
className: SkillCenterPage_module_css_default.connectorIcon,
|
|
653
|
+
"aria-hidden": "true",
|
|
654
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 })
|
|
655
|
+
}),
|
|
656
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
657
|
+
className: SkillCenterPage_module_css_default.connectorIdentity,
|
|
658
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
659
|
+
className: SkillCenterPage_module_css_default.connectorName,
|
|
660
|
+
children: connector.name
|
|
661
|
+
}), connector.vendor === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
662
|
+
className: SkillCenterPage_module_css_default.connectorVendor,
|
|
663
|
+
children: connector.vendor
|
|
664
|
+
})]
|
|
665
|
+
}),
|
|
666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
|
|
667
|
+
tone: status.tone,
|
|
668
|
+
children: status.label
|
|
669
|
+
})
|
|
670
|
+
]
|
|
671
|
+
}),
|
|
672
|
+
connector.description === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
673
|
+
className: SkillCenterPage_module_css_default.connectorDescription,
|
|
674
|
+
children: connector.description
|
|
675
|
+
}),
|
|
676
|
+
connector.enabled && connector.error !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
677
|
+
className: SkillCenterPage_module_css_default.connectorError,
|
|
678
|
+
role: "status",
|
|
679
|
+
children: connector.error
|
|
680
|
+
}) : null,
|
|
681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
682
|
+
className: SkillCenterPage_module_css_default.connectorToggleRow,
|
|
683
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
684
|
+
className: SkillCenterPage_module_css_default.connectorToggleLabel,
|
|
685
|
+
children: connector.enabled ? t("connector.enabled") : t("connector.disabled")
|
|
686
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
687
|
+
checked: connector.enabled,
|
|
688
|
+
disabled: busy,
|
|
689
|
+
label: (connector.enabled ? t("connector.disable") : t("connector.enable")) + " " + connector.name,
|
|
690
|
+
onChange: (next) => {
|
|
691
|
+
onToggleConnector(connector, next);
|
|
692
|
+
}
|
|
693
|
+
})]
|
|
694
|
+
}),
|
|
695
|
+
connector.enabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
696
|
+
className: SkillCenterPage_module_css_default.capabilityList,
|
|
697
|
+
"data-connector-capabilities": true,
|
|
698
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
699
|
+
className: SkillCenterPage_module_css_default.capabilityTitle,
|
|
700
|
+
children: t("connector.capabilities")
|
|
701
|
+
}), capabilities.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
702
|
+
className: SkillCenterPage_module_css_default.capabilityEmpty,
|
|
703
|
+
children: t("connector.noCapabilities")
|
|
704
|
+
}) : capabilities.map((capability) => {
|
|
705
|
+
const unavailable = capability.unavailableReason !== void 0;
|
|
706
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
707
|
+
className: SkillCenterPage_module_css_default.capabilityRow,
|
|
708
|
+
"data-capability-id": capability.id,
|
|
709
|
+
"data-capability-enabled": capability.enabled,
|
|
710
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
711
|
+
className: SkillCenterPage_module_css_default.capabilityCopy,
|
|
712
|
+
children: [
|
|
713
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
714
|
+
className: SkillCenterPage_module_css_default.capabilityName,
|
|
715
|
+
children: capability.name
|
|
716
|
+
}),
|
|
717
|
+
capability.description === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
718
|
+
className: SkillCenterPage_module_css_default.capabilityDescription,
|
|
719
|
+
children: capability.description
|
|
720
|
+
}),
|
|
721
|
+
capability.unavailableReason === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
722
|
+
className: SkillCenterPage_module_css_default.capabilityReason,
|
|
723
|
+
children: [
|
|
724
|
+
t("connector.unavailable"),
|
|
725
|
+
" · ",
|
|
726
|
+
capability.unavailableReason
|
|
727
|
+
]
|
|
728
|
+
})
|
|
729
|
+
]
|
|
730
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
731
|
+
checked: capability.enabled,
|
|
732
|
+
disabled: busy || unavailable,
|
|
733
|
+
label: (capability.enabled ? t("connector.disable") : t("connector.enable")) + " " + capability.name,
|
|
734
|
+
onChange: (next) => {
|
|
735
|
+
onToggleCapability(connector, capability, next);
|
|
736
|
+
}
|
|
737
|
+
})]
|
|
738
|
+
}, capability.id);
|
|
739
|
+
})]
|
|
740
|
+
}) : null
|
|
741
|
+
]
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Render the connector tab body.
|
|
746
|
+
* @param props - catalogue state, search text, and the two write handlers.
|
|
747
|
+
* @returns the connector cards, or the loading/failure/empty status.
|
|
748
|
+
*/
|
|
749
|
+
function ConnectorsTab(props) {
|
|
750
|
+
const { state, query, busyId, t, onRetry, onToggleConnector, onToggleCapability } = props;
|
|
751
|
+
if (state.kind === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
752
|
+
className: SkillCenterPage_module_css_default.status,
|
|
753
|
+
children: t("connector.loading")
|
|
754
|
+
});
|
|
755
|
+
if (state.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
756
|
+
className: SkillCenterPage_module_css_default.connectorFailed,
|
|
757
|
+
role: "alert",
|
|
758
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
759
|
+
t("connector.failed"),
|
|
760
|
+
":",
|
|
761
|
+
state.message
|
|
762
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
763
|
+
variant: "outline",
|
|
764
|
+
size: "sm",
|
|
765
|
+
onClick: onRetry,
|
|
766
|
+
children: t("connector.retry")
|
|
767
|
+
})]
|
|
768
|
+
});
|
|
769
|
+
const needle = query.trim().toLowerCase();
|
|
770
|
+
const connectors = state.catalogue.connectors.filter((connector) => matchesQuery(connector, needle));
|
|
771
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
772
|
+
className: SkillCenterPage_module_css_default.connectorTab,
|
|
773
|
+
"data-connector-catalogue": true,
|
|
774
|
+
"data-demo": state.catalogue.demo,
|
|
775
|
+
children: [state.catalogue.demo ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
776
|
+
className: SkillCenterPage_module_css_default.connectorDemoNote,
|
|
777
|
+
role: "status",
|
|
778
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
779
|
+
className: SkillCenterPage_module_css_default.connectorDemoTag,
|
|
780
|
+
children: t("connector.demoTag")
|
|
781
|
+
}), t("connector.demo")]
|
|
782
|
+
}) : null, connectors.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
783
|
+
className: SkillCenterPage_module_css_default.status,
|
|
784
|
+
children: state.catalogue.connectors.length === 0 ? t("connector.empty") : t("connector.noMatches")
|
|
785
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
786
|
+
className: SkillCenterPage_module_css_default.connectorGrid,
|
|
787
|
+
children: connectors.map((connector) => {
|
|
788
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorCard, {
|
|
789
|
+
connector,
|
|
790
|
+
busy: busyId === connector.id || busyId?.startsWith(connector.id + ":") === true,
|
|
791
|
+
t,
|
|
792
|
+
onToggleConnector,
|
|
793
|
+
onToggleCapability
|
|
794
|
+
}, connector.id);
|
|
795
|
+
})
|
|
796
|
+
})]
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
//#endregion
|
|
800
|
+
//#region src/client/scope.ts
|
|
801
|
+
/** Read the identity the dataops-account plugin publishes. */
|
|
802
|
+
function readAccountIdentity() {
|
|
803
|
+
if (typeof window === "undefined") return void 0;
|
|
804
|
+
const fromWindow = window.__DATAOPS_USER__;
|
|
805
|
+
if (fromWindow !== void 0) return fromWindow;
|
|
806
|
+
if (typeof document === "undefined") return void 0;
|
|
807
|
+
const dataset = document.documentElement.dataset;
|
|
808
|
+
if (dataset.dataopsAccountId === void 0 && dataset.dataopsAccountName === void 0) return void 0;
|
|
809
|
+
const identity = {};
|
|
810
|
+
if (dataset.dataopsAccountId !== void 0) identity.id = dataset.dataopsAccountId;
|
|
811
|
+
if (dataset.dataopsAccountName !== void 0) identity.displayName = dataset.dataopsAccountName;
|
|
812
|
+
return identity;
|
|
813
|
+
}
|
|
814
|
+
/** Classify the caller: global review means super admin/admin; review means department admin. */
|
|
815
|
+
function scopeRole(scope) {
|
|
816
|
+
if (scope?.canReviewGlobal === true) return "admin";
|
|
817
|
+
if (scope?.canReview === true) return "dept-admin";
|
|
818
|
+
return "user";
|
|
819
|
+
}
|
|
820
|
+
/** Visibilities this caller may select. */
|
|
821
|
+
function allowedVisibilities(scope) {
|
|
822
|
+
if (scopeRole(scope) === "admin") return [
|
|
823
|
+
"global",
|
|
824
|
+
"department",
|
|
825
|
+
"private"
|
|
826
|
+
];
|
|
827
|
+
if (hasDepartment(scope)) return ["department", "private"];
|
|
828
|
+
return ["private"];
|
|
829
|
+
}
|
|
830
|
+
/** Whether the caller belongs to a department (needed for department visibility). */
|
|
831
|
+
function hasDepartment(scope) {
|
|
832
|
+
return typeof scope?.departmentCode === "string" && scope.departmentCode !== "";
|
|
833
|
+
}
|
|
834
|
+
/** First-run default: admins publish globally, everyone else to their department, else private. */
|
|
835
|
+
function defaultVisibility(scope) {
|
|
836
|
+
if (scopeRole(scope) === "admin") return "global";
|
|
837
|
+
return hasDepartment(scope) ? "department" : "private";
|
|
838
|
+
}
|
|
839
|
+
/** The caller's own department code. */
|
|
840
|
+
function ownDepartment(scope) {
|
|
841
|
+
const code = scope?.departmentCode;
|
|
842
|
+
return typeof code === "string" && code !== "" ? code : void 0;
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Coerce a remembered choice into one this caller may still make.
|
|
846
|
+
*
|
|
847
|
+
* A saved global choice is dropped for a non-admin; a saved department code is
|
|
848
|
+
* kept only when it is the caller's own department (department admins/users)
|
|
849
|
+
* or still present in the admin's fetched department list.
|
|
850
|
+
*/
|
|
851
|
+
function sanitizeChoice(saved, scope, departments = []) {
|
|
852
|
+
const allowed = allowedVisibilities(scope);
|
|
853
|
+
const visibility = saved !== void 0 && allowed.includes(saved.visibility) ? saved.visibility : defaultVisibility(scope);
|
|
854
|
+
if (visibility !== "department") return { visibility };
|
|
855
|
+
if (scopeRole(scope) === "admin") {
|
|
856
|
+
const savedCode = saved?.departmentCode;
|
|
857
|
+
if (savedCode !== void 0 && departments.some((department) => department.code === savedCode)) return {
|
|
858
|
+
visibility,
|
|
859
|
+
departmentCode: savedCode
|
|
860
|
+
};
|
|
861
|
+
const code = ownDepartment(scope) ?? departments[0]?.code;
|
|
862
|
+
return code === void 0 ? { visibility } : {
|
|
863
|
+
visibility,
|
|
864
|
+
departmentCode: code
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
const code = ownDepartment(scope);
|
|
868
|
+
return code === void 0 ? { visibility } : {
|
|
869
|
+
visibility,
|
|
870
|
+
departmentCode: code
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
/** localStorage key, per DataOps user. */
|
|
874
|
+
function scopeStorageKey(identity) {
|
|
875
|
+
return "dsh-skill-center:plaza-scope:" + (identity?.id ?? identity?.username ?? "anonymous");
|
|
876
|
+
}
|
|
877
|
+
/** Read a remembered choice (invalid JSON is treated as no choice). */
|
|
878
|
+
function readSavedScope(storage, key) {
|
|
879
|
+
try {
|
|
880
|
+
const raw = storage.getItem(key);
|
|
881
|
+
if (raw === null || raw === "") return void 0;
|
|
882
|
+
const parsed = JSON.parse(raw);
|
|
883
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
884
|
+
const value = parsed;
|
|
885
|
+
if (value.visibility !== "global" && value.visibility !== "department" && value.visibility !== "private") return void 0;
|
|
886
|
+
return {
|
|
887
|
+
visibility: value.visibility,
|
|
888
|
+
...typeof value.departmentCode === "string" && value.departmentCode !== "" ? { departmentCode: value.departmentCode } : {}
|
|
889
|
+
};
|
|
890
|
+
} catch {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
/** Persist one choice. */
|
|
895
|
+
function writeSavedScope(storage, key, choice) {
|
|
896
|
+
try {
|
|
897
|
+
storage.setItem(key, JSON.stringify(choice));
|
|
898
|
+
} catch {}
|
|
899
|
+
}
|
|
900
|
+
//#endregion
|
|
168
901
|
//#region src/client/SkillCenterPage.tsx
|
|
169
902
|
/**
|
|
170
903
|
* Skill center page. Browses the loaded skills grouped by source, toggles model
|
|
@@ -175,6 +908,8 @@ window.__ModuleLoader__.load({
|
|
|
175
908
|
*
|
|
176
909
|
* @module @sparkelf/dsh-client-ui-skill-center/client/SkillCenterPage
|
|
177
910
|
*/
|
|
911
|
+
/** Group key the host uses for skills that ship inside the runtime. */
|
|
912
|
+
const BUNDLED_GROUP = "bundled";
|
|
178
913
|
/**
|
|
179
914
|
* One labelled create-form field.
|
|
180
915
|
* @param props - the field's label and the control it wraps.
|
|
@@ -195,7 +930,7 @@ window.__ModuleLoader__.load({
|
|
|
195
930
|
* with, its toggle, and its delete action.
|
|
196
931
|
* @returns the row.
|
|
197
932
|
*/
|
|
198
|
-
function SkillCard({ skill, api, cwd, t, onToggle, onDelete }) {
|
|
933
|
+
function SkillCard({ skill, api, cwd, t, share, shareBusy, shareDisabled, onToggle, onDelete, onShare, onUnshare }) {
|
|
199
934
|
const [open, setOpen] = (0, react.useState)(false);
|
|
200
935
|
const [body, setBody] = (0, react.useState)({ kind: "loading" });
|
|
201
936
|
(0, react.useEffect)(() => {
|
|
@@ -224,6 +959,7 @@ window.__ModuleLoader__.load({
|
|
|
224
959
|
cwd
|
|
225
960
|
]);
|
|
226
961
|
const foreign = skill.isActiveWorkspace === false && skill.workspaceName !== void 0;
|
|
962
|
+
const shareLabel = share.status === "approved" ? t("plaza.statusApproved") : share.status === "pending" ? t("plaza.statusPending") : share.status === "rejected" ? t("plaza.statusRejected") : t("plaza.statusLocal");
|
|
227
963
|
const details = [];
|
|
228
964
|
if (skill.whenToUse !== void 0) details.push({
|
|
229
965
|
key: "detail.whenToUse",
|
|
@@ -243,6 +979,8 @@ window.__ModuleLoader__.load({
|
|
|
243
979
|
});
|
|
244
980
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
245
981
|
className: foreign ? SkillCenterPage_module_css_default.card + " " + SkillCenterPage_module_css_default.cardForeign : SkillCenterPage_module_css_default.card,
|
|
982
|
+
"data-skill-name": skill.name,
|
|
983
|
+
"data-plaza-status": share.status,
|
|
246
984
|
children: [
|
|
247
985
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
248
986
|
className: SkillCenterPage_module_css_default.cardHead,
|
|
@@ -251,38 +989,62 @@ window.__ModuleLoader__.load({
|
|
|
251
989
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutlineRegular, { size: 16 })
|
|
252
990
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
253
991
|
className: SkillCenterPage_module_css_default.cardTitleRow,
|
|
254
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
255
|
-
className: SkillCenterPage_module_css_default.cardTitle,
|
|
256
|
-
children: skill.i18n?.title ?? skill.name
|
|
257
|
-
}), skill.workspaceName === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
258
|
-
className: SkillCenterPage_module_css_default.workspaceBadge,
|
|
259
|
-
children: skill.workspaceName
|
|
260
|
-
})]
|
|
261
|
-
})]
|
|
262
|
-
}),
|
|
263
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
264
|
-
className: SkillCenterPage_module_css_default.cardBody,
|
|
265
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
266
|
-
className: SkillCenterPage_module_css_default.cardSummary,
|
|
267
|
-
children: skill.i18n?.summary ?? skill.description
|
|
268
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
269
|
-
className: SkillCenterPage_module_css_default.cardMarks,
|
|
270
992
|
children: [
|
|
271
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
272
|
-
className:
|
|
273
|
-
children:
|
|
993
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
994
|
+
className: SkillCenterPage_module_css_default.cardTitle,
|
|
995
|
+
children: skill.i18n?.title ?? skill.name
|
|
996
|
+
}),
|
|
997
|
+
skill.workspaceName === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
998
|
+
className: SkillCenterPage_module_css_default.workspaceBadge,
|
|
999
|
+
children: skill.workspaceName
|
|
274
1000
|
}),
|
|
275
1001
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
276
|
-
className:
|
|
277
|
-
|
|
1002
|
+
className: SkillCenterPage_module_css_default.plazaBadge + " " + (share.status === "approved" ? SkillCenterPage_module_css_default.plazaBadgeApproved : share.status === "rejected" ? SkillCenterPage_module_css_default.plazaBadgeRejected : share.status === "pending" ? SkillCenterPage_module_css_default.plazaBadgePending : SkillCenterPage_module_css_default.plazaBadgeLocal),
|
|
1003
|
+
"data-plaza-status": share.status,
|
|
1004
|
+
children: shareLabel
|
|
278
1005
|
}),
|
|
279
|
-
|
|
280
|
-
className: SkillCenterPage_module_css_default.
|
|
281
|
-
|
|
1006
|
+
share.status === "approved" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1007
|
+
className: SkillCenterPage_module_css_default.plazaSharedTag,
|
|
1008
|
+
"data-plaza-shared": true,
|
|
1009
|
+
children: t("plaza.sharedTag")
|
|
282
1010
|
}) : null
|
|
283
1011
|
]
|
|
284
1012
|
})]
|
|
285
1013
|
}),
|
|
1014
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1015
|
+
className: SkillCenterPage_module_css_default.cardBody,
|
|
1016
|
+
children: [
|
|
1017
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1018
|
+
className: SkillCenterPage_module_css_default.cardSummary,
|
|
1019
|
+
children: skill.i18n?.summary ?? skill.description
|
|
1020
|
+
}),
|
|
1021
|
+
share.status === "rejected" && share.record?.reviewNote !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1022
|
+
className: SkillCenterPage_module_css_default.plazaReason,
|
|
1023
|
+
children: [
|
|
1024
|
+
t("plaza.reason"),
|
|
1025
|
+
": ",
|
|
1026
|
+
share.record.reviewNote
|
|
1027
|
+
]
|
|
1028
|
+
}) : null,
|
|
1029
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1030
|
+
className: SkillCenterPage_module_css_default.cardMarks,
|
|
1031
|
+
children: [
|
|
1032
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1033
|
+
className: skill.modelInvocable ? SkillCenterPage_module_css_default.mark + " " + SkillCenterPage_module_css_default.markOn : SkillCenterPage_module_css_default.mark + " " + SkillCenterPage_module_css_default.markOff,
|
|
1034
|
+
children: t("skill.modelInvocable")
|
|
1035
|
+
}),
|
|
1036
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1037
|
+
className: skill.userInvocable ? SkillCenterPage_module_css_default.mark + " " + SkillCenterPage_module_css_default.markOn : SkillCenterPage_module_css_default.mark + " " + SkillCenterPage_module_css_default.markOff,
|
|
1038
|
+
children: t("skill.userInvocable")
|
|
1039
|
+
}),
|
|
1040
|
+
skill.linked === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1041
|
+
className: SkillCenterPage_module_css_default.mark + " " + SkillCenterPage_module_css_default.markDanger,
|
|
1042
|
+
children: t("skill.linked")
|
|
1043
|
+
}) : null
|
|
1044
|
+
]
|
|
1045
|
+
})
|
|
1046
|
+
]
|
|
1047
|
+
}),
|
|
286
1048
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
287
1049
|
className: SkillCenterPage_module_css_default.cardEnd,
|
|
288
1050
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -295,21 +1057,42 @@ window.__ModuleLoader__.load({
|
|
|
295
1057
|
}
|
|
296
1058
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
297
1059
|
className: SkillCenterPage_module_css_default.cardActions,
|
|
298
|
-
children: [
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
1060
|
+
children: [
|
|
1061
|
+
canSubmit(share.status) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1062
|
+
variant: "primary",
|
|
1063
|
+
size: "sm",
|
|
1064
|
+
disabled: shareBusy || shareDisabled,
|
|
1065
|
+
onClick: () => {
|
|
1066
|
+
onShare(skill);
|
|
1067
|
+
},
|
|
1068
|
+
children: share.status === "rejected" ? t("plaza.resubmit") : t("plaza.share")
|
|
1069
|
+
}) : null,
|
|
1070
|
+
share.sharedByMe && share.record !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1071
|
+
variant: "outline",
|
|
1072
|
+
size: "sm",
|
|
1073
|
+
disabled: shareBusy,
|
|
1074
|
+
onClick: () => {
|
|
1075
|
+
if (share.record !== void 0) onUnshare(skill, share.record.id);
|
|
1076
|
+
},
|
|
1077
|
+
children: t("plaza.unshare")
|
|
1078
|
+
}) : null,
|
|
1079
|
+
skill.path === void 0 || skill.linked === true ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1080
|
+
variant: "outline",
|
|
1081
|
+
size: "sm",
|
|
1082
|
+
onClick: () => {
|
|
1083
|
+
onDelete(skill);
|
|
1084
|
+
},
|
|
1085
|
+
children: t("action.delete")
|
|
1086
|
+
}),
|
|
1087
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1088
|
+
variant: "outline",
|
|
1089
|
+
size: "sm",
|
|
1090
|
+
onClick: () => {
|
|
1091
|
+
setOpen(true);
|
|
1092
|
+
},
|
|
1093
|
+
children: t("action.showDetail")
|
|
1094
|
+
})
|
|
1095
|
+
]
|
|
313
1096
|
})]
|
|
314
1097
|
}),
|
|
315
1098
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
@@ -376,8 +1159,13 @@ window.__ModuleLoader__.load({
|
|
|
376
1159
|
*/
|
|
377
1160
|
function SkillCenterPage({ t, renderSlot, ...runtime }) {
|
|
378
1161
|
const api = (0, react.useMemo)(() => new SkillApi(), []);
|
|
1162
|
+
const connectorSource = (0, react.useMemo)(() => new HttpConnectorSource(), []);
|
|
379
1163
|
const [state, setState] = (0, react.useState)({ kind: "loading" });
|
|
1164
|
+
const [tab, setTab] = (0, react.useState)("builtin");
|
|
380
1165
|
const [query, setQuery] = (0, react.useState)("");
|
|
1166
|
+
const [connectors, setConnectors] = (0, react.useState)({ kind: "loading" });
|
|
1167
|
+
const [connectorBusyId, setConnectorBusyId] = (0, react.useState)(null);
|
|
1168
|
+
const [connectorNotice, setConnectorNotice] = (0, react.useState)(null);
|
|
381
1169
|
const [progress, setProgress] = (0, react.useState)(void 0);
|
|
382
1170
|
const [creating, setCreating] = (0, react.useState)(false);
|
|
383
1171
|
const [draft, setDraft] = (0, react.useState)({
|
|
@@ -387,6 +1175,17 @@ window.__ModuleLoader__.load({
|
|
|
387
1175
|
content: "",
|
|
388
1176
|
root: "user"
|
|
389
1177
|
});
|
|
1178
|
+
const [plaza, setPlaza] = (0, react.useState)({ kind: "loading" });
|
|
1179
|
+
const [shareTarget, setShareTarget] = (0, react.useState)(null);
|
|
1180
|
+
const [shareInstruction, setShareInstruction] = (0, react.useState)("");
|
|
1181
|
+
const [shareTags, setShareTags] = (0, react.useState)("");
|
|
1182
|
+
const [shareLoading, setShareLoading] = (0, react.useState)(false);
|
|
1183
|
+
const [shareBusy, setShareBusy] = (0, react.useState)(false);
|
|
1184
|
+
const [shareError, setShareError] = (0, react.useState)(null);
|
|
1185
|
+
const [reviewScope, setReviewScope] = (0, react.useState)(void 0);
|
|
1186
|
+
const [departments, setDepartments] = (0, react.useState)([]);
|
|
1187
|
+
const [shareVisibility, setShareVisibility] = (0, react.useState)("private");
|
|
1188
|
+
const [shareDepartment, setShareDepartment] = (0, react.useState)(void 0);
|
|
390
1189
|
const useWorkspaces = runtime.useWorkspaces;
|
|
391
1190
|
const workspaces = useWorkspaces === void 0 ? [] : useWorkspaces((snapshot) => snapshot.items);
|
|
392
1191
|
const scope = (0, react.useMemo)(() => {
|
|
@@ -405,9 +1204,59 @@ window.__ModuleLoader__.load({
|
|
|
405
1204
|
});
|
|
406
1205
|
}
|
|
407
1206
|
}, [api, scope]);
|
|
1207
|
+
const loadPlaza = (0, react.useCallback)(async () => {
|
|
1208
|
+
try {
|
|
1209
|
+
const rows = await api.plazaMine();
|
|
1210
|
+
setPlaza({
|
|
1211
|
+
kind: "ready",
|
|
1212
|
+
records: new Map(rows.map((row) => [row.name, row]))
|
|
1213
|
+
});
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
if (error instanceof PlazaUnavailableError) setPlaza({ kind: "unavailable" });
|
|
1216
|
+
else setPlaza({
|
|
1217
|
+
kind: "failed",
|
|
1218
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
}, [api]);
|
|
408
1222
|
(0, react.useEffect)(() => {
|
|
409
1223
|
load();
|
|
410
1224
|
}, [load]);
|
|
1225
|
+
(0, react.useEffect)(() => {
|
|
1226
|
+
loadPlaza();
|
|
1227
|
+
}, [loadPlaza]);
|
|
1228
|
+
const loadConnectors = (0, react.useCallback)(async () => {
|
|
1229
|
+
setConnectors({ kind: "loading" });
|
|
1230
|
+
setConnectorNotice(null);
|
|
1231
|
+
try {
|
|
1232
|
+
setConnectors({
|
|
1233
|
+
kind: "ready",
|
|
1234
|
+
catalogue: await readConnectorCatalogue(connectorSource)
|
|
1235
|
+
});
|
|
1236
|
+
} catch (error) {
|
|
1237
|
+
setConnectors({
|
|
1238
|
+
kind: "failed",
|
|
1239
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
}, [connectorSource]);
|
|
1243
|
+
(0, react.useEffect)(() => {
|
|
1244
|
+
loadConnectors();
|
|
1245
|
+
}, [loadConnectors]);
|
|
1246
|
+
(0, react.useEffect)(() => {
|
|
1247
|
+
let cancelled = false;
|
|
1248
|
+
api.reviewContext().then(async (scope) => {
|
|
1249
|
+
if (cancelled) return;
|
|
1250
|
+
setReviewScope(scope);
|
|
1251
|
+
if (scope.canReviewGlobal === true) {
|
|
1252
|
+
const rows = await api.departments();
|
|
1253
|
+
if (!cancelled) setDepartments(rows);
|
|
1254
|
+
}
|
|
1255
|
+
}).catch(() => {});
|
|
1256
|
+
return () => {
|
|
1257
|
+
cancelled = true;
|
|
1258
|
+
};
|
|
1259
|
+
}, [api]);
|
|
411
1260
|
(0, react.useEffect)(() => {
|
|
412
1261
|
let cancelled = false;
|
|
413
1262
|
api.translationProgress().then((p) => {
|
|
@@ -417,6 +1266,15 @@ window.__ModuleLoader__.load({
|
|
|
417
1266
|
cancelled = true;
|
|
418
1267
|
};
|
|
419
1268
|
}, [api]);
|
|
1269
|
+
const plazaRecords = plaza.kind === "ready" ? plaza.records : /* @__PURE__ */ new Map();
|
|
1270
|
+
const visibilityOptions = allowedVisibilities(reviewScope);
|
|
1271
|
+
const role = scopeRole(reviewScope);
|
|
1272
|
+
const ownCode = ownDepartment(reviewScope);
|
|
1273
|
+
const departmentChoices = role === "admin" && departments.length > 0 ? departments : (reviewScope?.departmentPath ?? []).filter((node) => node.code !== "");
|
|
1274
|
+
const selectableDepartments = role === "admin" ? departmentChoices : ownCode === void 0 ? [] : [{
|
|
1275
|
+
code: ownCode,
|
|
1276
|
+
name: departmentChoices.find((node) => node.code === ownCode)?.name ?? ownCode
|
|
1277
|
+
}];
|
|
420
1278
|
const groups = (0, react.useMemo)(() => {
|
|
421
1279
|
if (state.kind !== "ready") return [];
|
|
422
1280
|
const q = query.trim().toLowerCase();
|
|
@@ -426,6 +1284,32 @@ window.__ModuleLoader__.load({
|
|
|
426
1284
|
skills: g.skills.filter((s) => s.name.toLowerCase().includes(q) || s.description.toLowerCase().includes(q) || (s.i18n?.title ?? "").toLowerCase().includes(q) || (s.i18n?.description ?? "").toLowerCase().includes(q) || (s.i18n?.summary ?? "").toLowerCase().includes(q) || (s.whenToUse ?? "").toLowerCase().includes(q))
|
|
427
1285
|
})).filter((g) => g.skills.length > 0);
|
|
428
1286
|
}, [state, query]);
|
|
1287
|
+
const builtinGroups = (0, react.useMemo)(() => groups.filter((group) => group.key === BUNDLED_GROUP), [groups]);
|
|
1288
|
+
const personalGroups = (0, react.useMemo)(() => groups.filter((group) => group.key !== BUNDLED_GROUP), [groups]);
|
|
1289
|
+
const countOf = (rows) => rows.reduce((count, group) => count + group.skills.length, 0);
|
|
1290
|
+
const connectorCount = connectors.kind === "ready" ? connectors.catalogue.connectors.length : 0;
|
|
1291
|
+
const tabRows = [
|
|
1292
|
+
{
|
|
1293
|
+
value: "builtin",
|
|
1294
|
+
label: t("tab.builtin"),
|
|
1295
|
+
count: countOf(builtinGroups)
|
|
1296
|
+
},
|
|
1297
|
+
{
|
|
1298
|
+
value: "personal",
|
|
1299
|
+
label: t("tab.personal"),
|
|
1300
|
+
count: countOf(personalGroups)
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
value: "plaza",
|
|
1304
|
+
label: t("tab.plaza"),
|
|
1305
|
+
count: 0
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
value: "connectors",
|
|
1309
|
+
label: t("tab.connectors"),
|
|
1310
|
+
count: connectorCount
|
|
1311
|
+
}
|
|
1312
|
+
];
|
|
429
1313
|
const toggle = (0, react.useCallback)(async (skill, enabled) => {
|
|
430
1314
|
if (skill.path === void 0) return;
|
|
431
1315
|
try {
|
|
@@ -455,6 +1339,168 @@ window.__ModuleLoader__.load({
|
|
|
455
1339
|
load,
|
|
456
1340
|
t
|
|
457
1341
|
]);
|
|
1342
|
+
const toggleConnector = (0, react.useCallback)(async (connector, enabled) => {
|
|
1343
|
+
if (connectors.kind !== "ready") return;
|
|
1344
|
+
setConnectorBusyId(connector.id);
|
|
1345
|
+
setConnectorNotice(null);
|
|
1346
|
+
try {
|
|
1347
|
+
if (connectors.catalogue.demo) setConnectors({
|
|
1348
|
+
kind: "ready",
|
|
1349
|
+
catalogue: {
|
|
1350
|
+
demo: true,
|
|
1351
|
+
connectors: connectors.catalogue.connectors.map((row) => row.id === connector.id ? {
|
|
1352
|
+
...row,
|
|
1353
|
+
enabled,
|
|
1354
|
+
connected: enabled
|
|
1355
|
+
} : row)
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
else setConnectors({
|
|
1359
|
+
kind: "ready",
|
|
1360
|
+
catalogue: {
|
|
1361
|
+
demo: false,
|
|
1362
|
+
connectors: await connectorSource.setEnabled(connector.id, enabled)
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
} catch (error) {
|
|
1366
|
+
setConnectorNotice(error instanceof Error ? error.message : String(error));
|
|
1367
|
+
} finally {
|
|
1368
|
+
setConnectorBusyId(null);
|
|
1369
|
+
}
|
|
1370
|
+
}, [connectorSource, connectors]);
|
|
1371
|
+
const toggleCapability = (0, react.useCallback)(async (connector, capability, enabled) => {
|
|
1372
|
+
if (connectors.kind !== "ready") return;
|
|
1373
|
+
setConnectorBusyId(connector.id + ":" + capability.id);
|
|
1374
|
+
setConnectorNotice(null);
|
|
1375
|
+
try {
|
|
1376
|
+
if (connectors.catalogue.demo) setConnectors({
|
|
1377
|
+
kind: "ready",
|
|
1378
|
+
catalogue: {
|
|
1379
|
+
demo: true,
|
|
1380
|
+
connectors: connectors.catalogue.connectors.map((row) => row.id === connector.id ? {
|
|
1381
|
+
...row,
|
|
1382
|
+
capabilities: row.capabilities.map((item) => item.id === capability.id ? {
|
|
1383
|
+
...item,
|
|
1384
|
+
enabled
|
|
1385
|
+
} : item)
|
|
1386
|
+
} : row)
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
else setConnectors({
|
|
1390
|
+
kind: "ready",
|
|
1391
|
+
catalogue: {
|
|
1392
|
+
demo: false,
|
|
1393
|
+
connectors: await connectorSource.setCapability(connector.id, capability.id, enabled)
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
} catch (error) {
|
|
1397
|
+
setConnectorNotice(error instanceof Error ? error.message : String(error));
|
|
1398
|
+
} finally {
|
|
1399
|
+
setConnectorBusyId(null);
|
|
1400
|
+
}
|
|
1401
|
+
}, [connectorSource, connectors]);
|
|
1402
|
+
const openShare = (0, react.useCallback)((skill) => {
|
|
1403
|
+
setShareTarget(skill);
|
|
1404
|
+
setShareInstruction("");
|
|
1405
|
+
setShareTags("");
|
|
1406
|
+
setShareError(null);
|
|
1407
|
+
const choice = sanitizeChoice(readSavedScope(window.localStorage, scopeStorageKey(readAccountIdentity())), reviewScope, departments);
|
|
1408
|
+
setShareVisibility(choice.visibility);
|
|
1409
|
+
setShareDepartment(choice.departmentCode);
|
|
1410
|
+
setShareLoading(true);
|
|
1411
|
+
api.content(skill.name, skill.path, scope).then((payload) => {
|
|
1412
|
+
setShareInstruction(payload.content);
|
|
1413
|
+
}).catch((error) => {
|
|
1414
|
+
setShareError(t("plaza.failed") + ": " + (error instanceof Error ? error.message : String(error)));
|
|
1415
|
+
}).finally(() => {
|
|
1416
|
+
setShareLoading(false);
|
|
1417
|
+
});
|
|
1418
|
+
}, [
|
|
1419
|
+
api,
|
|
1420
|
+
departments,
|
|
1421
|
+
reviewScope,
|
|
1422
|
+
scope,
|
|
1423
|
+
t
|
|
1424
|
+
]);
|
|
1425
|
+
(0, react.useEffect)(() => {
|
|
1426
|
+
if (shareTarget === null || reviewScope === void 0) return;
|
|
1427
|
+
const choice = sanitizeChoice(readSavedScope(window.localStorage, scopeStorageKey(readAccountIdentity())), reviewScope, departments);
|
|
1428
|
+
setShareVisibility(choice.visibility);
|
|
1429
|
+
setShareDepartment(choice.departmentCode);
|
|
1430
|
+
}, [
|
|
1431
|
+
reviewScope,
|
|
1432
|
+
departments,
|
|
1433
|
+
shareTarget
|
|
1434
|
+
]);
|
|
1435
|
+
const closeShare = (0, react.useCallback)(() => {
|
|
1436
|
+
if (shareBusy) return;
|
|
1437
|
+
setShareTarget(null);
|
|
1438
|
+
setShareError(null);
|
|
1439
|
+
}, [shareBusy]);
|
|
1440
|
+
const submitShare = (0, react.useCallback)(async () => {
|
|
1441
|
+
if (shareTarget === null) return;
|
|
1442
|
+
if (shareInstruction.trim() === "") {
|
|
1443
|
+
setShareError(t("plaza.instruction") + " required");
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
setShareBusy(true);
|
|
1447
|
+
setShareError(null);
|
|
1448
|
+
try {
|
|
1449
|
+
const tags = shareTags.split(/[,,]/u).map((tag) => tag.trim()).filter((tag) => tag !== "");
|
|
1450
|
+
const choice = {
|
|
1451
|
+
visibility: shareVisibility,
|
|
1452
|
+
...shareVisibility === "department" && shareDepartment !== void 0 ? { departmentCode: shareDepartment } : {}
|
|
1453
|
+
};
|
|
1454
|
+
await api.plazaSubmit({
|
|
1455
|
+
name: shareTarget.name,
|
|
1456
|
+
description: shareTarget.description,
|
|
1457
|
+
instruction: shareInstruction,
|
|
1458
|
+
...tags.length === 0 ? {} : { tags },
|
|
1459
|
+
...choice
|
|
1460
|
+
});
|
|
1461
|
+
writeSavedScope(window.localStorage, scopeStorageKey(readAccountIdentity()), choice);
|
|
1462
|
+
setShareTarget(null);
|
|
1463
|
+
await loadPlaza();
|
|
1464
|
+
} catch (error) {
|
|
1465
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1466
|
+
if (shareVisibility === "global" && /403|forbidden|权限/i.test(message)) {
|
|
1467
|
+
const fallback = sanitizeChoice({ visibility: "department" }, reviewScope, departments);
|
|
1468
|
+
setShareVisibility(fallback.visibility);
|
|
1469
|
+
setShareDepartment(fallback.departmentCode);
|
|
1470
|
+
setShareError(t("plaza.scopeForbidden"));
|
|
1471
|
+
} else setShareError(error instanceof PlazaUnavailableError ? t("plaza.unavailable") : t("plaza.failed") + ": " + message);
|
|
1472
|
+
} finally {
|
|
1473
|
+
setShareBusy(false);
|
|
1474
|
+
}
|
|
1475
|
+
}, [
|
|
1476
|
+
api,
|
|
1477
|
+
departments,
|
|
1478
|
+
loadPlaza,
|
|
1479
|
+
reviewScope,
|
|
1480
|
+
shareDepartment,
|
|
1481
|
+
shareInstruction,
|
|
1482
|
+
shareTags,
|
|
1483
|
+
shareTarget,
|
|
1484
|
+
shareVisibility,
|
|
1485
|
+
t
|
|
1486
|
+
]);
|
|
1487
|
+
const unshare = (0, react.useCallback)(async (_skill, id) => {
|
|
1488
|
+
if (!window.confirm(t("plaza.unshareConfirm"))) return;
|
|
1489
|
+
setShareBusy(true);
|
|
1490
|
+
setShareError(null);
|
|
1491
|
+
try {
|
|
1492
|
+
await api.plazaUnshare(id);
|
|
1493
|
+
await loadPlaza();
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
setShareError(error instanceof PlazaUnavailableError ? t("plaza.unavailable") : t("plaza.failed") + ": " + (error instanceof Error ? error.message : String(error)));
|
|
1496
|
+
} finally {
|
|
1497
|
+
setShareBusy(false);
|
|
1498
|
+
}
|
|
1499
|
+
}, [
|
|
1500
|
+
api,
|
|
1501
|
+
loadPlaza,
|
|
1502
|
+
t
|
|
1503
|
+
]);
|
|
458
1504
|
/** Bind one draft key to a change handler. */
|
|
459
1505
|
const set = (0, react.useCallback)((key) => (event) => {
|
|
460
1506
|
const value = event.target.value;
|
|
@@ -492,201 +1538,430 @@ window.__ModuleLoader__.load({
|
|
|
492
1538
|
draft,
|
|
493
1539
|
load
|
|
494
1540
|
]);
|
|
495
|
-
const
|
|
496
|
-
|
|
1541
|
+
const visibleGroups = tab === "builtin" ? builtinGroups : personalGroups;
|
|
1542
|
+
const visibleTotal = countOf(visibleGroups);
|
|
1543
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
497
1544
|
className: SkillCenterPage_module_css_default.page,
|
|
498
|
-
children:
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
className: SkillCenterPage_module_css_default.
|
|
503
|
-
children:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
1545
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1546
|
+
className: SkillCenterPage_module_css_default.pageContent,
|
|
1547
|
+
children: [
|
|
1548
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1549
|
+
className: SkillCenterPage_module_css_default.pageHead,
|
|
1550
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
1551
|
+
className: SkillCenterPage_module_css_default.pageTitle,
|
|
1552
|
+
children: t("panel")
|
|
1553
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1554
|
+
className: SkillCenterPage_module_css_default.toolbar,
|
|
1555
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1556
|
+
type: "button",
|
|
1557
|
+
className: SkillCenterPage_module_css_default.iconButton,
|
|
1558
|
+
"aria-label": t("action.refresh"),
|
|
1559
|
+
title: t("action.refresh"),
|
|
1560
|
+
onClick: () => {
|
|
1561
|
+
load();
|
|
1562
|
+
},
|
|
1563
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1564
|
+
className: SkillCenterPage_module_css_default.iconWrap,
|
|
1565
|
+
"aria-hidden": "true",
|
|
1566
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineRegular, {})
|
|
1567
|
+
})
|
|
1568
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1569
|
+
variant: "primary",
|
|
1570
|
+
size: "sm",
|
|
1571
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 13 }),
|
|
1572
|
+
onClick: () => {
|
|
1573
|
+
setCreating((v) => !v);
|
|
1574
|
+
},
|
|
1575
|
+
children: t("action.create")
|
|
1576
|
+
})]
|
|
1577
|
+
})]
|
|
1578
|
+
}),
|
|
1579
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1580
|
+
className: SkillCenterPage_module_css_default.tabs,
|
|
1581
|
+
role: "tablist",
|
|
1582
|
+
"aria-label": t("tab.label"),
|
|
1583
|
+
children: tabRows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
507
1584
|
type: "button",
|
|
508
|
-
|
|
509
|
-
"
|
|
510
|
-
|
|
1585
|
+
role: "tab",
|
|
1586
|
+
id: "skill-center-tab-" + row.value,
|
|
1587
|
+
"aria-selected": tab === row.value,
|
|
1588
|
+
"aria-controls": "skill-center-panel-" + row.value,
|
|
1589
|
+
className: tab === row.value ? SkillCenterPage_module_css_default.tab + " " + SkillCenterPage_module_css_default.tabActive : SkillCenterPage_module_css_default.tab,
|
|
1590
|
+
"data-tab": row.value,
|
|
511
1591
|
onClick: () => {
|
|
512
|
-
|
|
1592
|
+
setTab(row.value);
|
|
1593
|
+
if (row.value === "connectors" && connectors.kind === "failed") loadConnectors();
|
|
513
1594
|
},
|
|
514
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
515
|
-
className: SkillCenterPage_module_css_default.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
1595
|
+
children: [row.label, row.count === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1596
|
+
className: SkillCenterPage_module_css_default.tabCount,
|
|
1597
|
+
children: row.count
|
|
1598
|
+
})]
|
|
1599
|
+
}, row.value))
|
|
1600
|
+
}),
|
|
1601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1602
|
+
open: creating,
|
|
1603
|
+
onClose: () => {
|
|
1604
|
+
setCreating(false);
|
|
1605
|
+
},
|
|
1606
|
+
title: t("create.title"),
|
|
1607
|
+
closeLabel: t("action.cancel"),
|
|
1608
|
+
className: SkillCenterPage_module_css_default.dialog,
|
|
1609
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1610
|
+
variant: "outline",
|
|
1611
|
+
autoFocus: true,
|
|
1612
|
+
onClick: () => {
|
|
1613
|
+
setCreating(false);
|
|
1614
|
+
},
|
|
1615
|
+
children: t("action.cancel")
|
|
519
1616
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
520
1617
|
variant: "primary",
|
|
521
|
-
size: "sm",
|
|
522
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { size: 13 }),
|
|
523
1618
|
onClick: () => {
|
|
524
|
-
|
|
1619
|
+
submit();
|
|
525
1620
|
},
|
|
526
|
-
children: t("action.
|
|
527
|
-
})]
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
1621
|
+
children: t("action.confirm")
|
|
1622
|
+
})] }),
|
|
1623
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1624
|
+
className: SkillCenterPage_module_css_default.form,
|
|
1625
|
+
children: [
|
|
1626
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1627
|
+
label: t("create.name"),
|
|
1628
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1629
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1630
|
+
value: draft.name,
|
|
1631
|
+
onChange: set("name")
|
|
1632
|
+
})
|
|
1633
|
+
}),
|
|
1634
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1635
|
+
label: t("create.description"),
|
|
1636
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1637
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1638
|
+
value: draft.description,
|
|
1639
|
+
onChange: set("description")
|
|
1640
|
+
})
|
|
1641
|
+
}),
|
|
1642
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1643
|
+
label: t("create.whenToUse"),
|
|
1644
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1645
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1646
|
+
value: draft.whenToUse,
|
|
1647
|
+
onChange: set("whenToUse")
|
|
1648
|
+
})
|
|
1649
|
+
}),
|
|
1650
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1651
|
+
label: t("create.content"),
|
|
1652
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
1653
|
+
className: SkillCenterPage_module_css_default.textarea,
|
|
1654
|
+
value: draft.content,
|
|
1655
|
+
onChange: set("content")
|
|
1656
|
+
})
|
|
1657
|
+
}),
|
|
1658
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1659
|
+
label: t("create.root"),
|
|
1660
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
1661
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1662
|
+
value: draft.root,
|
|
1663
|
+
onChange: (e) => {
|
|
1664
|
+
setDraft((d) => ({
|
|
1665
|
+
...d,
|
|
1666
|
+
root: e.target.value === "project" ? "project" : "user"
|
|
1667
|
+
}));
|
|
1668
|
+
},
|
|
1669
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1670
|
+
value: "user",
|
|
1671
|
+
children: t("create.rootUser")
|
|
1672
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1673
|
+
value: "project",
|
|
1674
|
+
children: t("create.rootProject")
|
|
1675
|
+
})]
|
|
1676
|
+
})
|
|
561
1677
|
})
|
|
1678
|
+
]
|
|
1679
|
+
})
|
|
1680
|
+
}),
|
|
1681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1682
|
+
open: shareTarget !== null,
|
|
1683
|
+
onClose: closeShare,
|
|
1684
|
+
title: t("plaza.dialogTitle"),
|
|
1685
|
+
headless: true,
|
|
1686
|
+
className: SkillCenterPage_module_css_default.publishDialog,
|
|
1687
|
+
children: [
|
|
1688
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
1689
|
+
className: SkillCenterPage_module_css_default.dialogHeader,
|
|
1690
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1691
|
+
className: SkillCenterPage_module_css_default.dialogTitle,
|
|
1692
|
+
children: t("plaza.dialogTitle")
|
|
1693
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1694
|
+
type: "button",
|
|
1695
|
+
className: SkillCenterPage_module_css_default.dialogClose,
|
|
1696
|
+
"aria-label": t("action.close"),
|
|
1697
|
+
onClick: closeShare,
|
|
1698
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, { size: 14 })
|
|
1699
|
+
})]
|
|
562
1700
|
}),
|
|
563
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
1701
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1702
|
+
className: SkillCenterPage_module_css_default.dialogBody,
|
|
1703
|
+
"data-publish-body": true,
|
|
1704
|
+
children: shareTarget === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1705
|
+
className: SkillCenterPage_module_css_default.form,
|
|
1706
|
+
"data-share-dialog": shareTarget.name,
|
|
1707
|
+
children: [
|
|
1708
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1709
|
+
label: t("create.name"),
|
|
1710
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1711
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1712
|
+
value: shareTarget.name,
|
|
1713
|
+
readOnly: true
|
|
1714
|
+
})
|
|
1715
|
+
}),
|
|
1716
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1717
|
+
label: t("create.description"),
|
|
1718
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1719
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1720
|
+
value: shareTarget.description,
|
|
1721
|
+
readOnly: true
|
|
1722
|
+
})
|
|
1723
|
+
}),
|
|
1724
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1725
|
+
label: t("plaza.tags"),
|
|
1726
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1727
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1728
|
+
value: shareTags,
|
|
1729
|
+
placeholder: t("plaza.tagsPlaceholder"),
|
|
1730
|
+
onChange: (event) => {
|
|
1731
|
+
setShareTags(event.target.value);
|
|
1732
|
+
}
|
|
1733
|
+
})
|
|
1734
|
+
}),
|
|
1735
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1736
|
+
label: t("plaza.visibility"),
|
|
1737
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
1738
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1739
|
+
value: shareVisibility,
|
|
1740
|
+
"data-share-visibility": true,
|
|
1741
|
+
onChange: (event) => {
|
|
1742
|
+
const visibility = event.target.value;
|
|
1743
|
+
setShareVisibility(visibility);
|
|
1744
|
+
if (visibility === "department") setShareDepartment(shareDepartment ?? ownCode ?? selectableDepartments[0]?.code);
|
|
1745
|
+
},
|
|
1746
|
+
children: [
|
|
1747
|
+
visibilityOptions.includes("global") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1748
|
+
value: "global",
|
|
1749
|
+
children: t("plaza.visibilityGlobal")
|
|
1750
|
+
}) : null,
|
|
1751
|
+
visibilityOptions.includes("department") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1752
|
+
value: "department",
|
|
1753
|
+
children: t("plaza.visibilityDepartment")
|
|
1754
|
+
}) : null,
|
|
1755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1756
|
+
value: "private",
|
|
1757
|
+
children: t("plaza.visibilityPrivate")
|
|
1758
|
+
})
|
|
1759
|
+
]
|
|
1760
|
+
})
|
|
1761
|
+
}),
|
|
1762
|
+
shareVisibility === "department" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1763
|
+
label: t("plaza.department"),
|
|
1764
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
1765
|
+
className: SkillCenterPage_module_css_default.input,
|
|
1766
|
+
value: shareDepartment ?? selectableDepartments[0]?.code ?? "",
|
|
1767
|
+
"data-share-department": true,
|
|
1768
|
+
disabled: role !== "admin" || selectableDepartments.length <= 1,
|
|
1769
|
+
onChange: (event) => {
|
|
1770
|
+
setShareDepartment(event.target.value);
|
|
1771
|
+
},
|
|
1772
|
+
children: selectableDepartments.map((department) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1773
|
+
value: department.code,
|
|
1774
|
+
children: department.name
|
|
1775
|
+
}, department.code))
|
|
1776
|
+
})
|
|
1777
|
+
}) : null,
|
|
1778
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1779
|
+
className: SkillCenterPage_module_css_default.plazaScopeHint,
|
|
1780
|
+
children: role === "admin" ? t("plaza.scopeHintAdmin") : t("plaza.scopeHintUser")
|
|
1781
|
+
}),
|
|
1782
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftField, {
|
|
1783
|
+
label: t("plaza.instruction"),
|
|
1784
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
1785
|
+
className: SkillCenterPage_module_css_default.textarea,
|
|
1786
|
+
value: shareInstruction,
|
|
1787
|
+
readOnly: shareLoading,
|
|
1788
|
+
placeholder: shareLoading ? t("plaza.contentLoading") : void 0,
|
|
1789
|
+
onChange: (event) => {
|
|
1790
|
+
setShareInstruction(event.target.value);
|
|
1791
|
+
}
|
|
1792
|
+
})
|
|
1793
|
+
}),
|
|
1794
|
+
shareError === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1795
|
+
className: SkillCenterPage_module_css_default.status + " " + SkillCenterPage_module_css_default.statusError,
|
|
1796
|
+
role: "alert",
|
|
1797
|
+
children: shareError
|
|
1798
|
+
})
|
|
1799
|
+
]
|
|
569
1800
|
})
|
|
570
1801
|
}),
|
|
571
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
572
|
-
|
|
573
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
1802
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
|
|
1803
|
+
className: SkillCenterPage_module_css_default.dialogFooter,
|
|
1804
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1805
|
+
variant: "outline",
|
|
1806
|
+
disabled: shareBusy,
|
|
1807
|
+
onClick: closeShare,
|
|
1808
|
+
children: t("action.cancel")
|
|
1809
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1810
|
+
variant: "primary",
|
|
1811
|
+
disabled: shareBusy || shareLoading,
|
|
1812
|
+
onClick: () => {
|
|
1813
|
+
submitShare();
|
|
1814
|
+
},
|
|
1815
|
+
children: t("plaza.submit")
|
|
1816
|
+
})]
|
|
1817
|
+
})
|
|
1818
|
+
]
|
|
1819
|
+
}),
|
|
1820
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1821
|
+
className: SkillCenterPage_module_css_default.searchField,
|
|
1822
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
1823
|
+
type: "search",
|
|
1824
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, {}),
|
|
1825
|
+
placeholder: tab === "connectors" ? t("search.connectorPlaceholder") : t("search.placeholder"),
|
|
1826
|
+
"aria-label": tab === "connectors" ? t("search.connectorPlaceholder") : t("search.placeholder"),
|
|
1827
|
+
value: query,
|
|
1828
|
+
onChange: (e) => {
|
|
1829
|
+
setQuery(e.target.value);
|
|
1830
|
+
}
|
|
1831
|
+
}), query === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1832
|
+
size: "sm",
|
|
1833
|
+
variant: "ghost",
|
|
1834
|
+
className: SkillCenterPage_module_css_default.searchClear,
|
|
1835
|
+
"aria-label": t("search.clear"),
|
|
1836
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16, {}),
|
|
1837
|
+
onClick: () => {
|
|
1838
|
+
setQuery("");
|
|
1839
|
+
}
|
|
1840
|
+
})]
|
|
1841
|
+
}),
|
|
1842
|
+
tab !== "connectors" && plaza.kind === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1843
|
+
className: SkillCenterPage_module_css_default.status,
|
|
1844
|
+
role: "status",
|
|
1845
|
+
"data-plaza-unavailable": true,
|
|
1846
|
+
children: t("plaza.unavailable")
|
|
1847
|
+
}) : null,
|
|
1848
|
+
shareError !== null && shareTarget === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1849
|
+
className: SkillCenterPage_module_css_default.status + " " + SkillCenterPage_module_css_default.statusError,
|
|
1850
|
+
role: "alert",
|
|
1851
|
+
children: shareError
|
|
1852
|
+
}) : null,
|
|
1853
|
+
connectorNotice === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1854
|
+
className: SkillCenterPage_module_css_default.status + " " + SkillCenterPage_module_css_default.statusError,
|
|
1855
|
+
role: "alert",
|
|
1856
|
+
children: connectorNotice
|
|
1857
|
+
}),
|
|
1858
|
+
(tab === "builtin" || tab === "personal") && progress !== void 0 && progress.done < progress.total ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1859
|
+
className: SkillCenterPage_module_css_default.progressRow,
|
|
1860
|
+
children: [
|
|
1861
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1862
|
+
className: SkillCenterPage_module_css_default.progressLabel,
|
|
1863
|
+
children: t("translate.label")
|
|
578
1864
|
}),
|
|
579
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
580
|
-
|
|
581
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
582
|
-
className: SkillCenterPage_module_css_default.
|
|
583
|
-
|
|
584
|
-
onChange: set("content")
|
|
1865
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1866
|
+
className: SkillCenterPage_module_css_default.progressTrack,
|
|
1867
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1868
|
+
className: SkillCenterPage_module_css_default.progressFill,
|
|
1869
|
+
style: { width: String(progress.total === 0 ? 0 : Math.round(progress.done / progress.total * 100)) + "%" }
|
|
585
1870
|
})
|
|
586
1871
|
}),
|
|
587
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
588
|
-
|
|
589
|
-
children:
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
...d,
|
|
595
|
-
root: e.target.value === "project" ? "project" : "user"
|
|
596
|
-
}));
|
|
597
|
-
},
|
|
598
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
599
|
-
value: "user",
|
|
600
|
-
children: t("create.rootUser")
|
|
601
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
602
|
-
value: "project",
|
|
603
|
-
children: t("create.rootProject")
|
|
604
|
-
})]
|
|
605
|
-
})
|
|
1872
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1873
|
+
className: SkillCenterPage_module_css_default.progressCount,
|
|
1874
|
+
children: [
|
|
1875
|
+
progress.done,
|
|
1876
|
+
" / ",
|
|
1877
|
+
progress.total
|
|
1878
|
+
]
|
|
606
1879
|
})
|
|
607
1880
|
]
|
|
1881
|
+
}) : null,
|
|
1882
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1883
|
+
className: SkillCenterPage_module_css_default.tabPanel,
|
|
1884
|
+
id: "skill-center-panel-" + tab,
|
|
1885
|
+
role: "tabpanel",
|
|
1886
|
+
"aria-labelledby": "skill-center-tab-" + tab,
|
|
1887
|
+
"data-tab-panel": tab,
|
|
1888
|
+
children: [
|
|
1889
|
+
tab === "builtin" || tab === "personal" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
1890
|
+
state.kind === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1891
|
+
className: SkillCenterPage_module_css_default.status,
|
|
1892
|
+
children: t("state.loading")
|
|
1893
|
+
}) : null,
|
|
1894
|
+
state.kind === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1895
|
+
className: SkillCenterPage_module_css_default.status + " " + SkillCenterPage_module_css_default.statusError,
|
|
1896
|
+
children: [
|
|
1897
|
+
t("state.failed"),
|
|
1898
|
+
": ",
|
|
1899
|
+
state.message
|
|
1900
|
+
]
|
|
1901
|
+
}) : null,
|
|
1902
|
+
state.kind === "ready" && visibleTotal === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1903
|
+
className: SkillCenterPage_module_css_default.status,
|
|
1904
|
+
children: query.trim() === "" ? t("state.empty") : t("search.noMatches")
|
|
1905
|
+
}) : null,
|
|
1906
|
+
visibleGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1907
|
+
className: SkillCenterPage_module_css_default.group,
|
|
1908
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
|
|
1909
|
+
className: SkillCenterPage_module_css_default.groupTitle,
|
|
1910
|
+
children: [group.title, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1911
|
+
className: SkillCenterPage_module_css_default.groupCount,
|
|
1912
|
+
children: group.skills.length
|
|
1913
|
+
})]
|
|
1914
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1915
|
+
className: SkillCenterPage_module_css_default.cards,
|
|
1916
|
+
children: group.skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillCard, {
|
|
1917
|
+
skill,
|
|
1918
|
+
api,
|
|
1919
|
+
cwd: state.kind === "ready" ? state.payload.cwd : scope,
|
|
1920
|
+
t,
|
|
1921
|
+
share: shareOf(skill.name, plazaRecords),
|
|
1922
|
+
shareBusy,
|
|
1923
|
+
shareDisabled: plaza.kind === "unavailable",
|
|
1924
|
+
onToggle: (s, enabled) => {
|
|
1925
|
+
toggle(s, enabled);
|
|
1926
|
+
},
|
|
1927
|
+
onDelete: (s) => {
|
|
1928
|
+
remove(s);
|
|
1929
|
+
},
|
|
1930
|
+
onShare: openShare,
|
|
1931
|
+
onUnshare: (s, id) => {
|
|
1932
|
+
unshare(s, id);
|
|
1933
|
+
}
|
|
1934
|
+
}, group.key + ":" + skill.name))
|
|
1935
|
+
})]
|
|
1936
|
+
}, group.key))
|
|
1937
|
+
] }) : null,
|
|
1938
|
+
tab === "plaza" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1939
|
+
className: SkillCenterPage_module_css_default.plazaPanel,
|
|
1940
|
+
"data-plaza-panel": true,
|
|
1941
|
+
children: renderSlot("skill-center.section", { query }, { fallback: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1942
|
+
className: SkillCenterPage_module_css_default.status,
|
|
1943
|
+
children: t("plaza.sectionFallback")
|
|
1944
|
+
}) })
|
|
1945
|
+
}) : null,
|
|
1946
|
+
tab === "connectors" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorsTab, {
|
|
1947
|
+
state: connectors,
|
|
1948
|
+
query,
|
|
1949
|
+
busyId: connectorBusyId,
|
|
1950
|
+
t,
|
|
1951
|
+
onRetry: () => {
|
|
1952
|
+
loadConnectors();
|
|
1953
|
+
},
|
|
1954
|
+
onToggleConnector: (connector, enabled) => {
|
|
1955
|
+
toggleConnector(connector, enabled);
|
|
1956
|
+
},
|
|
1957
|
+
onToggleCapability: (connector, capability, enabled) => {
|
|
1958
|
+
toggleCapability(connector, capability, enabled);
|
|
1959
|
+
}
|
|
1960
|
+
}) : null
|
|
1961
|
+
]
|
|
608
1962
|
})
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
className: SkillCenterPage_module_css_default.search,
|
|
612
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, {}),
|
|
613
|
-
placeholder: t("search.placeholder"),
|
|
614
|
-
"aria-label": t("search.placeholder"),
|
|
615
|
-
value: query,
|
|
616
|
-
onChange: (e) => {
|
|
617
|
-
setQuery(e.target.value);
|
|
618
|
-
}
|
|
619
|
-
}),
|
|
620
|
-
progress === void 0 || progress.done >= progress.total ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
621
|
-
className: SkillCenterPage_module_css_default.progressRow,
|
|
622
|
-
children: [
|
|
623
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
624
|
-
className: SkillCenterPage_module_css_default.progressLabel,
|
|
625
|
-
children: t("translate.label")
|
|
626
|
-
}),
|
|
627
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
628
|
-
className: SkillCenterPage_module_css_default.progressTrack,
|
|
629
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
630
|
-
className: SkillCenterPage_module_css_default.progressFill,
|
|
631
|
-
style: { width: String(progress.total === 0 ? 0 : Math.round(progress.done / progress.total * 100)) + "%" }
|
|
632
|
-
})
|
|
633
|
-
}),
|
|
634
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
635
|
-
className: SkillCenterPage_module_css_default.progressCount,
|
|
636
|
-
children: [
|
|
637
|
-
progress.done,
|
|
638
|
-
" / ",
|
|
639
|
-
progress.total
|
|
640
|
-
]
|
|
641
|
-
})
|
|
642
|
-
]
|
|
643
|
-
}),
|
|
644
|
-
state.kind === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
645
|
-
className: SkillCenterPage_module_css_default.status,
|
|
646
|
-
children: t("state.loading")
|
|
647
|
-
}) : null,
|
|
648
|
-
state.kind === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
649
|
-
className: SkillCenterPage_module_css_default.status + " " + SkillCenterPage_module_css_default.statusError,
|
|
650
|
-
children: [
|
|
651
|
-
t("state.failed"),
|
|
652
|
-
": ",
|
|
653
|
-
state.message
|
|
654
|
-
]
|
|
655
|
-
}) : null,
|
|
656
|
-
state.kind === "ready" && groups.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
657
|
-
className: SkillCenterPage_module_css_default.status,
|
|
658
|
-
children: query.trim() === "" ? t("state.empty") : t("search.noMatches")
|
|
659
|
-
}) : null,
|
|
660
|
-
state.kind === "ready" && groups.length > 0 && total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
661
|
-
className: SkillCenterPage_module_css_default.status,
|
|
662
|
-
children: t("state.empty")
|
|
663
|
-
}) : null,
|
|
664
|
-
groups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
665
|
-
className: SkillCenterPage_module_css_default.group,
|
|
666
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
|
|
667
|
-
className: SkillCenterPage_module_css_default.groupTitle,
|
|
668
|
-
children: [group.title, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
669
|
-
className: SkillCenterPage_module_css_default.groupCount,
|
|
670
|
-
children: group.skills.length
|
|
671
|
-
})]
|
|
672
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
673
|
-
className: SkillCenterPage_module_css_default.cards,
|
|
674
|
-
children: group.skills.map((skill) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillCard, {
|
|
675
|
-
skill,
|
|
676
|
-
api,
|
|
677
|
-
cwd: state.kind === "ready" ? state.payload.cwd : scope,
|
|
678
|
-
t,
|
|
679
|
-
onToggle: (s, enabled) => {
|
|
680
|
-
toggle(s, enabled);
|
|
681
|
-
},
|
|
682
|
-
onDelete: (s) => {
|
|
683
|
-
remove(s);
|
|
684
|
-
}
|
|
685
|
-
}, group.key + ":" + skill.name))
|
|
686
|
-
})]
|
|
687
|
-
}, group.key)),
|
|
688
|
-
renderSlot("skill-center.section", { query })
|
|
689
|
-
]
|
|
1963
|
+
]
|
|
1964
|
+
})
|
|
690
1965
|
});
|
|
691
1966
|
}
|
|
692
1967
|
//#endregion
|
|
@@ -704,8 +1979,15 @@ window.__ModuleLoader__.load({
|
|
|
704
1979
|
/** Simplified Chinese dictionary. */
|
|
705
1980
|
const zh = {
|
|
706
1981
|
"panel": "技能中心",
|
|
1982
|
+
"tab.label": "技能分类",
|
|
1983
|
+
"tab.builtin": "内置",
|
|
1984
|
+
"tab.personal": "个人",
|
|
1985
|
+
"tab.plaza": "技能广场",
|
|
1986
|
+
"tab.connectors": "连接器",
|
|
707
1987
|
"search.placeholder": "搜索技能…",
|
|
1988
|
+
"search.connectorPlaceholder": "搜索连接器…",
|
|
708
1989
|
"search.noMatches": "无匹配技能",
|
|
1990
|
+
"search.clear": "清空搜索",
|
|
709
1991
|
"action.refresh": "刷新",
|
|
710
1992
|
"action.create": "新建技能",
|
|
711
1993
|
"action.delete": "删除",
|
|
@@ -737,13 +2019,64 @@ window.__ModuleLoader__.load({
|
|
|
737
2019
|
"create.root": "位置",
|
|
738
2020
|
"create.rootUser": "用户级",
|
|
739
2021
|
"create.rootProject": "项目级",
|
|
740
|
-
"delete.confirm": "删除后可从 .trash 恢复。确定删除?"
|
|
2022
|
+
"delete.confirm": "删除后可从 .trash 恢复。确定删除?",
|
|
2023
|
+
"plaza.statusLocal": "未共享",
|
|
2024
|
+
"plaza.statusPending": "待审核",
|
|
2025
|
+
"plaza.statusApproved": "已上架",
|
|
2026
|
+
"plaza.statusRejected": "已驳回",
|
|
2027
|
+
"plaza.sharedTag": "已共享",
|
|
2028
|
+
"plaza.share": "上架",
|
|
2029
|
+
"plaza.resubmit": "重新提交",
|
|
2030
|
+
"plaza.unshare": "取消共享",
|
|
2031
|
+
"plaza.unavailable": "共享服务未就绪,暂时无法上架",
|
|
2032
|
+
"plaza.failed": "共享操作失败",
|
|
2033
|
+
"plaza.dialogTitle": "上架到技能广场",
|
|
2034
|
+
"plaza.tags": "标签",
|
|
2035
|
+
"plaza.tagsPlaceholder": "用逗号分隔,例如:数据,SQL",
|
|
2036
|
+
"plaza.instruction": "技能内容",
|
|
2037
|
+
"plaza.submit": "提交审核",
|
|
2038
|
+
"plaza.unshareConfirm": "确定取消共享?",
|
|
2039
|
+
"plaza.reason": "审核意见",
|
|
2040
|
+
"plaza.contentLoading": "正在读取技能内容…",
|
|
2041
|
+
"plaza.visibility": "可见范围",
|
|
2042
|
+
"plaza.visibilityGlobal": "全局(所有人可见)",
|
|
2043
|
+
"plaza.visibilityDepartment": "部门专属",
|
|
2044
|
+
"plaza.visibilityPrivate": "私有(仅自己可见)",
|
|
2045
|
+
"plaza.department": "部门",
|
|
2046
|
+
"plaza.scopeForbidden": "无权选择该范围,请改用部门专属或私有",
|
|
2047
|
+
"plaza.scopeHintAdmin": "超管/管理员可选全局或任意部门",
|
|
2048
|
+
"plaza.scopeHintUser": "普通用户/部门管理员只能选本部门或私有",
|
|
2049
|
+
"plaza.sectionFallback": "技能广场服务未就绪,暂时无法浏览",
|
|
2050
|
+
"connector.loading": "正在加载连接器…",
|
|
2051
|
+
"connector.failed": "连接器加载失败",
|
|
2052
|
+
"connector.retry": "重试",
|
|
2053
|
+
"connector.demo": "当前显示示例连接器,后端接入后自动替换",
|
|
2054
|
+
"connector.demoTag": "示例",
|
|
2055
|
+
"connector.enabled": "已启用",
|
|
2056
|
+
"connector.disabled": "未启用",
|
|
2057
|
+
"connector.connected": "已连接",
|
|
2058
|
+
"connector.error": "连接异常",
|
|
2059
|
+
"connector.enable": "启用",
|
|
2060
|
+
"connector.disable": "停用",
|
|
2061
|
+
"connector.capabilities": "能力",
|
|
2062
|
+
"connector.noCapabilities": "当前账号没有可用的连接器能力",
|
|
2063
|
+
"connector.empty": "暂无连接器",
|
|
2064
|
+
"connector.noMatches": "无匹配连接器",
|
|
2065
|
+
"connector.unavailable": "暂不可用",
|
|
2066
|
+
"connector.busy": "处理中…"
|
|
741
2067
|
};
|
|
742
2068
|
/** English dictionary. */
|
|
743
2069
|
const en = {
|
|
744
2070
|
"panel": "Skill Center",
|
|
2071
|
+
"tab.label": "Skill sections",
|
|
2072
|
+
"tab.builtin": "Built-in",
|
|
2073
|
+
"tab.personal": "Personal",
|
|
2074
|
+
"tab.plaza": "Skill plaza",
|
|
2075
|
+
"tab.connectors": "Connectors",
|
|
745
2076
|
"search.placeholder": "Search skills…",
|
|
2077
|
+
"search.connectorPlaceholder": "Search connectors…",
|
|
746
2078
|
"search.noMatches": "No matching skills",
|
|
2079
|
+
"search.clear": "Clear search",
|
|
747
2080
|
"action.refresh": "Refresh",
|
|
748
2081
|
"action.create": "New skill",
|
|
749
2082
|
"action.delete": "Delete",
|
|
@@ -775,7 +2108,51 @@ window.__ModuleLoader__.load({
|
|
|
775
2108
|
"create.root": "Location",
|
|
776
2109
|
"create.rootUser": "User",
|
|
777
2110
|
"create.rootProject": "Project",
|
|
778
|
-
"delete.confirm": "Deleting moves it into .trash, where it can be restored. Delete?"
|
|
2111
|
+
"delete.confirm": "Deleting moves it into .trash, where it can be restored. Delete?",
|
|
2112
|
+
"plaza.statusLocal": "Local",
|
|
2113
|
+
"plaza.statusPending": "Pending review",
|
|
2114
|
+
"plaza.statusApproved": "Published",
|
|
2115
|
+
"plaza.statusRejected": "Rejected",
|
|
2116
|
+
"plaza.sharedTag": "Shared",
|
|
2117
|
+
"plaza.share": "Publish",
|
|
2118
|
+
"plaza.resubmit": "Resubmit",
|
|
2119
|
+
"plaza.unshare": "Unshare",
|
|
2120
|
+
"plaza.unavailable": "Sharing service is not ready; publishing is disabled",
|
|
2121
|
+
"plaza.failed": "Sharing action failed",
|
|
2122
|
+
"plaza.dialogTitle": "Publish to skill plaza",
|
|
2123
|
+
"plaza.tags": "Tags",
|
|
2124
|
+
"plaza.tagsPlaceholder": "Comma separated, e.g. data, SQL",
|
|
2125
|
+
"plaza.instruction": "Skill content",
|
|
2126
|
+
"plaza.submit": "Submit for review",
|
|
2127
|
+
"plaza.unshareConfirm": "Stop sharing this skill?",
|
|
2128
|
+
"plaza.reason": "Review note",
|
|
2129
|
+
"plaza.contentLoading": "Loading skill content…",
|
|
2130
|
+
"plaza.visibility": "Visibility",
|
|
2131
|
+
"plaza.visibilityGlobal": "Global (everyone)",
|
|
2132
|
+
"plaza.visibilityDepartment": "Department only",
|
|
2133
|
+
"plaza.visibilityPrivate": "Private (only me)",
|
|
2134
|
+
"plaza.department": "Department",
|
|
2135
|
+
"plaza.scopeForbidden": "You cannot use that visibility; pick department or private",
|
|
2136
|
+
"plaza.scopeHintAdmin": "Super admins/admins may publish globally or to any department",
|
|
2137
|
+
"plaza.scopeHintUser": "Users and department admins may publish to their own department or privately",
|
|
2138
|
+
"plaza.sectionFallback": "The skill plaza is not available yet",
|
|
2139
|
+
"connector.loading": "Loading connectors…",
|
|
2140
|
+
"connector.failed": "Could not load connectors",
|
|
2141
|
+
"connector.retry": "Retry",
|
|
2142
|
+
"connector.demo": "Showing demo connectors until the backend supplies the catalogue",
|
|
2143
|
+
"connector.demoTag": "Demo",
|
|
2144
|
+
"connector.enabled": "Enabled",
|
|
2145
|
+
"connector.disabled": "Disabled",
|
|
2146
|
+
"connector.connected": "Connected",
|
|
2147
|
+
"connector.error": "Connection error",
|
|
2148
|
+
"connector.enable": "Enable",
|
|
2149
|
+
"connector.disable": "Disable",
|
|
2150
|
+
"connector.capabilities": "Capabilities",
|
|
2151
|
+
"connector.noCapabilities": "This account has no available connector capabilities",
|
|
2152
|
+
"connector.empty": "No connectors",
|
|
2153
|
+
"connector.noMatches": "No matching connectors",
|
|
2154
|
+
"connector.unavailable": "Unavailable",
|
|
2155
|
+
"connector.busy": "Working…"
|
|
779
2156
|
};
|
|
780
2157
|
//#endregion
|
|
781
2158
|
//#region src/client/index.ts
|