@ondrej-svec/hog 1.12.0 → 1.13.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/dist/cli.js +95 -56
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4845,47 +4845,69 @@ var init_repos_panel = __esm({
|
|
|
4845
4845
|
|
|
4846
4846
|
// src/board/components/issue-row.tsx
|
|
4847
4847
|
import { Box as Box20, Text as Text19 } from "ink";
|
|
4848
|
-
import {
|
|
4848
|
+
import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4849
4849
|
function truncate(s, max) {
|
|
4850
4850
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
4851
4851
|
}
|
|
4852
|
-
function
|
|
4853
|
-
if (
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
}
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
if (seconds < 60) return "now";
|
|
4852
|
+
function formatDate2(issue) {
|
|
4853
|
+
if (issue.targetDate) {
|
|
4854
|
+
const d = new Date(issue.targetDate);
|
|
4855
|
+
const days2 = Math.ceil((d.getTime() - Date.now()) / 864e5);
|
|
4856
|
+
if (days2 < 0) return { text: `${Math.abs(days2)}d overdue`, color: "red" };
|
|
4857
|
+
if (days2 === 0) return { text: "today", color: "yellow" };
|
|
4858
|
+
if (days2 === 1) return { text: "tomorrow", color: "white" };
|
|
4859
|
+
if (days2 <= 7) return { text: `in ${days2}d`, color: "white" };
|
|
4860
|
+
return {
|
|
4861
|
+
text: d.toLocaleDateString("en-US", { month: "short", day: "numeric" }),
|
|
4862
|
+
color: "gray"
|
|
4863
|
+
};
|
|
4864
|
+
}
|
|
4865
|
+
const seconds = Math.floor((Date.now() - new Date(issue.updatedAt).getTime()) / 1e3);
|
|
4866
|
+
if (seconds < 60) return { text: "now", color: "gray" };
|
|
4868
4867
|
const minutes = Math.floor(seconds / 60);
|
|
4869
|
-
if (minutes < 60) return `${minutes}m
|
|
4868
|
+
if (minutes < 60) return { text: `${minutes}m`, color: "gray" };
|
|
4870
4869
|
const hours = Math.floor(minutes / 60);
|
|
4871
|
-
if (hours < 24) return `${hours}h
|
|
4870
|
+
if (hours < 24) return { text: `${hours}h`, color: "gray" };
|
|
4872
4871
|
const days = Math.floor(hours / 24);
|
|
4873
|
-
if (days < 30) return `${days}d
|
|
4872
|
+
if (days < 30) return { text: `${days}d`, color: "gray" };
|
|
4874
4873
|
const months = Math.floor(days / 30);
|
|
4875
|
-
return `${months}mo
|
|
4874
|
+
return { text: `${months}mo`, color: "gray" };
|
|
4875
|
+
}
|
|
4876
|
+
function compactLabel(name) {
|
|
4877
|
+
const lc = name.toLowerCase();
|
|
4878
|
+
const colon = lc.indexOf(":");
|
|
4879
|
+
if (colon < 0) return PLAIN_ABBREVS[lc] ?? name.slice(0, 5);
|
|
4880
|
+
const key = lc.slice(0, colon);
|
|
4881
|
+
const val = name.slice(colon + 1);
|
|
4882
|
+
if (key === "size") return val.slice(0, 3).toUpperCase();
|
|
4883
|
+
if (key === "priority") return `p:${val.slice(0, 1).toUpperCase()}`;
|
|
4884
|
+
if (key === "work") return "WIP";
|
|
4885
|
+
return `${key.slice(0, 2)}:${val.slice(0, 2)}`;
|
|
4876
4886
|
}
|
|
4877
4887
|
function labelColor(name) {
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4888
|
+
const lc = name.toLowerCase();
|
|
4889
|
+
if (lc === "bug" || lc === "urgent" || lc.startsWith("priority:h") || lc.startsWith("priority:c"))
|
|
4890
|
+
return "red";
|
|
4891
|
+
if (lc.startsWith("priority:m") || lc.startsWith("work:")) return "yellow";
|
|
4892
|
+
if (lc.startsWith("priority:l") || lc === "wontfix") return "gray";
|
|
4893
|
+
if (lc.startsWith("size:")) return "white";
|
|
4894
|
+
if (lc === "feature" || lc === "enhancement") return "green";
|
|
4895
|
+
if (lc === "documentation") return "blue";
|
|
4896
|
+
if (lc === "good first issue") return "magenta";
|
|
4897
|
+
return "cyan";
|
|
4898
|
+
}
|
|
4899
|
+
function IssueRow({ issue, selfLogin, isSelected, panelWidth }) {
|
|
4881
4900
|
const assignees = issue.assignees ?? [];
|
|
4882
4901
|
const isSelf = assignees.some((a) => a.login === selfLogin);
|
|
4883
4902
|
const isUnassigned = assignees.length === 0;
|
|
4884
4903
|
const assigneeColor = isSelf ? "green" : isUnassigned ? "gray" : "white";
|
|
4885
|
-
const assigneeText = isUnassigned ? "unassigned" : truncate(assignees.map((a) => a.login).join(", "),
|
|
4904
|
+
const assigneeText = isUnassigned ? "unassigned" : truncate(assignees.map((a) => a.login).join(", "), ASSIGN_W);
|
|
4886
4905
|
const labels = (issue.labels ?? []).slice(0, 2);
|
|
4887
|
-
const
|
|
4888
|
-
const
|
|
4906
|
+
const date = formatDate2(issue);
|
|
4907
|
+
const innerW = panelWidth - 2;
|
|
4908
|
+
const titleW = Math.max(8, innerW - FIXED_OVERHEAD);
|
|
4909
|
+
const titleStr = truncate(issue.title, titleW).padEnd(titleW);
|
|
4910
|
+
const dateStr = date.text.padStart(DATE_W);
|
|
4889
4911
|
return /* @__PURE__ */ jsxs21(Box20, { children: [
|
|
4890
4912
|
isSelected ? /* @__PURE__ */ jsx21(Text19, { color: "cyan", bold: true, children: "\u25B6 " }) : /* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4891
4913
|
/* @__PURE__ */ jsxs21(Text19, { color: "cyan", children: [
|
|
@@ -4893,49 +4915,57 @@ function IssueRow({ issue, selfLogin, isSelected }) {
|
|
|
4893
4915
|
String(issue.number).padEnd(5)
|
|
4894
4916
|
] }),
|
|
4895
4917
|
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4896
|
-
isSelected ? /* @__PURE__ */ jsx21(Text19, { color: "white",
|
|
4918
|
+
isSelected ? /* @__PURE__ */ jsx21(Text19, { bold: true, color: "white", children: titleStr }) : /* @__PURE__ */ jsx21(Text19, { children: titleStr }),
|
|
4897
4919
|
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4898
|
-
/* @__PURE__ */ jsx21(Box20, { width:
|
|
4920
|
+
/* @__PURE__ */ jsx21(Box20, { width: LABEL_W, overflow: "hidden", children: labels.length === 0 ? /* @__PURE__ */ jsx21(Text19, { color: "gray", children: " ".repeat(LABEL_W) }) : labels.map((l, i) => /* @__PURE__ */ jsxs21(Text19, { children: [
|
|
4899
4921
|
i > 0 ? " " : "",
|
|
4900
4922
|
/* @__PURE__ */ jsxs21(Text19, { color: labelColor(l.name), children: [
|
|
4901
4923
|
"[",
|
|
4902
|
-
|
|
4924
|
+
compactLabel(l.name),
|
|
4903
4925
|
"]"
|
|
4904
4926
|
] })
|
|
4905
4927
|
] }, l.name)) }),
|
|
4906
4928
|
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4907
|
-
/* @__PURE__ */ jsx21(Text19, { color: assigneeColor, children: assigneeText.padEnd(
|
|
4929
|
+
/* @__PURE__ */ jsx21(Text19, { color: assigneeColor, children: assigneeText.padEnd(ASSIGN_W) }),
|
|
4908
4930
|
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4909
|
-
/* @__PURE__ */ jsx21(Text19, { color:
|
|
4910
|
-
target.text ? /* @__PURE__ */ jsxs21(Fragment3, { children: [
|
|
4911
|
-
/* @__PURE__ */ jsx21(Text19, { children: " " }),
|
|
4912
|
-
/* @__PURE__ */ jsx21(Text19, { color: target.color, children: target.text })
|
|
4913
|
-
] }) : null
|
|
4931
|
+
/* @__PURE__ */ jsx21(Text19, { color: date.color, children: dateStr })
|
|
4914
4932
|
] });
|
|
4915
4933
|
}
|
|
4916
|
-
var
|
|
4934
|
+
var PLAIN_ABBREVS, CURSOR_W, NUM_W, LABEL_W, ASSIGN_W, DATE_W, FIXED_OVERHEAD;
|
|
4917
4935
|
var init_issue_row = __esm({
|
|
4918
4936
|
"src/board/components/issue-row.tsx"() {
|
|
4919
4937
|
"use strict";
|
|
4920
|
-
|
|
4921
|
-
bug: "
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
documentation: "
|
|
4925
|
-
"good first issue": "
|
|
4926
|
-
help: "
|
|
4927
|
-
question: "
|
|
4928
|
-
urgent: "
|
|
4929
|
-
wontfix: "
|
|
4938
|
+
PLAIN_ABBREVS = {
|
|
4939
|
+
bug: "bug",
|
|
4940
|
+
feature: "feat",
|
|
4941
|
+
enhancement: "enh",
|
|
4942
|
+
documentation: "docs",
|
|
4943
|
+
"good first issue": "gfi",
|
|
4944
|
+
help: "help",
|
|
4945
|
+
question: "?",
|
|
4946
|
+
urgent: "urg!",
|
|
4947
|
+
wontfix: "wont",
|
|
4948
|
+
task: "task"
|
|
4930
4949
|
};
|
|
4931
|
-
|
|
4950
|
+
CURSOR_W = 2;
|
|
4951
|
+
NUM_W = 7;
|
|
4952
|
+
LABEL_W = 13;
|
|
4953
|
+
ASSIGN_W = 10;
|
|
4954
|
+
DATE_W = 10;
|
|
4955
|
+
FIXED_OVERHEAD = CURSOR_W + NUM_W + 1 + LABEL_W + 1 + ASSIGN_W + 1 + DATE_W;
|
|
4932
4956
|
}
|
|
4933
4957
|
});
|
|
4934
4958
|
|
|
4935
4959
|
// src/board/components/row-renderer.tsx
|
|
4936
4960
|
import { Box as Box21, Text as Text20 } from "ink";
|
|
4937
4961
|
import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4938
|
-
function RowRenderer({
|
|
4962
|
+
function RowRenderer({
|
|
4963
|
+
row,
|
|
4964
|
+
selectedId,
|
|
4965
|
+
selfLogin,
|
|
4966
|
+
isMultiSelected,
|
|
4967
|
+
panelWidth = 120
|
|
4968
|
+
}) {
|
|
4939
4969
|
switch (row.type) {
|
|
4940
4970
|
case "sectionHeader": {
|
|
4941
4971
|
const arrow = row.isCollapsed ? "\u25B6" : "\u25BC";
|
|
@@ -4990,7 +5020,15 @@ function RowRenderer({ row, selectedId, selfLogin, isMultiSelected }) {
|
|
|
4990
5020
|
const checkbox2 = isMultiSelected != null ? isMultiSelected ? "\u2611 " : "\u2610 " : "";
|
|
4991
5021
|
return /* @__PURE__ */ jsxs22(Box21, { children: [
|
|
4992
5022
|
checkbox2 ? /* @__PURE__ */ jsx22(Text20, { color: isMultiSelected ? "cyan" : "gray", children: checkbox2 }) : null,
|
|
4993
|
-
/* @__PURE__ */ jsx22(
|
|
5023
|
+
/* @__PURE__ */ jsx22(
|
|
5024
|
+
IssueRow,
|
|
5025
|
+
{
|
|
5026
|
+
issue: row.issue,
|
|
5027
|
+
selfLogin,
|
|
5028
|
+
isSelected: selectedId === row.navId,
|
|
5029
|
+
panelWidth
|
|
5030
|
+
}
|
|
5031
|
+
)
|
|
4994
5032
|
] });
|
|
4995
5033
|
}
|
|
4996
5034
|
case "activity": {
|
|
@@ -5065,10 +5103,10 @@ var init_statuses_panel = __esm({
|
|
|
5065
5103
|
// src/board/components/toast-container.tsx
|
|
5066
5104
|
import { Spinner as Spinner3 } from "@inkjs/ui";
|
|
5067
5105
|
import { Box as Box23, Text as Text22 } from "ink";
|
|
5068
|
-
import { Fragment as
|
|
5106
|
+
import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5069
5107
|
function ToastContainer({ toasts }) {
|
|
5070
5108
|
if (toasts.length === 0) return null;
|
|
5071
|
-
return /* @__PURE__ */ jsx24(Box23, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx24(Box23, { children: t.type === "loading" ? /* @__PURE__ */ jsxs24(
|
|
5109
|
+
return /* @__PURE__ */ jsx24(Box23, { flexDirection: "column", children: toasts.map((t) => /* @__PURE__ */ jsx24(Box23, { children: t.type === "loading" ? /* @__PURE__ */ jsxs24(Fragment3, { children: [
|
|
5072
5110
|
/* @__PURE__ */ jsx24(Spinner3, { label: "" }),
|
|
5073
5111
|
/* @__PURE__ */ jsxs24(Text22, { color: "cyan", children: [
|
|
5074
5112
|
" ",
|
|
@@ -5104,7 +5142,7 @@ import { execFileSync as execFileSync3, spawnSync as spawnSync4 } from "child_pr
|
|
|
5104
5142
|
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
5105
5143
|
import { Box as Box24, Text as Text23, useApp, useStdout } from "ink";
|
|
5106
5144
|
import { useCallback as useCallback12, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef13, useState as useState16 } from "react";
|
|
5107
|
-
import { Fragment as
|
|
5145
|
+
import { Fragment as Fragment4, jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5108
5146
|
function resolveStatusGroups(statusOptions, configuredGroups) {
|
|
5109
5147
|
if (configuredGroups && configuredGroups.length > 0) {
|
|
5110
5148
|
return configuredGroups.map((entry) => {
|
|
@@ -5801,6 +5839,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5801
5839
|
row,
|
|
5802
5840
|
selectedId: nav.selectedId,
|
|
5803
5841
|
selfLogin: config2.board.assignee,
|
|
5842
|
+
panelWidth: issuesPanelWidth,
|
|
5804
5843
|
isMultiSelected: ui.state.mode === "multiSelect" && row.navId ? multiSelect.isSelected(row.navId) : void 0
|
|
5805
5844
|
},
|
|
5806
5845
|
row.key
|
|
@@ -5851,10 +5890,10 @@ function Dashboard({ config: config2, options, activeProfile }) {
|
|
|
5851
5890
|
dateStr
|
|
5852
5891
|
] }),
|
|
5853
5892
|
/* @__PURE__ */ jsx25(Text23, { children: " " }),
|
|
5854
|
-
isRefreshing ? /* @__PURE__ */ jsxs25(
|
|
5893
|
+
isRefreshing ? /* @__PURE__ */ jsxs25(Fragment4, { children: [
|
|
5855
5894
|
/* @__PURE__ */ jsx25(Spinner4, { label: "" }),
|
|
5856
5895
|
/* @__PURE__ */ jsx25(Text23, { color: "cyan", children: " Refreshing..." })
|
|
5857
|
-
] }) : /* @__PURE__ */ jsxs25(
|
|
5896
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment4, { children: [
|
|
5858
5897
|
/* @__PURE__ */ jsx25(RefreshAge, { lastRefresh }),
|
|
5859
5898
|
consecutiveFailures > 0 ? /* @__PURE__ */ jsx25(Text23, { color: "red", children: " (!)" }) : null
|
|
5860
5899
|
] }),
|
|
@@ -7142,7 +7181,7 @@ function resolveProjectId(projectId) {
|
|
|
7142
7181
|
process.exit(1);
|
|
7143
7182
|
}
|
|
7144
7183
|
var program = new Command();
|
|
7145
|
-
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.
|
|
7184
|
+
program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.13.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
|
|
7146
7185
|
const opts = thisCommand.opts();
|
|
7147
7186
|
if (opts.json) setFormat("json");
|
|
7148
7187
|
if (opts.human) setFormat("human");
|