@ondrej-svec/hog 1.8.0 → 1.8.1
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/cli.js +86 -114
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2337,7 +2337,16 @@ function navReducer(state, action) {
|
|
|
2337
2337
|
case "SET_ITEMS": {
|
|
2338
2338
|
const sections = [...new Set(action.items.map((i) => i.section))];
|
|
2339
2339
|
const isFirstLoad = state.sections.length === 0;
|
|
2340
|
-
|
|
2340
|
+
let collapsedSections;
|
|
2341
|
+
if (isFirstLoad) {
|
|
2342
|
+
collapsedSections = new Set(sections.filter((s) => s === "activity"));
|
|
2343
|
+
} else {
|
|
2344
|
+
const validIds = /* @__PURE__ */ new Set([
|
|
2345
|
+
...sections,
|
|
2346
|
+
...action.items.filter((i) => i.type === "subHeader").map((i) => i.id)
|
|
2347
|
+
]);
|
|
2348
|
+
collapsedSections = new Set([...state.collapsedSections].filter((id) => validIds.has(id)));
|
|
2349
|
+
}
|
|
2341
2350
|
const selectionValid = state.selectedId != null && action.items.some((i) => i.id === state.selectedId);
|
|
2342
2351
|
if (!isFirstLoad && selectionValid && arraysEqual(sections, state.sections)) {
|
|
2343
2352
|
return state.allItems === action.items ? state : { ...state, allItems: action.items };
|
|
@@ -4990,128 +4999,121 @@ function groupByStatus(issues) {
|
|
|
4990
4999
|
}
|
|
4991
5000
|
return groups;
|
|
4992
5001
|
}
|
|
4993
|
-
function
|
|
4994
|
-
const
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
issues.sort((a, b) => issuePriorityRank(a) - issuePriorityRank(b));
|
|
5000
|
-
return issues;
|
|
5001
|
-
}
|
|
5002
|
-
function buildNavItems(repos, tasks, activityCount) {
|
|
5003
|
-
const items = [];
|
|
5004
|
-
if (activityCount > 0) {
|
|
5005
|
-
items.push({ id: "header:activity", section: "activity", type: "header" });
|
|
5006
|
-
}
|
|
5007
|
-
for (const rd of repos) {
|
|
5008
|
-
items.push({ id: `header:${rd.repo.shortName}`, section: rd.repo.shortName, type: "header" });
|
|
5002
|
+
function buildBoardTree(repos, tasks, activity) {
|
|
5003
|
+
const sections = repos.map((rd) => {
|
|
5004
|
+
const sectionId = rd.repo.name;
|
|
5005
|
+
if (rd.error) {
|
|
5006
|
+
return { repo: rd.repo, sectionId, groups: [], error: rd.error };
|
|
5007
|
+
}
|
|
5009
5008
|
const statusGroupDefs = resolveStatusGroups(rd.statusOptions, rd.repo.statusGroups);
|
|
5010
5009
|
const byStatus = groupByStatus(rd.issues);
|
|
5011
|
-
const
|
|
5010
|
+
const coveredKeys = /* @__PURE__ */ new Set();
|
|
5011
|
+
const groups = [];
|
|
5012
5012
|
for (const sg of statusGroupDefs) {
|
|
5013
|
-
const
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5013
|
+
const issues = [];
|
|
5014
|
+
for (const [status, statusIssues] of byStatus) {
|
|
5015
|
+
if (sg.statuses.some((s) => s.toLowerCase().trim() === status.toLowerCase().trim())) {
|
|
5016
|
+
issues.push(...statusIssues);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
if (issues.length === 0) continue;
|
|
5020
|
+
issues.sort((a, b) => issuePriorityRank(a) - issuePriorityRank(b));
|
|
5021
|
+
groups.push({ label: sg.label, subId: `sub:${sectionId}:${sg.label}`, issues });
|
|
5022
|
+
for (const s of sg.statuses) coveredKeys.add(s.toLowerCase().trim());
|
|
5023
|
+
}
|
|
5024
|
+
for (const [status, statusIssues] of byStatus) {
|
|
5025
|
+
if (!(coveredKeys.has(status.toLowerCase().trim()) || isTerminalStatus(status))) {
|
|
5026
|
+
groups.push({ label: status, subId: `sub:${sectionId}:${status}`, issues: statusIssues });
|
|
5027
|
+
}
|
|
5028
|
+
}
|
|
5029
|
+
return { repo: rd.repo, sectionId, groups, error: null };
|
|
5030
|
+
});
|
|
5031
|
+
return { activity, sections, tasks };
|
|
5032
|
+
}
|
|
5033
|
+
function buildNavItems(tree) {
|
|
5034
|
+
const items = [];
|
|
5035
|
+
if (tree.activity.length > 0)
|
|
5036
|
+
items.push({ id: "header:activity", section: "activity", type: "header" });
|
|
5037
|
+
for (const { repo, sectionId, groups } of tree.sections) {
|
|
5038
|
+
items.push({ id: `header:${sectionId}`, section: sectionId, type: "header" });
|
|
5039
|
+
for (const group of groups) {
|
|
5040
|
+
items.push({ id: group.subId, section: sectionId, type: "subHeader" });
|
|
5041
|
+
for (const issue of group.issues) {
|
|
5018
5042
|
items.push({
|
|
5019
|
-
id: `gh:${
|
|
5020
|
-
section:
|
|
5043
|
+
id: `gh:${repo.name}:${issue.number}`,
|
|
5044
|
+
section: sectionId,
|
|
5021
5045
|
type: "item",
|
|
5022
|
-
subSection: subId
|
|
5046
|
+
subSection: group.subId
|
|
5023
5047
|
});
|
|
5024
5048
|
}
|
|
5025
|
-
for (const s of sg.statuses) coveredStatuses.add(s);
|
|
5026
|
-
}
|
|
5027
|
-
for (const [status, issues] of byStatus) {
|
|
5028
|
-
if (!(coveredStatuses.has(status) || isTerminalStatus(status)) && issues.length > 0) {
|
|
5029
|
-
const subId = `sub:${rd.repo.shortName}:${status}`;
|
|
5030
|
-
items.push({ id: subId, section: rd.repo.shortName, type: "subHeader" });
|
|
5031
|
-
for (const issue of issues) {
|
|
5032
|
-
items.push({
|
|
5033
|
-
id: `gh:${rd.repo.name}:${issue.number}`,
|
|
5034
|
-
section: rd.repo.shortName,
|
|
5035
|
-
type: "item",
|
|
5036
|
-
subSection: subId
|
|
5037
|
-
});
|
|
5038
|
-
}
|
|
5039
|
-
}
|
|
5040
5049
|
}
|
|
5041
5050
|
}
|
|
5042
|
-
if (tasks.length > 0) {
|
|
5051
|
+
if (tree.tasks.length > 0) {
|
|
5043
5052
|
items.push({ id: "header:ticktick", section: "ticktick", type: "header" });
|
|
5044
|
-
for (const task2 of tasks)
|
|
5053
|
+
for (const task2 of tree.tasks)
|
|
5045
5054
|
items.push({ id: `tt:${task2.id}`, section: "ticktick", type: "item" });
|
|
5046
|
-
}
|
|
5047
5055
|
}
|
|
5048
5056
|
return items;
|
|
5049
5057
|
}
|
|
5050
|
-
function buildFlatRows(
|
|
5058
|
+
function buildFlatRows(tree, isCollapsed) {
|
|
5051
5059
|
const rows = [];
|
|
5052
|
-
if (activity.length > 0) {
|
|
5060
|
+
if (tree.activity.length > 0) {
|
|
5053
5061
|
const collapsed = isCollapsed("activity");
|
|
5054
5062
|
rows.push({
|
|
5055
5063
|
type: "sectionHeader",
|
|
5056
5064
|
key: "header:activity",
|
|
5057
5065
|
navId: "header:activity",
|
|
5058
5066
|
label: "Recent Activity (24h)",
|
|
5059
|
-
count: activity.length,
|
|
5067
|
+
count: tree.activity.length,
|
|
5060
5068
|
countLabel: "events",
|
|
5061
5069
|
isCollapsed: collapsed
|
|
5062
5070
|
});
|
|
5063
5071
|
if (!collapsed) {
|
|
5064
|
-
for (const [i, event] of activity.entries()) {
|
|
5072
|
+
for (const [i, event] of tree.activity.entries()) {
|
|
5065
5073
|
rows.push({ type: "activity", key: `act:${i}`, navId: null, event });
|
|
5066
5074
|
}
|
|
5067
5075
|
}
|
|
5068
5076
|
}
|
|
5069
|
-
for (const
|
|
5070
|
-
const
|
|
5071
|
-
const
|
|
5077
|
+
for (const { repo, sectionId, groups, error } of tree.sections) {
|
|
5078
|
+
const collapsed = isCollapsed(sectionId);
|
|
5079
|
+
const totalIssues = groups.reduce((s, g) => s + g.issues.length, 0);
|
|
5072
5080
|
rows.push({
|
|
5073
5081
|
type: "sectionHeader",
|
|
5074
|
-
key: `header:${
|
|
5075
|
-
navId: `header:${
|
|
5082
|
+
key: `header:${sectionId}`,
|
|
5083
|
+
navId: `header:${sectionId}`,
|
|
5076
5084
|
label: repo.shortName,
|
|
5077
|
-
|
|
5085
|
+
// display label still shows shortName
|
|
5086
|
+
count: totalIssues,
|
|
5078
5087
|
countLabel: "issues",
|
|
5079
5088
|
isCollapsed: collapsed
|
|
5080
5089
|
});
|
|
5081
5090
|
if (!collapsed) {
|
|
5082
|
-
if (
|
|
5083
|
-
rows.push({ type: "error", key: `error:${
|
|
5084
|
-
} else if (
|
|
5091
|
+
if (error) {
|
|
5092
|
+
rows.push({ type: "error", key: `error:${sectionId}`, navId: null, text: error });
|
|
5093
|
+
} else if (groups.length === 0) {
|
|
5085
5094
|
rows.push({
|
|
5086
5095
|
type: "subHeader",
|
|
5087
|
-
key: `empty:${
|
|
5096
|
+
key: `empty:${sectionId}`,
|
|
5088
5097
|
navId: null,
|
|
5089
5098
|
text: "No open issues"
|
|
5090
5099
|
});
|
|
5091
5100
|
} else {
|
|
5092
|
-
const statusGroupDefs = resolveStatusGroups(rd.statusOptions, rd.repo.statusGroups);
|
|
5093
|
-
const byStatus = groupByStatus(issues);
|
|
5094
|
-
const coveredStatuses = /* @__PURE__ */ new Set();
|
|
5095
5101
|
let isFirstGroup = true;
|
|
5096
|
-
for (const
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
if (!isFirstGroup) {
|
|
5100
|
-
rows.push({ type: "gap", key: `gap:${repo.shortName}:${sg.label}`, navId: null });
|
|
5101
|
-
}
|
|
5102
|
+
for (const group of groups) {
|
|
5103
|
+
if (!isFirstGroup)
|
|
5104
|
+
rows.push({ type: "gap", key: `gap:${sectionId}:${group.label}`, navId: null });
|
|
5102
5105
|
isFirstGroup = false;
|
|
5103
|
-
const
|
|
5104
|
-
const subCollapsed = isCollapsed(subId);
|
|
5106
|
+
const subCollapsed = isCollapsed(group.subId);
|
|
5105
5107
|
rows.push({
|
|
5106
5108
|
type: "subHeader",
|
|
5107
|
-
key: subId,
|
|
5108
|
-
navId: subId,
|
|
5109
|
-
text:
|
|
5110
|
-
count:
|
|
5109
|
+
key: group.subId,
|
|
5110
|
+
navId: group.subId,
|
|
5111
|
+
text: group.label,
|
|
5112
|
+
count: group.issues.length,
|
|
5111
5113
|
isCollapsed: subCollapsed
|
|
5112
5114
|
});
|
|
5113
5115
|
if (!subCollapsed) {
|
|
5114
|
-
for (const issue of
|
|
5116
|
+
for (const issue of group.issues) {
|
|
5115
5117
|
rows.push({
|
|
5116
5118
|
type: "issue",
|
|
5117
5119
|
key: `gh:${repo.name}:${issue.number}`,
|
|
@@ -5121,55 +5123,24 @@ function buildFlatRows(repos, tasks, activity, isCollapsed) {
|
|
|
5121
5123
|
});
|
|
5122
5124
|
}
|
|
5123
5125
|
}
|
|
5124
|
-
for (const s of sg.statuses) coveredStatuses.add(s);
|
|
5125
|
-
}
|
|
5126
|
-
for (const [status, groupIssues] of byStatus) {
|
|
5127
|
-
if (!(coveredStatuses.has(status) || isTerminalStatus(status)) && groupIssues.length > 0) {
|
|
5128
|
-
if (!isFirstGroup) {
|
|
5129
|
-
rows.push({ type: "gap", key: `gap:${repo.shortName}:${status}`, navId: null });
|
|
5130
|
-
}
|
|
5131
|
-
isFirstGroup = false;
|
|
5132
|
-
const subId = `sub:${repo.shortName}:${status}`;
|
|
5133
|
-
const subCollapsed = isCollapsed(subId);
|
|
5134
|
-
rows.push({
|
|
5135
|
-
type: "subHeader",
|
|
5136
|
-
key: subId,
|
|
5137
|
-
navId: subId,
|
|
5138
|
-
text: status,
|
|
5139
|
-
count: groupIssues.length,
|
|
5140
|
-
isCollapsed: subCollapsed
|
|
5141
|
-
});
|
|
5142
|
-
if (!subCollapsed) {
|
|
5143
|
-
for (const issue of groupIssues) {
|
|
5144
|
-
rows.push({
|
|
5145
|
-
type: "issue",
|
|
5146
|
-
key: `gh:${repo.name}:${issue.number}`,
|
|
5147
|
-
navId: `gh:${repo.name}:${issue.number}`,
|
|
5148
|
-
issue,
|
|
5149
|
-
repoName: repo.name
|
|
5150
|
-
});
|
|
5151
|
-
}
|
|
5152
|
-
}
|
|
5153
|
-
}
|
|
5154
5126
|
}
|
|
5155
5127
|
}
|
|
5156
5128
|
}
|
|
5157
5129
|
}
|
|
5158
|
-
if (tasks.length > 0) {
|
|
5130
|
+
if (tree.tasks.length > 0) {
|
|
5159
5131
|
const collapsed = isCollapsed("ticktick");
|
|
5160
5132
|
rows.push({
|
|
5161
5133
|
type: "sectionHeader",
|
|
5162
5134
|
key: "header:ticktick",
|
|
5163
5135
|
navId: "header:ticktick",
|
|
5164
5136
|
label: "Personal (TickTick)",
|
|
5165
|
-
count: tasks.length,
|
|
5137
|
+
count: tree.tasks.length,
|
|
5166
5138
|
countLabel: "tasks",
|
|
5167
5139
|
isCollapsed: collapsed
|
|
5168
5140
|
});
|
|
5169
5141
|
if (!collapsed) {
|
|
5170
|
-
for (const task2 of tasks)
|
|
5142
|
+
for (const task2 of tree.tasks)
|
|
5171
5143
|
rows.push({ type: "task", key: `tt:${task2.id}`, navId: `tt:${task2.id}`, task: task2 });
|
|
5172
|
-
}
|
|
5173
5144
|
}
|
|
5174
5145
|
}
|
|
5175
5146
|
return rows;
|
|
@@ -5263,10 +5234,11 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5263
5234
|
const q = searchQuery.toLowerCase();
|
|
5264
5235
|
return allTasks.filter((t) => t.title.toLowerCase().includes(q));
|
|
5265
5236
|
}, [allTasks, searchQuery]);
|
|
5266
|
-
const
|
|
5267
|
-
() =>
|
|
5268
|
-
[repos, tasks, allActivity
|
|
5237
|
+
const boardTree = useMemo3(
|
|
5238
|
+
() => buildBoardTree(repos, tasks, allActivity),
|
|
5239
|
+
[repos, tasks, allActivity]
|
|
5269
5240
|
);
|
|
5241
|
+
const navItems = useMemo3(() => buildNavItems(boardTree), [boardTree]);
|
|
5270
5242
|
const nav = useNavigation(navItems);
|
|
5271
5243
|
const getRepoForId = useCallback11((id) => {
|
|
5272
5244
|
if (id.startsWith("gh:")) {
|
|
@@ -5418,8 +5390,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5418
5390
|
termSize.rows - CHROME_ROWS - overlayBarRows - toastRows - logPaneRows
|
|
5419
5391
|
);
|
|
5420
5392
|
const flatRows = useMemo3(
|
|
5421
|
-
() => buildFlatRows(
|
|
5422
|
-
[
|
|
5393
|
+
() => buildFlatRows(boardTree, nav.isCollapsed),
|
|
5394
|
+
[boardTree, nav.isCollapsed]
|
|
5423
5395
|
);
|
|
5424
5396
|
const scrollRef = useRef13(0);
|
|
5425
5397
|
const selectedRowIdx = useMemo3(
|
|
@@ -6951,7 +6923,7 @@ function resolveProjectId(projectId) {
|
|
|
6951
6923
|
process.exit(1);
|
|
6952
6924
|
}
|
|
6953
6925
|
var program = new Command();
|
|
6954
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.8.
|
|
6926
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.8.1").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
6955
6927
|
const opts = thisCommand.opts();
|
|
6956
6928
|
if (opts.json) setFormat("json");
|
|
6957
6929
|
if (opts.human) setFormat("human");
|