@michengai/dsh-skills-manager 0.1.17 → 0.1.18
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/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/lib/client.js +251 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -165,3 +165,4 @@ npm run pack:check
|
|
|
165
165
|
Project status, usage boundaries, architecture, and iteration records begin at the [documentation entry point](docs/00-交接入口/00-阅读导航.md). The detailed operational guide is `docs\02-产品与业务\01-使用说明.md`.
|
|
166
166
|
|
|
167
167
|
Licensed under [Apache License 2.0](LICENSE).
|
|
168
|
+
|
package/README.zh-CN.md
CHANGED
package/lib/client.js
CHANGED
|
@@ -40,6 +40,16 @@ window.__ModuleLoader__.load({
|
|
|
40
40
|
"summary.enabled.one": "个已启用",
|
|
41
41
|
"summary.enabled.other": "个已启用",
|
|
42
42
|
"summary.group": "{count} 个",
|
|
43
|
+
"filter.category": "分类",
|
|
44
|
+
"filter.all": "全部",
|
|
45
|
+
"filter.option": "{name}({count})",
|
|
46
|
+
"filter.showing.one": "显示 {count} 个",
|
|
47
|
+
"filter.showing.other": "显示 {count} 个",
|
|
48
|
+
"search": "搜索",
|
|
49
|
+
"search.placeholder": "名称、形态或简介",
|
|
50
|
+
"search.clear": "清除搜索",
|
|
51
|
+
"empty.search": "没有匹配的插件。试试其他关键词,或切换到「{all}」。",
|
|
52
|
+
"empty.search.reset": "清除筛选",
|
|
43
53
|
"note.missing": "未提供简介",
|
|
44
54
|
"empty.dir.uncreated": "目录尚未创建,上传第一个插件后会自动创建。",
|
|
45
55
|
"empty.dir.missing": "公共目录不存在。",
|
|
@@ -128,6 +138,16 @@ window.__ModuleLoader__.load({
|
|
|
128
138
|
"summary.enabled.one": "enabled",
|
|
129
139
|
"summary.enabled.other": "enabled",
|
|
130
140
|
"summary.group": "{count} items",
|
|
141
|
+
"filter.category": "Category",
|
|
142
|
+
"filter.all": "All",
|
|
143
|
+
"filter.option": "{name} ({count})",
|
|
144
|
+
"filter.showing.one": "Showing {count} skill",
|
|
145
|
+
"filter.showing.other": "Showing {count} skills",
|
|
146
|
+
"search": "Search",
|
|
147
|
+
"search.placeholder": "Name, kind, or description",
|
|
148
|
+
"search.clear": "Clear search",
|
|
149
|
+
"empty.search": "No matching plugins. Try another keyword, or switch to {all}.",
|
|
150
|
+
"empty.search.reset": "Clear filters",
|
|
131
151
|
"note.missing": "No description provided",
|
|
132
152
|
"empty.dir.uncreated": "The directory has not been created yet; it will be created automatically after the first upload.",
|
|
133
153
|
"empty.dir.missing": "The public directory does not exist.",
|
|
@@ -202,7 +222,8 @@ window.__ModuleLoader__.load({
|
|
|
202
222
|
.dssm-row{display:flex;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--dsw-alias-border-l1)}.dssm-row:last-child{border-bottom:0}.dssm-row-main{display:flex;min-width:0;flex:1;flex-direction:column;gap:3px}.dssm-row-id{display:flex;align-items:center;gap:7px;min-width:0}.dssm-row-name{overflow:hidden;font-size:13px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.dssm-tag{flex:none;padding:1px 6px;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:16px}.dssm-tag-on{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.dssm-tag-off{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.dssm-note{overflow:hidden;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.dssm-empty{padding:28px 16px;color:var(--dsw-alias-label-tertiary);font-size:13px;text-align:center}.dssm-error{color:var(--dsw-alias-state-error-primary);font-size:13px;line-height:20px}
|
|
203
223
|
.dssm-mask{position:fixed;z-index:1100;inset:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:100%;height:100%;padding:24px;background:rgba(0,0,0,.58)}.dssm-modal{box-sizing:border-box;display:flex;width:min(480px,100%)!important;height:auto!important;max-width:100%;max-height:100%;min-width:0;min-height:0;flex:0 0 auto!important;align-self:center!important;flex-direction:column;gap:18px;padding:24px;overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:16px;background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-shadow-lv3)}.dssm-modal-upload{width:min(480px,100%)!important;height:auto!important;max-width:100%;max-height:100%;align-self:center!important;flex:0 0 auto!important;overflow:auto}.dssm-modal-head{display:flex;align-items:center;gap:12px}.dssm-modal-title{margin:0;flex:1;font-size:17px;line-height:24px;font-weight:650}.dssm-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:0;border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:20px;line-height:1;cursor:pointer}.dssm-icon-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
204
224
|
.dssm-dropzone{box-sizing:border-box;display:flex;width:100%;min-height:144px;flex:none;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:18px;border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);cursor:pointer;transition:border-color 180ms ease,background 180ms ease}.dssm-dropzone:hover,.dssm-dropzone-active{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-interactive-bg-hover)}.dssm-dropzone-title{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:560}.dssm-dropzone-copy{font-size:12px;line-height:18px;text-align:center}.dssm-file{display:flex;align-items:center;gap:8px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-primary);font-size:13px}.dssm-file-name{overflow:hidden;flex:1;text-overflow:ellipsis;white-space:nowrap}.dssm-modal-head,.dssm-file,.dssm-modal-actions{flex:none}.dssm-modal-actions{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px}.dssm-hidden-input{display:none}
|
|
205
|
-
|
|
225
|
+
.dssm-filters{display:flex;align-items:flex-end;gap:10px}.dssm-field{display:flex;min-width:0;flex:1;flex-direction:column;gap:6px}.dssm-field-category{flex:0 1 220px}.dssm-field-search{flex:1 1 240px}.dssm-label{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px}.dssm-control{box-sizing:border-box;width:100%;min-height:32px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}.dssm-control:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dssm-select{position:relative}.dssm-select-trigger{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:32px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer}.dssm-select-trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.dssm-select-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dssm-select-trigger[aria-expanded="true"]{border-color:var(--dsw-alias-state-success-primary)}.dssm-select-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dssm-select-caret{flex:none;width:12px;height:12px;color:var(--dsw-alias-label-tertiary)}.dssm-select-menu{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:30;box-sizing:border-box;max-height:280px;overflow:auto;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3)}.dssm-select-option{box-sizing:border-box;display:flex;align-items:center;width:100%;min-height:32px;padding:0 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer}.dssm-select-option:hover,.dssm-select-option[data-active="true"]{background:var(--dsw-alias-interactive-bg-hover)}.dssm-select-option[aria-selected="true"]{color:var(--dsw-alias-state-success-primary)}.dssm-search-wrap{position:relative;display:flex;align-items:center}.dssm-search{padding-right:32px}.dssm-search::-webkit-search-cancel-button,.dssm-search::-webkit-search-decoration{-webkit-appearance:none;appearance:none}.dssm-search-clear{position:absolute;right:4px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:16px;line-height:1;cursor:pointer}.dssm-search-clear:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dssm-search-clear:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dssm-empty-filter{display:flex;flex-direction:column;align-items:center;gap:12px;padding:28px 16px;border:1px dashed var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;text-align:center}.dssm-filter-meta{margin-left:auto;color:var(--dsw-alias-label-tertiary);font-size:12px}
|
|
226
|
+
@media (max-width:560px){.dssm-mask{padding:12px;align-items:center}.dssm-modal{width:100%!important;height:auto!important;padding:16px;gap:12px;align-self:center!important}.dssm-modal-upload{width:100%!important;align-self:center!important}.dssm-toolbar{flex-wrap:wrap}.dssm-actions{margin-left:0}.dssm-path{display:none}.dssm-row{align-items:flex-start;flex-wrap:wrap}.dssm-row>.dssm-btn{margin-left:auto}.dssm-filters{flex-direction:column;align-items:stretch}.dssm-field-category,.dssm-field-search{flex:none}.dssm-filter-meta{margin-left:0}.dssm-modal-actions{justify-content:stretch}.dssm-modal-actions .dssm-btn{flex:1 1 auto}}@media (prefers-reduced-motion:reduce){.dssm-btn,.dssm-dropzone{transition:none}}
|
|
206
227
|
`;
|
|
207
228
|
|
|
208
229
|
function callApi(path, options) {
|
|
@@ -258,6 +279,50 @@ window.__ModuleLoader__.load({
|
|
|
258
279
|
return skill.invocationPolicyValid && skill.modelInvocable && skill.userInvocable;
|
|
259
280
|
}
|
|
260
281
|
|
|
282
|
+
/** 规范化检索词:去首尾空白并转小写,便于名称、形态和简介统一匹配。 */
|
|
283
|
+
function normalizeSkillQuery(query) {
|
|
284
|
+
return String(query == null ? "" : query).trim().toLowerCase();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** 按名称、简介、形态或分类标签做包含匹配;空检索视为全部命中。 */
|
|
288
|
+
function matchSkillQuery(skill, query) {
|
|
289
|
+
var q = normalizeSkillQuery(query);
|
|
290
|
+
if (q === "") return true;
|
|
291
|
+
return [
|
|
292
|
+
skill.name,
|
|
293
|
+
skill.description,
|
|
294
|
+
skill.kind,
|
|
295
|
+
skill.kindLabel,
|
|
296
|
+
skill.statusLabel,
|
|
297
|
+
skill.rootKey,
|
|
298
|
+
skill.rootLabel,
|
|
299
|
+
].some(function (field) {
|
|
300
|
+
return String(field == null ? "" : field).toLowerCase().includes(q);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** 先按目录分类收窄,再按检索词过滤。rootKey 为空表示全部分类。 */
|
|
305
|
+
function filterSkills(list, options) {
|
|
306
|
+
var query = options && options.query;
|
|
307
|
+
var rootKey = options && options.rootKey != null ? options.rootKey : "";
|
|
308
|
+
return list.filter(function (skill) {
|
|
309
|
+
return (rootKey === "" || skill.rootKey === rootKey) && matchSkillQuery(skill, query);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function skillSearchMeta(skill, root, t) {
|
|
314
|
+
var enabled = isSkillEnabled(skill);
|
|
315
|
+
return {
|
|
316
|
+
name: skill.name,
|
|
317
|
+
description: skill.description,
|
|
318
|
+
kind: skill.kind,
|
|
319
|
+
kindLabel: t(skill.kind === "bundle" ? "status.bundle" : "status.single"),
|
|
320
|
+
statusLabel: skill.invocationPolicyValid ? (enabled ? t("status.enabled") : t("status.disabled")) : t("status.invalid"),
|
|
321
|
+
rootKey: root.key,
|
|
322
|
+
rootLabel: translateOrFallback(t, "root." + root.key, root.label),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
261
326
|
function modalFocusable(modal) {
|
|
262
327
|
return Array.prototype.slice.call(modal.querySelectorAll("button:not(:disabled), [href], input:not([type=hidden]):not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex=\"-1\"])"));
|
|
263
328
|
}
|
|
@@ -273,6 +338,122 @@ window.__ModuleLoader__.load({
|
|
|
273
338
|
}
|
|
274
339
|
}
|
|
275
340
|
|
|
341
|
+
function CategorySelect(props) {
|
|
342
|
+
var openState = react.useState(false);
|
|
343
|
+
var open = openState[0];
|
|
344
|
+
var setOpen = openState[1];
|
|
345
|
+
var selectedIndex = 0;
|
|
346
|
+
for (var i = 0; i < props.options.length; i++) {
|
|
347
|
+
if (props.options[i].value === props.value) { selectedIndex = i; break; }
|
|
348
|
+
}
|
|
349
|
+
var activeState = react.useState(selectedIndex);
|
|
350
|
+
var active = activeState[0];
|
|
351
|
+
var setActive = activeState[1];
|
|
352
|
+
var rootRef = react.useRef(null);
|
|
353
|
+
var triggerRef = react.useRef(null);
|
|
354
|
+
var listRef = react.useRef(null);
|
|
355
|
+
var wasOpen = react.useRef(false);
|
|
356
|
+
var selected = props.options[selectedIndex];
|
|
357
|
+
|
|
358
|
+
react.useEffect(function () {
|
|
359
|
+
if (!open) return undefined;
|
|
360
|
+
setActive(selectedIndex);
|
|
361
|
+
function onPointerDown(event) {
|
|
362
|
+
var node = rootRef.current;
|
|
363
|
+
if (node && event.target && node.contains(event.target)) return;
|
|
364
|
+
setOpen(false);
|
|
365
|
+
}
|
|
366
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
367
|
+
return function () { document.removeEventListener("pointerdown", onPointerDown); };
|
|
368
|
+
}, [open, selectedIndex]);
|
|
369
|
+
|
|
370
|
+
react.useEffect(function () {
|
|
371
|
+
if (open) {
|
|
372
|
+
if (listRef.current) listRef.current.focus();
|
|
373
|
+
wasOpen.current = true;
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (wasOpen.current) {
|
|
377
|
+
if (triggerRef.current) triggerRef.current.focus();
|
|
378
|
+
wasOpen.current = false;
|
|
379
|
+
}
|
|
380
|
+
}, [open]);
|
|
381
|
+
|
|
382
|
+
react.useEffect(function () {
|
|
383
|
+
if (!open) return;
|
|
384
|
+
var option = document.getElementById(props.id + "-opt-" + String(active));
|
|
385
|
+
if (option) option.scrollIntoView({ block: "nearest" });
|
|
386
|
+
}, [active, open, props.id]);
|
|
387
|
+
|
|
388
|
+
function choose(value) {
|
|
389
|
+
props.onChange(value);
|
|
390
|
+
setOpen(false);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function move(next) {
|
|
394
|
+
if (!props.options.length) return;
|
|
395
|
+
setActive(Math.min(props.options.length - 1, Math.max(0, next)));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function onTriggerKeyDown(event) {
|
|
399
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
|
|
400
|
+
event.preventDefault();
|
|
401
|
+
setOpen(true);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function onListKeyDown(event) {
|
|
406
|
+
if (event.key === "ArrowDown") { event.preventDefault(); move(active + 1); return; }
|
|
407
|
+
if (event.key === "ArrowUp") { event.preventDefault(); move(active - 1); return; }
|
|
408
|
+
if (event.key === "Home") { event.preventDefault(); move(0); return; }
|
|
409
|
+
if (event.key === "End") { event.preventDefault(); move(props.options.length - 1); return; }
|
|
410
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
411
|
+
event.preventDefault();
|
|
412
|
+
var option = props.options[active];
|
|
413
|
+
if (option) choose(option.value);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (event.key === "Escape" || event.key === "Tab") setOpen(false);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return h("div", { className: "dssm-select", ref: rootRef },
|
|
420
|
+
h("button", {
|
|
421
|
+
id: props.id,
|
|
422
|
+
ref: triggerRef,
|
|
423
|
+
type: "button",
|
|
424
|
+
className: "dssm-select-trigger",
|
|
425
|
+
"aria-haspopup": "listbox",
|
|
426
|
+
"aria-expanded": open,
|
|
427
|
+
"aria-controls": props.id + "-list",
|
|
428
|
+
onClick: function () { setOpen(function (current) { return !current; }); },
|
|
429
|
+
onKeyDown: onTriggerKeyDown,
|
|
430
|
+
},
|
|
431
|
+
h("span", { className: "dssm-select-value" }, selected ? selected.label : ""),
|
|
432
|
+
h("svg", { className: "dssm-select-caret", viewBox: "0 0 12 12", "aria-hidden": true, focusable: false },
|
|
433
|
+
h("path", { d: "M2.5 4.5L6 8l3.5-3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
434
|
+
open ? h("div", {
|
|
435
|
+
id: props.id + "-list",
|
|
436
|
+
ref: listRef,
|
|
437
|
+
className: "dssm-select-menu",
|
|
438
|
+
role: "listbox",
|
|
439
|
+
tabIndex: 0,
|
|
440
|
+
"aria-activedescendant": props.id + "-opt-" + String(active),
|
|
441
|
+
onKeyDown: onListKeyDown,
|
|
442
|
+
}, props.options.map(function (option, index) {
|
|
443
|
+
return h("button", {
|
|
444
|
+
key: option.value === "" ? "all" : option.value,
|
|
445
|
+
id: props.id + "-opt-" + String(index),
|
|
446
|
+
type: "button",
|
|
447
|
+
role: "option",
|
|
448
|
+
className: "dssm-select-option",
|
|
449
|
+
"aria-selected": option.value === props.value,
|
|
450
|
+
"data-active": index === active,
|
|
451
|
+
onMouseEnter: function () { setActive(index); },
|
|
452
|
+
onClick: function () { choose(option.value); },
|
|
453
|
+
}, option.label);
|
|
454
|
+
})) : null);
|
|
455
|
+
}
|
|
456
|
+
|
|
276
457
|
// 渲染机制按 register 的 locale 字段把命名空间绑定的 t 注入组件 props。
|
|
277
458
|
function SkillManagerSection(props) {
|
|
278
459
|
var t = props.t;
|
|
@@ -297,6 +478,12 @@ window.__ModuleLoader__.load({
|
|
|
297
478
|
var deleteState = react.useState(null);
|
|
298
479
|
var confirmDelete = deleteState[0];
|
|
299
480
|
var setConfirmDelete = deleteState[1];
|
|
481
|
+
var queryState = react.useState("");
|
|
482
|
+
var query = queryState[0];
|
|
483
|
+
var setQuery = queryState[1];
|
|
484
|
+
var categoryState = react.useState("");
|
|
485
|
+
var category = categoryState[0];
|
|
486
|
+
var setCategory = categoryState[1];
|
|
300
487
|
var inputRef = react.useRef(null);
|
|
301
488
|
var modalRef = react.useRef(null);
|
|
302
489
|
|
|
@@ -443,15 +630,65 @@ window.__ModuleLoader__.load({
|
|
|
443
630
|
h("div", { className: "dssm-actions" },
|
|
444
631
|
h("button", { className: "dssm-btn dssm-btn-secondary", disabled: !!busy, onClick: refresh }, t("btn.refresh")),
|
|
445
632
|
h("button", { className: "dssm-btn", disabled: !!busy, onClick: function () { setImportResult(null); setUploadOpen(true); } }, t("btn.upload")))));
|
|
633
|
+
var searchable = roots.reduce(function (all, root) {
|
|
634
|
+
return all.concat((root.skills || []).map(function (skill) { return skillSearchMeta(skill, root, t); }));
|
|
635
|
+
}, []);
|
|
636
|
+
var filtered = filterSkills(searchable, { query: query, rootKey: category });
|
|
637
|
+
var filteredCount = filtered.length;
|
|
638
|
+
var hasQuery = normalizeSkillQuery(query) !== "";
|
|
639
|
+
var hasFilter = hasQuery || category !== "";
|
|
640
|
+
var resetFilters = function () { setQuery(""); setCategory(""); };
|
|
446
641
|
// 复数按 en 的 one/other 二元规则选择;zh/en 均适用,扩展多复数语言时需改 CLDR 规则。
|
|
447
642
|
nodes.push(h("div", { key: "summary", className: "dssm-summary" },
|
|
448
|
-
h("span", { className: "dssm-summary-count" }, skills.length), h("span", { className: "dssm-summary-label" }, t(skills.length === 1 ? "summary.total.one" : "summary.total.other", { count: skills.length })), h("span", { className: "dssm-summary-separator" }), h("span", { className: "dssm-summary-count" }, enabled), h("span", { className: "dssm-summary-label" }, t(enabled === 1 ? "summary.enabled.one" : "summary.enabled.other", { count: enabled }))
|
|
643
|
+
h("span", { className: "dssm-summary-count" }, skills.length), h("span", { className: "dssm-summary-label" }, t(skills.length === 1 ? "summary.total.one" : "summary.total.other", { count: skills.length })), h("span", { className: "dssm-summary-separator" }), h("span", { className: "dssm-summary-count" }, enabled), h("span", { className: "dssm-summary-label" }, t(enabled === 1 ? "summary.enabled.one" : "summary.enabled.other", { count: enabled })),
|
|
644
|
+
hasFilter ? h("span", { className: "dssm-filter-meta", "aria-live": "polite" }, t(filteredCount === 1 ? "filter.showing.one" : "filter.showing.other", { count: filteredCount })) : null));
|
|
645
|
+
nodes.push(h("div", { key: "filters", className: "dssm-filters" },
|
|
646
|
+
h("div", { className: "dssm-field dssm-field-category" },
|
|
647
|
+
h("label", { className: "dssm-label", htmlFor: "dssm-filter-category" }, t("filter.category")),
|
|
648
|
+
h(CategorySelect, {
|
|
649
|
+
id: "dssm-filter-category",
|
|
650
|
+
value: category,
|
|
651
|
+
onChange: setCategory,
|
|
652
|
+
options: [{ value: "", label: t("filter.option", { name: t("filter.all"), count: skills.length }) }].concat(roots.map(function (root) {
|
|
653
|
+
return { value: root.key, label: t("filter.option", { name: translateOrFallback(t, "root." + root.key, root.label), count: (root.skills || []).length }) };
|
|
654
|
+
})),
|
|
655
|
+
})),
|
|
656
|
+
h("div", { className: "dssm-field dssm-field-search" },
|
|
657
|
+
h("label", { className: "dssm-label", htmlFor: "dssm-filter-search" }, t("search")),
|
|
658
|
+
h("div", { className: "dssm-search-wrap" },
|
|
659
|
+
h("input", {
|
|
660
|
+
id: "dssm-filter-search",
|
|
661
|
+
className: "dssm-control dssm-search",
|
|
662
|
+
type: "search",
|
|
663
|
+
value: query,
|
|
664
|
+
autoComplete: "off",
|
|
665
|
+
spellCheck: false,
|
|
666
|
+
placeholder: t("search.placeholder"),
|
|
667
|
+
onChange: function (event) { setQuery(event.currentTarget.value); },
|
|
668
|
+
}),
|
|
669
|
+
query !== "" ? h("button", { type: "button", className: "dssm-search-clear", "aria-label": t("search.clear"), onClick: function () { setQuery(""); } }, "×") : null))));
|
|
670
|
+
var visibleRoots = [];
|
|
449
671
|
roots.forEach(function (root) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
672
|
+
if (category !== "" && root.key !== category) return;
|
|
673
|
+
var groupSkills = (root.skills || []).filter(function (skill) {
|
|
674
|
+
return matchSkillQuery(skillSearchMeta(skill, root, t), query);
|
|
675
|
+
});
|
|
676
|
+
if (hasQuery && groupSkills.length === 0) return;
|
|
677
|
+
visibleRoots.push({ root: root, groupSkills: groupSkills });
|
|
454
678
|
});
|
|
679
|
+
if (hasQuery && visibleRoots.length === 0) {
|
|
680
|
+
nodes.push(h("div", { key: "empty-search", className: "dssm-empty-filter" },
|
|
681
|
+
h("div", null, t("empty.search", { all: t("filter.all") })),
|
|
682
|
+
h("button", { type: "button", className: "dssm-btn dssm-btn-secondary", onClick: resetFilters }, t("empty.search.reset"))));
|
|
683
|
+
} else {
|
|
684
|
+
visibleRoots.forEach(function (item) {
|
|
685
|
+
var root = item.root;
|
|
686
|
+
var groupSkills = item.groupSkills;
|
|
687
|
+
nodes.push(h("div", { key: root.key, className: "dssm-group" },
|
|
688
|
+
h("div", { className: "dssm-group-head" }, h("h3", { className: "dssm-group-title" }, translateOrFallback(t, "root." + root.key, root.label)), h("span", { className: "dssm-count" }, t("summary.group", { count: groupSkills.length })), h("span", { className: "dssm-path", title: root.path }, root.path)),
|
|
689
|
+
root.exists === false ? h("div", { className: "dssm-empty" }, root.mutable ? t("empty.dir.uncreated") : t("empty.dir.missing")) : (groupSkills.length ? groupSkills.map(function (skill) { return skillRow(skill, root); }) : h("div", { className: "dssm-empty" }, t("empty.skills.none")))));
|
|
690
|
+
});
|
|
691
|
+
}
|
|
455
692
|
} else if (snapshot.loading) {
|
|
456
693
|
nodes.push(h("div", { key: "loading", className: "dssm-note" }, t("loading")));
|
|
457
694
|
}
|
|
@@ -522,8 +759,16 @@ window.__ModuleLoader__.load({
|
|
|
522
759
|
module.exports.DICT = DICT;
|
|
523
760
|
module.exports.translateError = translateError;
|
|
524
761
|
module.exports.isSkillEnabled = isSkillEnabled;
|
|
762
|
+
module.exports.normalizeSkillQuery = normalizeSkillQuery;
|
|
763
|
+
module.exports.matchSkillQuery = matchSkillQuery;
|
|
764
|
+
module.exports.filterSkills = filterSkills;
|
|
525
765
|
module.exports.parseApiResponse = parseApiResponse;
|
|
526
766
|
module.exports.trapModalFocus = trapModalFocus;
|
|
527
767
|
return module.exports;
|
|
528
768
|
}
|
|
529
769
|
});
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
package/package.json
CHANGED