@ondrej-svec/hog 1.14.1 → 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 +73 -11
- 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);
|
|
@@ -4192,8 +4228,9 @@ var init_help_overlay = __esm({
|
|
|
4192
4228
|
category: "Actions",
|
|
4193
4229
|
items: [
|
|
4194
4230
|
{ key: "p", desc: "Pick issue (assign + TickTick)" },
|
|
4195
|
-
{ key: "a", desc: "Assign to self" },
|
|
4231
|
+
{ key: "a", desc: "Assign to self (no-op if already assigned)" },
|
|
4196
4232
|
{ key: "u", desc: "Undo last reversible action" },
|
|
4233
|
+
{ key: "e", desc: "Edit issue in $EDITOR (title, assignee, status, labels)" },
|
|
4197
4234
|
{ key: "c", desc: "Comment on issue" },
|
|
4198
4235
|
{ key: "m", desc: "Move status" },
|
|
4199
4236
|
{ key: "e", desc: "Edit issue in $EDITOR" },
|
|
@@ -4469,7 +4506,7 @@ function SearchBar({ defaultValue, onChange, onSubmit }) {
|
|
|
4469
4506
|
TextInput5,
|
|
4470
4507
|
{
|
|
4471
4508
|
defaultValue,
|
|
4472
|
-
placeholder: "
|
|
4509
|
+
placeholder: "title, label, status, @user, #123, unassigned\u2026",
|
|
4473
4510
|
onChange,
|
|
4474
4511
|
onSubmit
|
|
4475
4512
|
}
|
|
@@ -5315,6 +5352,31 @@ function RefreshAge({ lastRefresh }) {
|
|
|
5315
5352
|
timeAgo(lastRefresh)
|
|
5316
5353
|
] });
|
|
5317
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
|
+
}
|
|
5318
5380
|
function Dashboard({ config: config2, options, activeProfile }) {
|
|
5319
5381
|
const { exit } = useApp();
|
|
5320
5382
|
const refreshMs = config2.board.refreshInterval * 1e3;
|
|
@@ -5364,8 +5426,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5364
5426
|
})).filter((rd) => rd.issues.length > 0);
|
|
5365
5427
|
}
|
|
5366
5428
|
if (!searchQuery) return filtered;
|
|
5367
|
-
|
|
5368
|
-
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);
|
|
5369
5430
|
}, [allRepos, searchQuery, mineOnly, config2.board.assignee]);
|
|
5370
5431
|
const boardTree = useMemo3(() => buildBoardTree(repos, allActivity), [repos, allActivity]);
|
|
5371
5432
|
const [selectedRepoIdx, setSelectedRepoIdx] = useState16(0);
|
|
@@ -6165,6 +6226,7 @@ async function fetchDashboard(config2, options = {}) {
|
|
|
6165
6226
|
...issue,
|
|
6166
6227
|
...e?.targetDate !== void 0 ? { targetDate: e.targetDate } : {},
|
|
6167
6228
|
...e?.projectStatus !== void 0 ? { projectStatus: e.projectStatus } : {},
|
|
6229
|
+
...e?.customFields !== void 0 ? { customFields: e.customFields } : {},
|
|
6168
6230
|
...slackUrl ? { slackThreadUrl: slackUrl } : {}
|
|
6169
6231
|
};
|
|
6170
6232
|
});
|
|
@@ -7211,7 +7273,7 @@ function resolveProjectId(projectId) {
|
|
|
7211
7273
|
process.exit(1);
|
|
7212
7274
|
}
|
|
7213
7275
|
var program = new Command();
|
|
7214
|
-
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) => {
|
|
7215
7277
|
const opts = thisCommand.opts();
|
|
7216
7278
|
if (opts.json) setFormat("json");
|
|
7217
7279
|
if (opts.human) setFormat("human");
|