@ondrej-svec/hog 1.14.0 → 1.15.0
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 +3 -1
- package/dist/cli.js +79 -15
- package/dist/cli.js.map +1 -1
- package/dist/fetch-worker.js +22 -3
- package/dist/fetch-worker.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,9 @@ Labels are abbreviated automatically: `size:M` → `[M]`, `priority:high` → `[
|
|
|
88
88
|
| Key | Action |
|
|
89
89
|
|-----|--------|
|
|
90
90
|
| `p` | Pick up issue — assign to yourself + optional TickTick task |
|
|
91
|
-
| `a`
|
|
91
|
+
| `a` | Assign issue to yourself (no-op if already assigned to anyone) |
|
|
92
|
+
| `u` | Undo last reversible action |
|
|
93
|
+
| `e` | Edit issue in `$EDITOR` — change assignee, title, status, labels, body |
|
|
92
94
|
| `m` | Change project status |
|
|
93
95
|
| `l` | Add / remove labels |
|
|
94
96
|
| `c` | Add comment |
|
package/dist/cli.js
CHANGED
|
@@ -694,6 +694,18 @@ function fetchProjectFields(repo, issueNumber, projectNumber) {
|
|
|
694
694
|
field { ... on ProjectV2SingleSelectField { name } }
|
|
695
695
|
name
|
|
696
696
|
}
|
|
697
|
+
... on ProjectV2ItemFieldTextValue {
|
|
698
|
+
field { ... on ProjectV2Field { name } }
|
|
699
|
+
text
|
|
700
|
+
}
|
|
701
|
+
... on ProjectV2ItemFieldNumberValue {
|
|
702
|
+
field { ... on ProjectV2Field { name } }
|
|
703
|
+
number
|
|
704
|
+
}
|
|
705
|
+
... on ProjectV2ItemFieldIterationValue {
|
|
706
|
+
field { ... on ProjectV2IterationField { name } }
|
|
707
|
+
title
|
|
708
|
+
}
|
|
697
709
|
}
|
|
698
710
|
}
|
|
699
711
|
}
|
|
@@ -724,11 +736,17 @@ function fetchProjectFields(repo, issueNumber, projectNumber) {
|
|
|
724
736
|
const fieldValues = projectItem.fieldValues?.nodes ?? [];
|
|
725
737
|
for (const fv of fieldValues) {
|
|
726
738
|
if (!fv) continue;
|
|
727
|
-
|
|
739
|
+
const fieldName = fv.field?.name ?? "";
|
|
740
|
+
if ("date" in fv && DATE_FIELD_NAME_RE2.test(fieldName)) {
|
|
728
741
|
fields.targetDate = fv.date;
|
|
729
|
-
}
|
|
730
|
-
if ("name" in fv && fv.field?.name === "Status") {
|
|
742
|
+
} else if ("name" in fv && fieldName === "Status") {
|
|
731
743
|
fields.status = fv.name;
|
|
744
|
+
} else if (fieldName) {
|
|
745
|
+
const value = "text" in fv && fv.text != null ? fv.text : "number" in fv && fv.number != null ? String(fv.number) : "name" in fv && fv.name != null ? fv.name : "title" in fv && fv.title != null ? fv.title : null;
|
|
746
|
+
if (value != null) {
|
|
747
|
+
if (!fields.customFields) fields.customFields = {};
|
|
748
|
+
fields.customFields[fieldName] = value;
|
|
749
|
+
}
|
|
732
750
|
}
|
|
733
751
|
}
|
|
734
752
|
return fields;
|
|
@@ -761,6 +779,18 @@ function fetchProjectEnrichment(repo, projectNumber) {
|
|
|
761
779
|
field { ... on ProjectV2SingleSelectField { name } }
|
|
762
780
|
name
|
|
763
781
|
}
|
|
782
|
+
... on ProjectV2ItemFieldTextValue {
|
|
783
|
+
field { ... on ProjectV2Field { name } }
|
|
784
|
+
text
|
|
785
|
+
}
|
|
786
|
+
... on ProjectV2ItemFieldNumberValue {
|
|
787
|
+
field { ... on ProjectV2Field { name } }
|
|
788
|
+
number
|
|
789
|
+
}
|
|
790
|
+
... on ProjectV2ItemFieldIterationValue {
|
|
791
|
+
field { ... on ProjectV2IterationField { name } }
|
|
792
|
+
title
|
|
793
|
+
}
|
|
764
794
|
}
|
|
765
795
|
}
|
|
766
796
|
}
|
|
@@ -793,11 +823,17 @@ function fetchProjectEnrichment(repo, projectNumber) {
|
|
|
793
823
|
const fieldValues = item.fieldValues?.nodes ?? [];
|
|
794
824
|
for (const fv of fieldValues) {
|
|
795
825
|
if (!fv) continue;
|
|
796
|
-
|
|
826
|
+
const fieldName = fv.field?.name ?? "";
|
|
827
|
+
if ("date" in fv && fv.date && DATE_FIELD_NAME_RE2.test(fieldName)) {
|
|
797
828
|
enrichment.targetDate = fv.date;
|
|
798
|
-
}
|
|
799
|
-
if ("name" in fv && fv.field?.name === "Status" && fv.name) {
|
|
829
|
+
} else if ("name" in fv && fieldName === "Status" && fv.name) {
|
|
800
830
|
enrichment.projectStatus = fv.name;
|
|
831
|
+
} else if (fieldName) {
|
|
832
|
+
const value = "text" in fv && fv.text != null ? fv.text : "number" in fv && fv.number != null ? String(fv.number) : "name" in fv && fv.name != null ? fv.name : "title" in fv && fv.title != null ? fv.title : null;
|
|
833
|
+
if (value != null) {
|
|
834
|
+
if (!enrichment.customFields) enrichment.customFields = {};
|
|
835
|
+
enrichment.customFields[fieldName] = value;
|
|
836
|
+
}
|
|
801
837
|
}
|
|
802
838
|
}
|
|
803
839
|
enrichMap.set(item.content.number, enrichment);
|
|
@@ -2273,7 +2309,7 @@ function useKeyboard({
|
|
|
2273
2309
|
handleToggleLog
|
|
2274
2310
|
]
|
|
2275
2311
|
);
|
|
2276
|
-
const inputActive = ui.state.mode === "normal" || ui.state.mode === "multiSelect" || ui.state.mode === "focus";
|
|
2312
|
+
const inputActive = ui.state.mode === "normal" || ui.state.mode === "multiSelect" || ui.state.mode === "focus" || ui.state.mode === "overlay:detail";
|
|
2277
2313
|
useInput(handleInput, { isActive: inputActive });
|
|
2278
2314
|
const handleSearchEscape = useCallback4(
|
|
2279
2315
|
(_input, key) => {
|
|
@@ -2983,6 +3019,7 @@ function formatCommentAge(createdAt) {
|
|
|
2983
3019
|
function DetailPanel({
|
|
2984
3020
|
issue,
|
|
2985
3021
|
width,
|
|
3022
|
+
height,
|
|
2986
3023
|
isActive,
|
|
2987
3024
|
commentsState,
|
|
2988
3025
|
fetchComments,
|
|
@@ -2994,9 +3031,9 @@ function DetailPanel({
|
|
|
2994
3031
|
fetchComments(issueRepo, issue.number);
|
|
2995
3032
|
}, [issue, issueRepo, fetchComments, commentsState]);
|
|
2996
3033
|
if (!issue) {
|
|
2997
|
-
return /* @__PURE__ */ jsx4(Panel, { title: "[0] Detail", isActive, width, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "No item selected" }) });
|
|
3034
|
+
return /* @__PURE__ */ jsx4(Panel, { title: "[0] Detail", isActive, width, height, children: /* @__PURE__ */ jsx4(Text4, { color: "gray", children: "No item selected" }) });
|
|
2998
3035
|
}
|
|
2999
|
-
return /* @__PURE__ */ jsxs4(Panel, { title: "[0] Detail", isActive, width, children: [
|
|
3036
|
+
return /* @__PURE__ */ jsxs4(Panel, { title: "[0] Detail", isActive, width, height, children: [
|
|
3000
3037
|
/* @__PURE__ */ jsxs4(Text4, { color: "cyan", bold: true, children: [
|
|
3001
3038
|
"#",
|
|
3002
3039
|
issue.number,
|
|
@@ -4191,8 +4228,9 @@ var init_help_overlay = __esm({
|
|
|
4191
4228
|
category: "Actions",
|
|
4192
4229
|
items: [
|
|
4193
4230
|
{ key: "p", desc: "Pick issue (assign + TickTick)" },
|
|
4194
|
-
{ key: "a", desc: "Assign to self" },
|
|
4231
|
+
{ key: "a", desc: "Assign to self (no-op if already assigned)" },
|
|
4195
4232
|
{ key: "u", desc: "Undo last reversible action" },
|
|
4233
|
+
{ key: "e", desc: "Edit issue in $EDITOR (title, assignee, status, labels)" },
|
|
4196
4234
|
{ key: "c", desc: "Comment on issue" },
|
|
4197
4235
|
{ key: "m", desc: "Move status" },
|
|
4198
4236
|
{ key: "e", desc: "Edit issue in $EDITOR" },
|
|
@@ -4468,7 +4506,7 @@ function SearchBar({ defaultValue, onChange, onSubmit }) {
|
|
|
4468
4506
|
TextInput5,
|
|
4469
4507
|
{
|
|
4470
4508
|
defaultValue,
|
|
4471
|
-
placeholder: "
|
|
4509
|
+
placeholder: "title, label, status, @user, #123, unassigned\u2026",
|
|
4472
4510
|
onChange,
|
|
4473
4511
|
onSubmit
|
|
4474
4512
|
}
|
|
@@ -5314,6 +5352,31 @@ function RefreshAge({ lastRefresh }) {
|
|
|
5314
5352
|
timeAgo(lastRefresh)
|
|
5315
5353
|
] });
|
|
5316
5354
|
}
|
|
5355
|
+
function matchesSearch(issue, query) {
|
|
5356
|
+
if (!query.trim()) return true;
|
|
5357
|
+
const tokens = query.toLowerCase().trim().split(/\s+/);
|
|
5358
|
+
const labels = issue.labels ?? [];
|
|
5359
|
+
const assignees = issue.assignees ?? [];
|
|
5360
|
+
return tokens.every((token) => {
|
|
5361
|
+
if (token.startsWith("#")) {
|
|
5362
|
+
const num = parseInt(token.slice(1), 10);
|
|
5363
|
+
return !Number.isNaN(num) && issue.number === num;
|
|
5364
|
+
}
|
|
5365
|
+
if (token.startsWith("@")) {
|
|
5366
|
+
const login = token.slice(1);
|
|
5367
|
+
return assignees.some((a) => a.login.toLowerCase().includes(login));
|
|
5368
|
+
}
|
|
5369
|
+
if (token === "unassigned") return assignees.length === 0;
|
|
5370
|
+
if (token === "assigned") return assignees.length > 0;
|
|
5371
|
+
if (issue.title.toLowerCase().includes(token)) return true;
|
|
5372
|
+
if (labels.some((l) => l.name.toLowerCase().includes(token))) return true;
|
|
5373
|
+
if (issue.projectStatus?.toLowerCase().includes(token)) return true;
|
|
5374
|
+
if (issue.customFields && Object.values(issue.customFields).some((v) => v.toLowerCase().includes(token)))
|
|
5375
|
+
return true;
|
|
5376
|
+
if (assignees.some((a) => a.login.toLowerCase().includes(token))) return true;
|
|
5377
|
+
return false;
|
|
5378
|
+
});
|
|
5379
|
+
}
|
|
5317
5380
|
function Dashboard({ config: config2, options, activeProfile }) {
|
|
5318
5381
|
const { exit } = useApp();
|
|
5319
5382
|
const refreshMs = config2.board.refreshInterval * 1e3;
|
|
@@ -5363,8 +5426,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5363
5426
|
})).filter((rd) => rd.issues.length > 0);
|
|
5364
5427
|
}
|
|
5365
5428
|
if (!searchQuery) return filtered;
|
|
5366
|
-
|
|
5367
|
-
return filtered.map((rd) => ({ ...rd, issues: rd.issues.filter((i) => i.title.toLowerCase().includes(q)) })).filter((rd) => rd.issues.length > 0);
|
|
5429
|
+
return filtered.map((rd) => ({ ...rd, issues: rd.issues.filter((i) => matchesSearch(i, searchQuery)) })).filter((rd) => rd.issues.length > 0);
|
|
5368
5430
|
}, [allRepos, searchQuery, mineOnly, config2.board.assignee]);
|
|
5369
5431
|
const boardTree = useMemo3(() => buildBoardTree(repos, allActivity), [repos, allActivity]);
|
|
5370
5432
|
const [selectedRepoIdx, setSelectedRepoIdx] = useState16(0);
|
|
@@ -5966,7 +6028,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5966
6028
|
DetailPanel,
|
|
5967
6029
|
{
|
|
5968
6030
|
issue: selectedItem.issue,
|
|
5969
|
-
width:
|
|
6031
|
+
width: usableWidth,
|
|
6032
|
+
height: issuesPanelHeight + ACTIVITY_HEIGHT,
|
|
5970
6033
|
isActive: true,
|
|
5971
6034
|
issueRepo: selectedItem.repoName,
|
|
5972
6035
|
fetchComments: handleFetchComments,
|
|
@@ -6163,6 +6226,7 @@ async function fetchDashboard(config2, options = {}) {
|
|
|
6163
6226
|
...issue,
|
|
6164
6227
|
...e?.targetDate !== void 0 ? { targetDate: e.targetDate } : {},
|
|
6165
6228
|
...e?.projectStatus !== void 0 ? { projectStatus: e.projectStatus } : {},
|
|
6229
|
+
...e?.customFields !== void 0 ? { customFields: e.customFields } : {},
|
|
6166
6230
|
...slackUrl ? { slackThreadUrl: slackUrl } : {}
|
|
6167
6231
|
};
|
|
6168
6232
|
});
|
|
@@ -7209,7 +7273,7 @@ function resolveProjectId(projectId) {
|
|
|
7209
7273
|
process.exit(1);
|
|
7210
7274
|
}
|
|
7211
7275
|
var program = new Command();
|
|
7212
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.
|
|
7276
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.15.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
7213
7277
|
const opts = thisCommand.opts();
|
|
7214
7278
|
if (opts.json) setFormat("json");
|
|
7215
7279
|
if (opts.human) setFormat("human");
|