dsh-task-ledger 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +189 -70
- package/dist/client.js.map +1 -1
- package/dist/host/board.d.ts +38 -17
- package/dist/host/board.js +140 -57
- package/dist/host/routes.js +4 -5
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -536,6 +536,26 @@ body[data-ds-dark-theme]{
|
|
|
536
536
|
/* 过程正文:宽度受限、长行折行 */
|
|
537
537
|
.dtl-worklog{max-width:72ch;font-size:var(--dtl-font-md);line-height:1.6}
|
|
538
538
|
|
|
539
|
+
/* 趋势分组柱状图:细柱(8px)+ 底部基线 + 均值虚线;「精细」靠细柱与参考线 */
|
|
540
|
+
.dtl-gchart{position:relative;display:flex;align-items:flex-end;gap:10px;height:104px;
|
|
541
|
+
border-bottom:1px solid var(--dtl-border);}
|
|
542
|
+
.dtl-gchart__col{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;
|
|
543
|
+
flex:1 1 0;height:100%;min-width:0;}
|
|
544
|
+
.dtl-gchart__pair{display:flex;align-items:flex-end;gap:2px;height:100%;justify-content:center;}
|
|
545
|
+
.dtl-gchart__bar{width:8px;min-height:0;border-radius:var(--dtl-radius-xs) var(--dtl-radius-xs) 0 0;}
|
|
546
|
+
.dtl-gchart__bar--done{background:var(--dtl-business);}
|
|
547
|
+
.dtl-gchart__bar--created{background:var(--dtl-chip-bg);}
|
|
548
|
+
.dtl-gchart__col:hover .dtl-gchart__bar--done{background:var(--dtl-accent);}
|
|
549
|
+
.dtl-gchart__label{font-size:10px;line-height:14px;color:var(--dtl-fg-3);white-space:nowrap;}
|
|
550
|
+
.dtl-gchart__avg{position:absolute;left:0;right:0;border-top:1px dashed var(--dtl-border-strong);pointer-events:none;}
|
|
551
|
+
.dtl-gchart__avgtag{position:absolute;right:0;font-size:10px;line-height:12px;color:var(--dtl-fg-3);
|
|
552
|
+
background:var(--dtl-surface-1);padding:0 2px;transform:translateY(-100%);}
|
|
553
|
+
.dtl-gchart-legend{display:flex;align-items:center;gap:var(--dtl-space-3);font-size:var(--dtl-font-xs);color:var(--dtl-fg-2);}
|
|
554
|
+
.dtl-gchart-legend i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:4px;}
|
|
555
|
+
|
|
556
|
+
/* 过程正文:宽度受限、长行折行 */
|
|
557
|
+
.dtl-worklog{max-width:72ch;font-size:var(--dtl-font-md);line-height:1.6}
|
|
558
|
+
|
|
539
559
|
/* 趋势柱状图:div 柱 + token 色,无新依赖 */
|
|
540
560
|
.dtl-chart{display:flex;align-items:flex-end;gap:var(--dtl-space-2);height:120px;}
|
|
541
561
|
.dtl-chart__col{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;gap:var(--dtl-space-1);flex:1 1 0;height:100%;min-width:0;}
|
|
@@ -619,19 +639,24 @@ body[data-ds-dark-theme]{
|
|
|
619
639
|
}
|
|
620
640
|
});
|
|
621
641
|
}
|
|
622
|
-
/** 统计卡:主数字 + 灰色口径小字;点一下联动下方列表筛选。
|
|
642
|
+
/** 统计卡:主数字 + 灰色口径小字;点一下联动下方列表筛选。
|
|
643
|
+
* `value` 为 0 时显示「—」(用户 2026-10-17 定稿:0 会被读成「没数据 / 出错了」);
|
|
644
|
+
* `hint` 可以是富文本(如把「停滞」两字标红);
|
|
645
|
+
* `interactive: false` = 纯展示卡(统计台:首页没有已结案可筛,不装可点)。 */
|
|
623
646
|
function StatCard(props) {
|
|
624
647
|
ensureUiBase();
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
"
|
|
648
|
+
const interactive = props.interactive !== false && props.onClick !== void 0;
|
|
649
|
+
const shown = props.value === 0 || props.value === "0" ? "—" : String(props.value);
|
|
650
|
+
return (0, react.createElement)(interactive ? "button" : "div", {
|
|
651
|
+
type: interactive ? "button" : void 0,
|
|
652
|
+
className: `dtl-card dtl-stat${interactive ? " dtl-card--clickable" : ""}`,
|
|
653
|
+
"data-active": props.active === true,
|
|
629
654
|
title: props.title,
|
|
630
|
-
onClick: props.onClick
|
|
655
|
+
onClick: interactive ? props.onClick : void 0
|
|
631
656
|
}, (0, react.createElement)("span", { style: {
|
|
632
657
|
fontSize: "var(--dtl-font-sm)",
|
|
633
658
|
color: "var(--dtl-fg-2)"
|
|
634
|
-
} }, props.label), (0, react.createElement)("span", { className: "dtl-stat__value" },
|
|
659
|
+
} }, props.label), (0, react.createElement)("span", { className: "dtl-stat__value" }, shown), props.hint === void 0 || props.hint === null || props.hint === "" ? null : (0, react.createElement)("span", { className: "dtl-stat__hint" }, props.hint));
|
|
635
660
|
}
|
|
636
661
|
/** chip(分类 / 标签 / 工作区名)。 */
|
|
637
662
|
function Chip(props) {
|
|
@@ -658,25 +683,41 @@ body[data-ds-dark-theme]{
|
|
|
658
683
|
color: "var(--dtl-fg-2)"
|
|
659
684
|
} }, props.hint));
|
|
660
685
|
}
|
|
661
|
-
/**
|
|
662
|
-
*
|
|
663
|
-
|
|
664
|
-
*/
|
|
665
|
-
function BarChart(props) {
|
|
686
|
+
/** 分组柱状图(div 柱,无新依赖):完成 / 新增各一细柱,底部基线 + 完成数平均值虚线。
|
|
687
|
+
* 「精细」= 细柱 + 基线 + 均值线,不是粗柱堆高度(用户 2026-10-17)。 */
|
|
688
|
+
function GroupedBarChart(props) {
|
|
666
689
|
ensureUiBase();
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
690
|
+
const plotHeight = 104;
|
|
691
|
+
const max = props.weeks.reduce((peak, week) => Math.max(peak, week.done, week.created), 0);
|
|
692
|
+
const doneTotal = props.weeks.reduce((sum, week) => sum + week.done, 0);
|
|
693
|
+
const avg = props.weeks.length === 0 ? 0 : doneTotal / props.weeks.length;
|
|
694
|
+
const barHeight = (value) => max === 0 ? 0 : Math.round(value / max * plotHeight);
|
|
695
|
+
return (0, react.createElement)("div", { style: {
|
|
696
|
+
position: "relative",
|
|
697
|
+
paddingBottom: "18px"
|
|
698
|
+
} }, (0, react.createElement)("div", {
|
|
699
|
+
className: "dtl-gchart",
|
|
670
700
|
role: "img",
|
|
671
701
|
"aria-label": props.ariaLabel
|
|
672
|
-
},
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
className: "dtl-
|
|
678
|
-
|
|
679
|
-
}
|
|
702
|
+
}, avg > 0 ? (0, react.createElement)("div", {
|
|
703
|
+
className: "dtl-gchart__avg",
|
|
704
|
+
style: { bottom: `${barHeight(avg)}px` }
|
|
705
|
+
}, (0, react.createElement)("span", { className: "dtl-gchart__avgtag" }, props.avgLabel)) : null, props.weeks.map((week) => (0, react.createElement)("div", {
|
|
706
|
+
key: week.label,
|
|
707
|
+
className: "dtl-gchart__col",
|
|
708
|
+
title: week.title
|
|
709
|
+
}, (0, react.createElement)("div", { className: "dtl-gchart__pair" }, (0, react.createElement)("span", {
|
|
710
|
+
className: "dtl-gchart__bar dtl-gchart__bar--done",
|
|
711
|
+
style: { height: `${barHeight(week.done)}px` }
|
|
712
|
+
}), (0, react.createElement)("span", {
|
|
713
|
+
className: "dtl-gchart__bar dtl-gchart__bar--created",
|
|
714
|
+
style: { height: `${barHeight(week.created)}px` }
|
|
715
|
+
})), (0, react.createElement)("span", { className: "dtl-gchart__label" }, week.label)))));
|
|
716
|
+
}
|
|
717
|
+
/** 图例(完成 / 新增 两个色块)。 */
|
|
718
|
+
function ChartLegend(props) {
|
|
719
|
+
ensureUiBase();
|
|
720
|
+
return (0, react.createElement)("div", { className: "dtl-gchart-legend" }, (0, react.createElement)("span", null, (0, react.createElement)("i", { style: { background: "var(--dtl-business)" } }), props.doneLabel), (0, react.createElement)("span", null, (0, react.createElement)("i", { style: { background: "var(--dtl-chip-bg)" } }), props.createdLabel));
|
|
680
721
|
}
|
|
681
722
|
//#endregion
|
|
682
723
|
//#region src/client/task-row.ts
|
|
@@ -875,18 +916,29 @@ body[data-ds-dark-theme]{
|
|
|
875
916
|
fontSize: "var(--dtl-font-xl)",
|
|
876
917
|
fontWeight: 600
|
|
877
918
|
};
|
|
878
|
-
/**
|
|
879
|
-
|
|
919
|
+
/** 操作台:全宽 4 列。列数**写死 4**,不用 auto-fit——那会排出 3+1 的非对称
|
|
920
|
+
* (用户 2026-10-17:必须上下对称;窄屏由 statsRowStyle 的堆叠兜底,仍是 2+2)。 */
|
|
921
|
+
const cardsGridStyle = {
|
|
922
|
+
display: "grid",
|
|
923
|
+
gridTemplateColumns: "repeat(4,minmax(0,1fr))",
|
|
924
|
+
gap: "var(--dtl-space-3)"
|
|
925
|
+
};
|
|
926
|
+
/** 第二行:统计台(2×2)+ 趋势图(右 1/3)。 */
|
|
927
|
+
const statsRowStyle = {
|
|
880
928
|
display: "grid",
|
|
881
929
|
gridTemplateColumns: "minmax(0,2fr) minmax(0,1fr)",
|
|
882
|
-
gap: "var(--dtl-space-3)"
|
|
883
|
-
marginBottom: "var(--dtl-space-4)"
|
|
930
|
+
gap: "var(--dtl-space-3)"
|
|
884
931
|
};
|
|
885
|
-
const
|
|
932
|
+
const statsCardsStyle = {
|
|
886
933
|
display: "grid",
|
|
887
|
-
gridTemplateColumns: "repeat(
|
|
934
|
+
gridTemplateColumns: "repeat(2,minmax(0,1fr))",
|
|
888
935
|
gap: "var(--dtl-space-3)"
|
|
889
936
|
};
|
|
937
|
+
const regionCaptionStyle = {
|
|
938
|
+
fontSize: "var(--dtl-font-xs)",
|
|
939
|
+
color: "var(--dtl-fg-3)",
|
|
940
|
+
margin: "var(--dtl-space-4) 0 var(--dtl-space-2)"
|
|
941
|
+
};
|
|
890
942
|
const chartCardStyle = {
|
|
891
943
|
display: "flex",
|
|
892
944
|
flexDirection: "column",
|
|
@@ -959,14 +1011,34 @@ body[data-ds-dark-theme]{
|
|
|
959
1011
|
setQuery(patch);
|
|
960
1012
|
}
|
|
961
1013
|
});
|
|
962
|
-
|
|
1014
|
+
/** 统计台卡:不可点(首页没有已结案可筛),hover 给具体日期区间。 */
|
|
1015
|
+
const periodCard = (label, period) => (0, react.createElement)(StatCard, {
|
|
1016
|
+
label: t(label),
|
|
1017
|
+
value: period?.done ?? 0,
|
|
1018
|
+
hint: t("statCreatedHint", { n: period?.created ?? 0 }),
|
|
1019
|
+
interactive: false,
|
|
1020
|
+
title: period === void 0 ? void 0 : t("periodRange", {
|
|
1021
|
+
from: period.from,
|
|
1022
|
+
to: period.to
|
|
1023
|
+
})
|
|
1024
|
+
});
|
|
1025
|
+
const [chartScope, setChartScope] = (0, react.useState)("all");
|
|
1026
|
+
const chartWeeks = (0, react.useMemo)(() => (board === null ? [] : board.closed.weekly[chartScope]).map((bucket) => ({
|
|
963
1027
|
label: bucket.week.slice(5),
|
|
964
|
-
|
|
1028
|
+
done: bucket.done,
|
|
1029
|
+
created: bucket.created,
|
|
965
1030
|
title: t("chartBucket", {
|
|
966
1031
|
week: bucket.week,
|
|
967
|
-
|
|
1032
|
+
done: bucket.done,
|
|
1033
|
+
created: bucket.created
|
|
968
1034
|
})
|
|
969
|
-
})), [
|
|
1035
|
+
})), [
|
|
1036
|
+
board,
|
|
1037
|
+
chartScope,
|
|
1038
|
+
t
|
|
1039
|
+
]);
|
|
1040
|
+
const chartDoneTotal = chartWeeks.reduce((sum, week) => sum + week.done, 0);
|
|
1041
|
+
const chartEmpty = chartWeeks.every((week) => week.done === 0 && week.created === 0);
|
|
970
1042
|
return (0, react.createElement)("div", { style: pageStyle }, (0, react.createElement)("div", { style: {
|
|
971
1043
|
display: "flex",
|
|
972
1044
|
justifyContent: "center"
|
|
@@ -1009,42 +1081,73 @@ body[data-ds-dark-theme]{
|
|
|
1009
1081
|
onClick: () => {
|
|
1010
1082
|
refresh();
|
|
1011
1083
|
}
|
|
1012
|
-
}, state.refreshing ? t("refreshing") : t("refresh")))), tab === "stats" ? (0, react.createElement)("div", { style: hintStyle }, t("statsPlaceholder")) : (0, react.createElement)("div", null, stats === void 0 ? null : (0, react.createElement)("div", { style:
|
|
1084
|
+
}, state.refreshing ? t("refreshing") : t("refresh")))), tab === "stats" ? (0, react.createElement)("div", { style: hintStyle }, t("statsPlaceholder")) : (0, react.createElement)("div", null, stats === void 0 ? null : (0, react.createElement)("div", { style: cardsGridStyle }, card("statMyActive", stats.myActive, t("statMyActiveHint", { n: stats.myBlocked }), {
|
|
1013
1085
|
scope: "mine",
|
|
1014
1086
|
status: "all",
|
|
1015
1087
|
workspace: ""
|
|
1016
|
-
}), card("statOpen",
|
|
1088
|
+
}), card("statOpen", stats.open, t("statOpenHint", { n: days(stats.oldestOpenDays) }), {
|
|
1017
1089
|
scope: "all",
|
|
1018
1090
|
status: "open",
|
|
1019
1091
|
workspace: ""
|
|
1020
|
-
}), card("statDoing",
|
|
1092
|
+
}), card("statDoing", stats.doing, t("statDoingHint", { n: stats.doing - stats.myActive + stats.myBlocked }), {
|
|
1021
1093
|
scope: "all",
|
|
1022
1094
|
status: "active",
|
|
1023
1095
|
workspace: ""
|
|
1024
|
-
}),
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1096
|
+
}), (0, react.createElement)(StatCard, {
|
|
1097
|
+
label: t("statBlockedStale"),
|
|
1098
|
+
value: stats.blocked,
|
|
1099
|
+
hint: stats.stale === 0 ? void 0 : (0, react.createElement)("span", null, (0, react.createElement)("span", { style: {
|
|
1100
|
+
color: "var(--dtl-danger)",
|
|
1101
|
+
fontWeight: 600
|
|
1102
|
+
} }, t("statStaleWord")), ` ${t("statStaleHint", { n: stats.stale })}`),
|
|
1103
|
+
active: isActive(state.query, {
|
|
1104
|
+
scope: "all",
|
|
1105
|
+
status: "blocked",
|
|
1106
|
+
workspace: ""
|
|
1107
|
+
}),
|
|
1108
|
+
title: t("statStaleHint", { n: stats.staleDays }),
|
|
1109
|
+
onClick: () => {
|
|
1110
|
+
setQuery({
|
|
1111
|
+
scope: "all",
|
|
1112
|
+
status: "blocked",
|
|
1113
|
+
workspace: ""
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
})), (0, react.createElement)("div", { style: regionCaptionStyle }, t("tabStats")), (0, react.createElement)("div", { style: statsRowStyle }, (0, react.createElement)("div", { style: statsCardsStyle }, periodCard("statWeekDone", board?.trend.thisWeek), periodCard("statLastWeekDone", board?.trend.lastWeek), periodCard("statMonthDone", board?.trend.thisMonth), periodCard("statLastMonthDone", board?.trend.lastMonth)), (0, react.createElement)("div", {
|
|
1037
1117
|
className: "dtl-card",
|
|
1038
1118
|
style: chartCardStyle
|
|
1039
1119
|
}, (0, react.createElement)("div", { style: {
|
|
1120
|
+
display: "flex",
|
|
1121
|
+
alignItems: "center",
|
|
1122
|
+
justifyContent: "space-between",
|
|
1123
|
+
gap: "var(--dtl-space-2)"
|
|
1124
|
+
} }, (0, react.createElement)("span", { style: {
|
|
1040
1125
|
fontSize: "var(--dtl-font-md)",
|
|
1041
1126
|
fontWeight: 600
|
|
1042
|
-
} }, t("chartTitle")),
|
|
1127
|
+
} }, t("chartTitle")), (0, react.createElement)(Segmented, {
|
|
1128
|
+
id: "dtl-chart-scope",
|
|
1129
|
+
value: chartScope,
|
|
1130
|
+
label: t("scopeLabel"),
|
|
1131
|
+
size: "sm",
|
|
1132
|
+
variant: "inset",
|
|
1133
|
+
items: [{
|
|
1134
|
+
value: "all",
|
|
1135
|
+
label: t("chartScopeAll")
|
|
1136
|
+
}, {
|
|
1137
|
+
value: "mine",
|
|
1138
|
+
label: t("chartScopeMine")
|
|
1139
|
+
}],
|
|
1140
|
+
onChange: setChartScope
|
|
1141
|
+
})), chartEmpty ? (0, react.createElement)("div", { style: {
|
|
1043
1142
|
...hintStyle,
|
|
1044
1143
|
padding: "var(--dtl-space-4) 0"
|
|
1045
|
-
} }, t("chartEmpty")) : (0, react.createElement)(
|
|
1046
|
-
|
|
1047
|
-
ariaLabel: t("chartTitle")
|
|
1144
|
+
} }, t("chartEmpty")) : (0, react.createElement)(GroupedBarChart, {
|
|
1145
|
+
weeks: chartWeeks,
|
|
1146
|
+
ariaLabel: t("chartTitle"),
|
|
1147
|
+
avgLabel: t("chartAvg", { n: Math.round(chartDoneTotal / Math.max(1, chartWeeks.length) * 10) / 10 })
|
|
1148
|
+
}), (0, react.createElement)(ChartLegend, {
|
|
1149
|
+
doneLabel: t("chartLegendDone"),
|
|
1150
|
+
createdLabel: t("chartLegendCreated")
|
|
1048
1151
|
}), (0, react.createElement)("div", { style: {
|
|
1049
1152
|
fontSize: "var(--dtl-font-xs)",
|
|
1050
1153
|
color: "var(--dtl-fg-3)"
|
|
@@ -1209,18 +1312,26 @@ body[data-ds-dark-theme]{
|
|
|
1209
1312
|
statOpenHint: "最老一条躺了 {n}",
|
|
1210
1313
|
statDoing: "进行中",
|
|
1211
1314
|
statDoingHint: "别人在做 {n}",
|
|
1212
|
-
|
|
1213
|
-
|
|
1315
|
+
statBlockedStale: "阻塞 · 停滞",
|
|
1316
|
+
statStaleWord: "停滞",
|
|
1317
|
+
statStaleHint: "{n} 条",
|
|
1214
1318
|
statWeekDone: "本周完成",
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1319
|
+
statLastWeekDone: "上周完成",
|
|
1320
|
+
statMonthDone: "本月完成",
|
|
1321
|
+
statLastMonthDone: "上月完成",
|
|
1322
|
+
statCreatedHint: "新增 {n} 条",
|
|
1218
1323
|
daysNone: "—",
|
|
1219
1324
|
daysValue: "{n} 天",
|
|
1220
|
-
chartTitle: "近 8
|
|
1221
|
-
chartCaption: "
|
|
1222
|
-
chartBucket: "{week} 那一周:完成 {
|
|
1223
|
-
chartEmpty: "近 8
|
|
1325
|
+
chartTitle: "近 8 周",
|
|
1326
|
+
chartCaption: "完成(按结案时间)/ 新增(按创建时间),周一起桶;我的 = owner 是我",
|
|
1327
|
+
chartBucket: "{week} 那一周:完成 {done} 条,新增 {created} 条",
|
|
1328
|
+
chartEmpty: "近 8 周没有记录",
|
|
1329
|
+
chartScopeAll: "所有",
|
|
1330
|
+
chartScopeMine: "我的",
|
|
1331
|
+
chartLegendDone: "完成",
|
|
1332
|
+
chartLegendCreated: "新增",
|
|
1333
|
+
chartAvg: "周均 {n}",
|
|
1334
|
+
periodRange: "{from} ~ {to}",
|
|
1224
1335
|
scopeLabel: "范围",
|
|
1225
1336
|
scopeMine: "我的",
|
|
1226
1337
|
scopeAll: "全部工作区",
|
|
@@ -1277,18 +1388,26 @@ body[data-ds-dark-theme]{
|
|
|
1277
1388
|
statOpenHint: "oldest waiting {n}",
|
|
1278
1389
|
statDoing: "In progress",
|
|
1279
1390
|
statDoingHint: "{n} by others",
|
|
1280
|
-
|
|
1281
|
-
|
|
1391
|
+
statBlockedStale: "Blocked · Stale",
|
|
1392
|
+
statStaleWord: "Stale",
|
|
1393
|
+
statStaleHint: "{n}",
|
|
1282
1394
|
statWeekDone: "Done this week",
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1395
|
+
statLastWeekDone: "Done last week",
|
|
1396
|
+
statMonthDone: "Done this month",
|
|
1397
|
+
statLastMonthDone: "Done last month",
|
|
1398
|
+
statCreatedHint: "{n} created",
|
|
1286
1399
|
daysNone: "—",
|
|
1287
1400
|
daysValue: "{n}d",
|
|
1288
1401
|
chartTitle: "Last 8 weeks",
|
|
1289
|
-
chartCaption: "by close time, weeks start Monday;
|
|
1290
|
-
chartBucket: "week of {week}: {
|
|
1291
|
-
chartEmpty: "Nothing
|
|
1402
|
+
chartCaption: "done (by close time) / created (by create time), weeks start Monday; mine = owner is me",
|
|
1403
|
+
chartBucket: "week of {week}: {done} done, {created} created",
|
|
1404
|
+
chartEmpty: "Nothing in the last 8 weeks",
|
|
1405
|
+
chartScopeAll: "All",
|
|
1406
|
+
chartScopeMine: "Mine",
|
|
1407
|
+
chartLegendDone: "Done",
|
|
1408
|
+
chartLegendCreated: "Created",
|
|
1409
|
+
chartAvg: "avg {n}/wk",
|
|
1410
|
+
periodRange: "{from} ~ {to}",
|
|
1292
1411
|
scopeLabel: "Scope",
|
|
1293
1412
|
scopeMine: "Mine",
|
|
1294
1413
|
scopeAll: "All workspaces",
|