dsh-better-workspace 0.17.1 → 0.17.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/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +74 -24
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-better-workspace",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.2",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "侧边栏工作区树:按官方磁盘目录嵌套(官方 workspace-tree 语义),可选按名称中的 / 分组(默认关闭,设置里开启);添加工作区由官方目录流承载。Workspace tree for the DSH sidebar workspace list, nested by official disk folders with optional \"/\"-name grouping.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-better-workspace",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.2",
|
|
4
4
|
"description": "侧边栏工作区树:按官方磁盘目录嵌套(官方 workspace-tree 语义),可选按名称中的 / 分组(默认关闭,设置里开启);添加工作区走官方目录流。Workspace tree for the DSH sidebar: disk-path nesting (official workspace-tree semantics), with optional \"/\"-name grouping (off by default); add-workspace rides the official directory flow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -151,6 +151,7 @@ window.__ModuleLoader__.load({
|
|
|
151
151
|
'group.new.nameHint': "名称中的 / 即嵌套层级,例如 前端/组件",
|
|
152
152
|
'group.new.empty': "请输入分组名称",
|
|
153
153
|
'group.new.root': "顶层",
|
|
154
|
+
'group.new.independent': "新建顶层分组",
|
|
154
155
|
'group.new.pickWorkspace': "选择一个工作区",
|
|
155
156
|
'group.new.noWorkspace': "还没有工作区,请先添加一个",
|
|
156
157
|
'group.new.pickFirst': "请先选择一个工作区",
|
|
@@ -279,6 +280,7 @@ window.__ModuleLoader__.load({
|
|
|
279
280
|
'group.new.nameHint': "A \"/\" nests further, e.g. frontend/components",
|
|
280
281
|
'group.new.empty': "Enter a group name",
|
|
281
282
|
'group.new.root': "Top level",
|
|
283
|
+
'group.new.independent': "New top-level group",
|
|
282
284
|
'group.new.pickWorkspace': "Pick a workspace",
|
|
283
285
|
'group.new.noWorkspace': "No workspaces yet — add one first",
|
|
284
286
|
'group.new.pickFirst': "Pick a workspace first",
|
|
@@ -415,6 +417,7 @@ window.__ModuleLoader__.load({
|
|
|
415
417
|
'group.new.nameHint': "الشرطة المائلة \"/\" تنشئ مستوى أعمق، مثل frontend/components",
|
|
416
418
|
'group.new.empty': "أدخل اسم المجموعة",
|
|
417
419
|
'group.new.root': "المستوى الأعلى",
|
|
420
|
+
'group.new.independent': "مجموعة جديدة في المستوى الأعلى",
|
|
418
421
|
'group.new.pickWorkspace': "اختر مساحة عمل",
|
|
419
422
|
'group.new.noWorkspace': "لا توجد مساحات عمل بعد — أضف واحدة أولاً",
|
|
420
423
|
'group.new.pickFirst': "اختر مساحة عمل أولاً",
|
|
@@ -543,6 +546,7 @@ window.__ModuleLoader__.load({
|
|
|
543
546
|
'group.new.nameHint': "Ein „/\" verschachtelt weiter, z. B. frontend/components",
|
|
544
547
|
'group.new.empty': "Gruppennamen eingeben",
|
|
545
548
|
'group.new.root': "Oberste Ebene",
|
|
549
|
+
'group.new.independent': "Neue Gruppe auf oberster Ebene",
|
|
546
550
|
'group.new.pickWorkspace': "Arbeitsbereich wählen",
|
|
547
551
|
'group.new.noWorkspace': "Noch keine Arbeitsbereiche — zuerst einen hinzufügen",
|
|
548
552
|
'group.new.pickFirst': "Zuerst einen Arbeitsbereich wählen",
|
|
@@ -671,6 +675,7 @@ window.__ModuleLoader__.load({
|
|
|
671
675
|
'group.new.nameHint': "Un « / » imbrique davantage, par ex. frontend/components",
|
|
672
676
|
'group.new.empty': "Saisissez un nom de groupe",
|
|
673
677
|
'group.new.root': "Niveau supérieur",
|
|
678
|
+
'group.new.independent': "Nouveau groupe de premier niveau",
|
|
674
679
|
'group.new.pickWorkspace': "Choisissez un espace de travail",
|
|
675
680
|
'group.new.noWorkspace': "Aucun espace de travail — ajoutez-en un d’abord",
|
|
676
681
|
'group.new.pickFirst': "Choisissez d’abord un espace de travail",
|
|
@@ -799,6 +804,7 @@ window.__ModuleLoader__.load({
|
|
|
799
804
|
'group.new.nameHint': "\"/\" और गहरा स्तर बनाता है, जैसे frontend/components",
|
|
800
805
|
'group.new.empty': "समूह का नाम दर्ज करें",
|
|
801
806
|
'group.new.root': "शीर्ष स्तर",
|
|
807
|
+
'group.new.independent': "नया शीर्ष-स्तरीय समूह",
|
|
802
808
|
'group.new.pickWorkspace': "एक कार्यस्थान चुनें",
|
|
803
809
|
'group.new.noWorkspace': "अभी कोई कार्यस्थान नहीं — पहले एक जोड़ें",
|
|
804
810
|
'group.new.pickFirst': "पहले एक कार्यस्थान चुनें",
|
|
@@ -927,6 +933,7 @@ window.__ModuleLoader__.load({
|
|
|
927
933
|
'group.new.nameHint': "\"/\" membuat tingkat lebih dalam, mis. frontend/components",
|
|
928
934
|
'group.new.empty': "Masukkan nama grup",
|
|
929
935
|
'group.new.root': "Tingkat teratas",
|
|
936
|
+
'group.new.independent': "Grup tingkat teratas baru",
|
|
930
937
|
'group.new.pickWorkspace': "Pilih ruang kerja",
|
|
931
938
|
'group.new.noWorkspace': "Belum ada ruang kerja — tambahkan dulu",
|
|
932
939
|
'group.new.pickFirst': "Pilih ruang kerja dulu",
|
|
@@ -1055,6 +1062,7 @@ window.__ModuleLoader__.load({
|
|
|
1055
1062
|
'group.new.nameHint': "Una «/» annida ulteriormente, es. frontend/components",
|
|
1056
1063
|
'group.new.empty': "Inserisci un nome di gruppo",
|
|
1057
1064
|
'group.new.root': "Livello superiore",
|
|
1065
|
+
'group.new.independent': "Nuovo gruppo di primo livello",
|
|
1058
1066
|
'group.new.pickWorkspace': "Scegli un’area di lavoro",
|
|
1059
1067
|
'group.new.noWorkspace': "Nessuna area di lavoro — aggiungine una prima",
|
|
1060
1068
|
'group.new.pickFirst': "Scegli prima un’area di lavoro",
|
|
@@ -1183,6 +1191,7 @@ window.__ModuleLoader__.load({
|
|
|
1183
1191
|
'group.new.nameHint': "/ でさらに深い階層になります(例: frontend/components)",
|
|
1184
1192
|
'group.new.empty': "グループ名を入力してください",
|
|
1185
1193
|
'group.new.root': "最上位",
|
|
1194
|
+
'group.new.independent': "最上位に新しいグループ",
|
|
1186
1195
|
'group.new.pickWorkspace': "ワークスペースを選択",
|
|
1187
1196
|
'group.new.noWorkspace': "ワークスペースがありません。先に追加してください",
|
|
1188
1197
|
'group.new.pickFirst': "先にワークスペースを選択してください",
|
|
@@ -1311,6 +1320,7 @@ window.__ModuleLoader__.load({
|
|
|
1311
1320
|
'group.new.nameHint': "\"/\"로 더 깊은 단계, 예: frontend/components",
|
|
1312
1321
|
'group.new.empty': "그룹 이름을 입력하세요",
|
|
1313
1322
|
'group.new.root': "최상위",
|
|
1323
|
+
'group.new.independent': "최상위 새 그룹",
|
|
1314
1324
|
'group.new.pickWorkspace': "워크스페이스 선택",
|
|
1315
1325
|
'group.new.noWorkspace': "워크스페이스가 없습니다. 먼저 추가하세요",
|
|
1316
1326
|
'group.new.pickFirst': "먼저 워크스페이스를 선택하세요",
|
|
@@ -1439,6 +1449,7 @@ window.__ModuleLoader__.load({
|
|
|
1439
1449
|
'group.new.nameHint': "Een \"/\" nest dieper, bijv. frontend/components",
|
|
1440
1450
|
'group.new.empty': "Voer een groepsnaam in",
|
|
1441
1451
|
'group.new.root': "Bovenste niveau",
|
|
1452
|
+
'group.new.independent': "Nieuwe groep op hoogste niveau",
|
|
1442
1453
|
'group.new.pickWorkspace': "Kies een werkruimte",
|
|
1443
1454
|
'group.new.noWorkspace': "Nog geen werkruimten — voeg er eerst een toe",
|
|
1444
1455
|
'group.new.pickFirst': "Kies eerst een werkruimte",
|
|
@@ -1567,6 +1578,7 @@ window.__ModuleLoader__.load({
|
|
|
1567
1578
|
'group.new.nameHint': "„/” zagnieżdża głębiej, np. frontend/components",
|
|
1568
1579
|
'group.new.empty': "Podaj nazwę grupy",
|
|
1569
1580
|
'group.new.root': "Najwyższy poziom",
|
|
1581
|
+
'group.new.independent': "Nowa grupa najwyższego poziomu",
|
|
1570
1582
|
'group.new.pickWorkspace': "Wybierz obszar roboczy",
|
|
1571
1583
|
'group.new.noWorkspace': "Brak obszarów roboczych — najpierw dodaj jeden",
|
|
1572
1584
|
'group.new.pickFirst': "Najpierw wybierz obszar roboczy",
|
|
@@ -1695,6 +1707,7 @@ window.__ModuleLoader__.load({
|
|
|
1695
1707
|
'group.new.nameHint': "Uma \"/\" aninha mais, ex. frontend/components",
|
|
1696
1708
|
'group.new.empty': "Digite um nome de grupo",
|
|
1697
1709
|
'group.new.root': "Nível superior",
|
|
1710
|
+
'group.new.independent': "Novo grupo de nível superior",
|
|
1698
1711
|
'group.new.pickWorkspace': "Escolha uma área de trabalho",
|
|
1699
1712
|
'group.new.noWorkspace': "Ainda não há áreas de trabalho — adicione uma primeiro",
|
|
1700
1713
|
'group.new.pickFirst': "Escolha uma área de trabalho primeiro",
|
|
@@ -1823,6 +1836,7 @@ window.__ModuleLoader__.load({
|
|
|
1823
1836
|
'group.new.nameHint': "«/» вкладывает глубже, напр. frontend/components",
|
|
1824
1837
|
'group.new.empty': "Введите имя группы",
|
|
1825
1838
|
'group.new.root': "Верхний уровень",
|
|
1839
|
+
'group.new.independent': "Новая группа верхнего уровня",
|
|
1826
1840
|
'group.new.pickWorkspace': "Выберите рабочую область",
|
|
1827
1841
|
'group.new.noWorkspace': "Рабочих областей пока нет — сначала добавьте одну",
|
|
1828
1842
|
'group.new.pickFirst': "Сначала выберите рабочую область",
|
|
@@ -1951,6 +1965,7 @@ window.__ModuleLoader__.load({
|
|
|
1951
1965
|
'group.new.nameHint': "Ett \"/\" nästlar djupare, t.ex. frontend/components",
|
|
1952
1966
|
'group.new.empty': "Ange ett gruppnamn",
|
|
1953
1967
|
'group.new.root': "Översta nivån",
|
|
1968
|
+
'group.new.independent': "Ny grupp på översta nivån",
|
|
1954
1969
|
'group.new.pickWorkspace': "Välj en arbetsyta",
|
|
1955
1970
|
'group.new.noWorkspace': "Inga arbetsytor än — lägg till en först",
|
|
1956
1971
|
'group.new.pickFirst': "Välj en arbetsyta först",
|
|
@@ -2079,6 +2094,7 @@ window.__ModuleLoader__.load({
|
|
|
2079
2094
|
'group.new.nameHint': "/ ใช้ซ้อนระดับลึกขึ้น เช่น frontend/components",
|
|
2080
2095
|
'group.new.empty': "กรอกชื่อกลุ่ม",
|
|
2081
2096
|
'group.new.root': "ระดับบนสุด",
|
|
2097
|
+
'group.new.independent': "กลุ่มระดับบนสุดใหม่",
|
|
2082
2098
|
'group.new.pickWorkspace': "เลือกเวิร์กสเปซ",
|
|
2083
2099
|
'group.new.noWorkspace': "ยังไม่มีเวิร์กสเปซ — เพิ่มก่อน",
|
|
2084
2100
|
'group.new.pickFirst': "เลือกเวิร์กสเปซก่อน",
|
|
@@ -2207,6 +2223,7 @@ window.__ModuleLoader__.load({
|
|
|
2207
2223
|
'group.new.nameHint': "\"/\" daha derin iç içe koyar, örn. frontend/components",
|
|
2208
2224
|
'group.new.empty': "Bir grup adı girin",
|
|
2209
2225
|
'group.new.root': "En üst düzey",
|
|
2226
|
+
'group.new.independent': "Yeni üst düzey grup",
|
|
2210
2227
|
'group.new.pickWorkspace': "Bir çalışma alanı seçin",
|
|
2211
2228
|
'group.new.noWorkspace': "Henüz çalışma alanı yok — önce bir tane ekleyin",
|
|
2212
2229
|
'group.new.pickFirst': "Önce bir çalışma alanı seçin",
|
|
@@ -2335,6 +2352,7 @@ window.__ModuleLoader__.load({
|
|
|
2335
2352
|
'group.new.nameHint': "\"/\" lồng sâu hơn, ví dụ frontend/components",
|
|
2336
2353
|
'group.new.empty': "Nhập tên nhóm",
|
|
2337
2354
|
'group.new.root': "Cấp cao nhất",
|
|
2355
|
+
'group.new.independent': "Nhóm cấp cao nhất mới",
|
|
2338
2356
|
'group.new.pickWorkspace': "Chọn một không gian làm việc",
|
|
2339
2357
|
'group.new.noWorkspace': "Chưa có không gian làm việc — hãy thêm trước",
|
|
2340
2358
|
'group.new.pickFirst': "Chọn không gian làm việc trước",
|
|
@@ -2463,6 +2481,7 @@ window.__ModuleLoader__.load({
|
|
|
2463
2481
|
'group.new.nameHint': "名入面嘅 / 即嵌套層級,例如 前端/組件",
|
|
2464
2482
|
'group.new.empty': "請輸入分組名",
|
|
2465
2483
|
'group.new.root': "最頂層",
|
|
2484
|
+
'group.new.independent': "新增頂層分組",
|
|
2466
2485
|
'group.new.pickWorkspace': "揀一個工作區",
|
|
2467
2486
|
'group.new.noWorkspace': "仲未有工作區,請先加一個",
|
|
2468
2487
|
'group.new.pickFirst': "請先揀一個工作區",
|
|
@@ -2591,6 +2610,7 @@ window.__ModuleLoader__.load({
|
|
|
2591
2610
|
'group.new.nameHint': "名入面嘅 / 即嵌套層級,例如 前端/組件",
|
|
2592
2611
|
'group.new.empty': "請輸入分組名",
|
|
2593
2612
|
'group.new.root': "最頂層",
|
|
2613
|
+
'group.new.independent': "新增頂層分組",
|
|
2594
2614
|
'group.new.pickWorkspace': "揀一個工作區",
|
|
2595
2615
|
'group.new.noWorkspace': "仲未有工作區,請先加一個",
|
|
2596
2616
|
'group.new.pickFirst': "請先揀一個工作區",
|
|
@@ -2719,6 +2739,7 @@ window.__ModuleLoader__.load({
|
|
|
2719
2739
|
'group.new.nameHint': "名稱中的 / 即巢狀層級,例如 前端/元件",
|
|
2720
2740
|
'group.new.empty': "請輸入分組名稱",
|
|
2721
2741
|
'group.new.root': "最頂層",
|
|
2742
|
+
'group.new.independent': "新增頂層分組",
|
|
2722
2743
|
'group.new.pickWorkspace': "選擇一個工作區",
|
|
2723
2744
|
'group.new.noWorkspace': "還沒有工作區,請先新增一個",
|
|
2724
2745
|
'group.new.pickFirst': "請先選擇一個工作區",
|
|
@@ -3101,6 +3122,14 @@ window.__ModuleLoader__.load({
|
|
|
3101
3122
|
return Array.isArray(raw) && raw.length > 0
|
|
3102
3123
|
}
|
|
3103
3124
|
|
|
3125
|
+
/**
|
|
3126
|
+
* Display name of a tree folder node. compressTree materializes a
|
|
3127
|
+
* single-child chain as a `kind:'ws'` row, and THAT shape carries `segs`
|
|
3128
|
+
* but no `name` — reading .name alone rendered a blank row (a lone
|
|
3129
|
+
* "E" above its only member F came out empty).
|
|
3130
|
+
*/
|
|
3131
|
+
const folderLabelOf = (node) => String(node.name || (Array.isArray(node.segs) ? node.segs.join('/') : '') || node.path || '')
|
|
3132
|
+
|
|
3104
3133
|
const explicitSegsOf = (explicit, scope) => {
|
|
3105
3134
|
const raw = explicit && typeof explicit === 'object' ? explicit[String(scope)] : undefined
|
|
3106
3135
|
const out = []
|
|
@@ -3296,6 +3325,10 @@ window.__ModuleLoader__.load({
|
|
|
3296
3325
|
'.bw-gn-hint{font-size:12px;color:var(--dsw-alias-label-tertiary,#9a9a9a)}',
|
|
3297
3326
|
// A container-only node (a workspace name-group in the session layer):
|
|
3298
3327
|
// still expandable, but it carries no workspaceId to file against.
|
|
3328
|
+
// The trailing "new top-level group" row: separated from the containers
|
|
3329
|
+
// above it, because it belongs to none of them.
|
|
3330
|
+
'.bw-gn-row-new{margin-top:4px;border-top:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.22));border-radius:0 0 6px 6px;padding-top:4px}',
|
|
3331
|
+
'.bw-gn-row-new .bw-gn-label{color:var(--dsw-alias-label-secondary,#b8b8b8)}',
|
|
3299
3332
|
'.bw-gn-row-hold{cursor:default}',
|
|
3300
3333
|
'.bw-gn-row-hold:hover{background:transparent}',
|
|
3301
3334
|
'.bw-gn-row-hold .bw-gn-label{color:var(--dsw-alias-label-secondary,#b8b8b8)}',
|
|
@@ -3834,7 +3867,7 @@ window.__ModuleLoader__.load({
|
|
|
3834
3867
|
* writes the declaration itself, which is why it is not the move dialog.
|
|
3835
3868
|
*/
|
|
3836
3869
|
function GroupNewDialog(props) {
|
|
3837
|
-
const { kinds, initialKind, treeOf, onConfirm, onClose, t } = props
|
|
3870
|
+
const { kinds, initialKind, treeOf, label, onConfirm, onClose, t } = props
|
|
3838
3871
|
const [kind, setKind] = React.useState(initialKind)
|
|
3839
3872
|
const [picked, setPicked] = React.useState(null)
|
|
3840
3873
|
const [openKeys, setOpenKeys] = React.useState({})
|
|
@@ -3859,7 +3892,7 @@ window.__ModuleLoader__.load({
|
|
|
3859
3892
|
const expanded = openKeys[node.id] === true || (depth === 0 && openKeys[node.id] !== false)
|
|
3860
3893
|
out.push(E('div', {
|
|
3861
3894
|
key: 'n-' + node.id,
|
|
3862
|
-
className: cls('bw-gn-row', node.pickable === false && 'bw-gn-row-hold', picked && picked.id === node.id && 'bw-gn-row-on'),
|
|
3895
|
+
className: cls('bw-gn-row', node.pickable === false && 'bw-gn-row-hold', node.kind === 'new' && 'bw-gn-row-new', picked && picked.id === node.id && 'bw-gn-row-on'),
|
|
3863
3896
|
style: { paddingLeft: 6 + depth * 14 },
|
|
3864
3897
|
role: 'treeitem',
|
|
3865
3898
|
'aria-selected': picked && picked.id === node.id ? 'true' : 'false',
|
|
@@ -3872,7 +3905,10 @@ window.__ModuleLoader__.load({
|
|
|
3872
3905
|
'aria-label': node.label,
|
|
3873
3906
|
onClick: (e) => { e.stopPropagation(); toggle(node.id) },
|
|
3874
3907
|
}, E('span', { className: 'bw-chevron' })) : E('span', { className: 'bw-gn-twist' }),
|
|
3875
|
-
E('span', { className: 'bw-gn-icon' },
|
|
3908
|
+
E('span', { className: 'bw-gn-icon' },
|
|
3909
|
+
node.kind === 'new' ? icon('IconPlusOutline16', 15)
|
|
3910
|
+
: node.kind === 'ws' ? icon('IconFolderOpen16', 15)
|
|
3911
|
+
: icon('IconFolderClose16', 15)),
|
|
3876
3912
|
E('span', { className: 'bw-gn-label' }, node.label),
|
|
3877
3913
|
))
|
|
3878
3914
|
if (hasKids && expanded) out.push(...renderNodes(node.children, depth + 1))
|
|
@@ -3883,7 +3919,7 @@ window.__ModuleLoader__.load({
|
|
|
3883
3919
|
open: true,
|
|
3884
3920
|
onClose,
|
|
3885
3921
|
closeLabel: t('close'),
|
|
3886
|
-
title:
|
|
3922
|
+
title: label,
|
|
3887
3923
|
footer: E('div', { className: 'bw-modal-actions' },
|
|
3888
3924
|
E(BTN, { variant: 'outline', onClick: onClose }, t('cancel')),
|
|
3889
3925
|
E(BTN, { variant: 'primary', onClick: submit }, t('confirm')),
|
|
@@ -5170,6 +5206,13 @@ window.__ModuleLoader__.load({
|
|
|
5170
5206
|
if (!compactChains || draggingWorkspace) return built
|
|
5171
5207
|
return { ...built, folders: built.folders.map((f) => materializeChain(compressTree(f))), workspaces: built.workspaces }
|
|
5172
5208
|
}, [items, compactChains, draggingWorkspace, workspaceSlash, wsFolders])
|
|
5209
|
+
// UNCOMPRESSED tree, for the new-group dialog only. compressTree merges a
|
|
5210
|
+
// single-child chain into one row that stands for BOTH a group and the
|
|
5211
|
+
// workspace under it — fine for drawing, useless for choosing a
|
|
5212
|
+
// container: one half must stay unselectable and the other must be
|
|
5213
|
+
// selectable, and a merged row cannot be both. (It also carried no
|
|
5214
|
+
// `name`, which is how a lone "E" rendered blank.)
|
|
5215
|
+
const rawTree = React.useMemo(() => buildTree(items, workspaceSlash, wsFolders), [items, workspaceSlash, wsFolders])
|
|
5173
5216
|
// Disk-layer ancestry for drag semantics (same derivation as buildTree).
|
|
5174
5217
|
const diskParentMap = React.useMemo(() => diskParentMapOf(items), [items])
|
|
5175
5218
|
|
|
@@ -5371,19 +5414,16 @@ window.__ModuleLoader__.load({
|
|
|
5371
5414
|
// write target: `scope` is the store's bags key (the disk level's idPrefix
|
|
5372
5415
|
// for workspaces, the workspaceId for sessions) and `path` is the parent
|
|
5373
5416
|
// group's name path — the dialog appends the new name to it.
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
}
|
|
5385
|
-
return out
|
|
5386
|
-
}
|
|
5417
|
+
// Workspace-GROUP containers: name-group folders only, never the
|
|
5418
|
+
// workspaces themselves. A workspace title is "group/leaf", so with
|
|
5419
|
+
// members A/B, A/C, D and E/F the only groups that exist are A and E —
|
|
5420
|
+
// B, C, D and F are leaves (they are workspaces, not containers), and
|
|
5421
|
+
// offering them would invite a group named after a leaf. Disk nesting is
|
|
5422
|
+
// a workspace fact too, so it is skipped for the same reason.
|
|
5423
|
+
const wsFolderNodesOf = (node) => (node.folders || []).map((f) => ({
|
|
5424
|
+
id: f.scope + '|' + f.path, scope: f.scope, path: f.path, label: folderLabelOf(f), kind: 'folder',
|
|
5425
|
+
children: wsFolderNodesOf(f),
|
|
5426
|
+
}))
|
|
5387
5427
|
const sessGroupNodesOf = (node, workspaceId) => (node.groups || []).map((g) => ({
|
|
5388
5428
|
id: workspaceId + '|' + g.path, scope: workspaceId, path: g.path, label: g.name, kind: 'sgroup',
|
|
5389
5429
|
children: sessGroupNodesOf(g, workspaceId),
|
|
@@ -5399,12 +5439,18 @@ window.__ModuleLoader__.load({
|
|
|
5399
5439
|
if (kind === 'workspace') {
|
|
5400
5440
|
// "Top level" IS a real target here (a group at the root of the
|
|
5401
5441
|
// workspace tree), so it is a node like any other.
|
|
5442
|
+
// A dedicated top-level row, not a root node that both expands AND
|
|
5443
|
+
// accepts the new name: that read as "pick a spot inside the top
|
|
5444
|
+
// level", and it left no way to say "give me a group NEXT TO A and
|
|
5445
|
+
// E". The row below is that way, and A / E sit beside it as the
|
|
5446
|
+
// top-level groups they actually are.
|
|
5447
|
+
const groups = treeView ? wsFolderNodesOf(rawTree) : []
|
|
5402
5448
|
return {
|
|
5403
|
-
hint:
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
}],
|
|
5449
|
+
hint: t('group.new.where'),
|
|
5450
|
+
// The "top level" row sits LAST (user's call): it reads as "and
|
|
5451
|
+
// here is one more, belonging to none of the above" instead of as
|
|
5452
|
+
// a header the others hang under.
|
|
5453
|
+
nodes: [...groups, { id: '@top', scope: '', path: '', label: t('group.new.independent'), kind: 'new', children: [] }],
|
|
5408
5454
|
}
|
|
5409
5455
|
}
|
|
5410
5456
|
// A session group lives INSIDE one workspace (folders.sess is keyed by
|
|
@@ -5422,7 +5468,7 @@ window.__ModuleLoader__.load({
|
|
|
5422
5468
|
const sessNodesOf = (node) => {
|
|
5423
5469
|
const out = []
|
|
5424
5470
|
for (const f of node.folders || []) {
|
|
5425
|
-
out.push({ id: f.scope + '|' + f.path, scope: '', path: '', label: f
|
|
5471
|
+
out.push({ id: f.scope + '|' + f.path, scope: '', path: '', label: folderLabelOf(f), kind: 'folder', pickable: false, children: sessNodesOf(f) })
|
|
5426
5472
|
}
|
|
5427
5473
|
for (const w of node.workspaces || []) {
|
|
5428
5474
|
const inner = sessGroupNodesOf(buildSessionTree(sessionsOf(w), sessionSlash, sessFolders, w.workspaceId), w.workspaceId)
|
|
@@ -5434,7 +5480,7 @@ window.__ModuleLoader__.load({
|
|
|
5434
5480
|
}
|
|
5435
5481
|
return out
|
|
5436
5482
|
}
|
|
5437
|
-
if (treeView) return { hint: t('group.new.pickWorkspace'), nodes: sessNodesOf(
|
|
5483
|
+
if (treeView) return { hint: t('group.new.pickWorkspace'), nodes: sessNodesOf(rawTree) }
|
|
5438
5484
|
// One-level modes: every workspace sits at the root, exactly as the
|
|
5439
5485
|
// sidebar draws it (raw items — there is no .sub level to nest here).
|
|
5440
5486
|
const flat = []
|
|
@@ -6272,6 +6318,10 @@ window.__ModuleLoader__.load({
|
|
|
6272
6318
|
kinds: newGroupLayers(),
|
|
6273
6319
|
initialKind: dialog.layer === 'workspace' ? 'workspace' : 'session',
|
|
6274
6320
|
treeOf: newGroupTreeOf,
|
|
6321
|
+
// The heading names the layer(s) the button promised: with both
|
|
6322
|
+
// layers live the switch below decides, so the generic wording is
|
|
6323
|
+
// accurate there and only there.
|
|
6324
|
+
label: newGroupLabel(),
|
|
6275
6325
|
onConfirm: (kind, scope, path) => { actions.addFolder(kind, scope, path); setDialog(null) },
|
|
6276
6326
|
onClose: () => setDialog(null),
|
|
6277
6327
|
t,
|