@takagaki/cortex-decisions-viewer 0.4.20 → 0.4.22
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/build.js +21 -2
- package/dist/render.js +123 -20
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -107,7 +107,7 @@ function resolveKnowledgeRoot(decisionsDirAbs) {
|
|
|
107
107
|
return null;
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
* リポジトリルートの fleet-status.json から externalSources / pipelines を読む。
|
|
110
|
+
* リポジトリルートの fleet-status.json から externalSources / internalSources / pipelines を読む。
|
|
111
111
|
* ファイルが無い・パース不能・当該フィールドが無い場合は undefined を返し、
|
|
112
112
|
* ビューア側で「データソースと自動化」セクションを出さない(後方互換・旧fleet-statusで壊れない)。
|
|
113
113
|
*/
|
|
@@ -130,11 +130,27 @@ async function readFleetSources(repoRoot) {
|
|
|
130
130
|
type: String(s.type ?? ""),
|
|
131
131
|
name: String(s.name ?? ""),
|
|
132
132
|
ref: s.ref != null ? String(s.ref) : undefined,
|
|
133
|
+
url: s.url != null ? String(s.url) : undefined,
|
|
133
134
|
gold: typeof s.gold === "boolean" ? s.gold : undefined,
|
|
134
135
|
notify: typeof s.notify === "boolean" ? s.notify : undefined,
|
|
135
136
|
gate: s.gate != null ? String(s.gate) : undefined,
|
|
136
137
|
}))
|
|
137
138
|
: undefined;
|
|
139
|
+
const internalSources = Array.isArray(obj.internalSources)
|
|
140
|
+
? obj.internalSources
|
|
141
|
+
.filter((s) => s != null && typeof s === "object")
|
|
142
|
+
.map((s) => ({
|
|
143
|
+
kind: String(s.kind ?? ""),
|
|
144
|
+
tool: String(s.tool ?? ""),
|
|
145
|
+
label: String(s.label ?? ""),
|
|
146
|
+
url: s.url != null ? String(s.url) : undefined,
|
|
147
|
+
lastSync: s.lastSync != null ? String(s.lastSync) : undefined,
|
|
148
|
+
matchKeys: Array.isArray(s.matchKeys)
|
|
149
|
+
? s.matchKeys.map((k) => String(k)).filter(Boolean)
|
|
150
|
+
: undefined,
|
|
151
|
+
driveSync: typeof s.driveSync === "boolean" ? s.driveSync : undefined,
|
|
152
|
+
}))
|
|
153
|
+
: undefined;
|
|
138
154
|
const pipelines = Array.isArray(obj.pipelines)
|
|
139
155
|
? obj.pipelines
|
|
140
156
|
.filter((p) => p != null && typeof p === "object")
|
|
@@ -142,9 +158,11 @@ async function readFleetSources(repoRoot) {
|
|
|
142
158
|
id: String(p.id ?? ""),
|
|
143
159
|
label: String(p.label ?? ""),
|
|
144
160
|
lastSuccess: p.lastSuccess != null ? String(p.lastSuccess) : undefined,
|
|
161
|
+
lastConclusion: p.lastConclusion != null ? String(p.lastConclusion) : undefined,
|
|
162
|
+
lastRun: p.lastRun != null ? String(p.lastRun) : undefined,
|
|
145
163
|
}))
|
|
146
164
|
: undefined;
|
|
147
|
-
return { externalSources, pipelines };
|
|
165
|
+
return { externalSources, internalSources, pipelines };
|
|
148
166
|
}
|
|
149
167
|
/** ディレクトリ内の .md を汎用レコードとして読み込む(存在しなければ空配列) */
|
|
150
168
|
async function loadGenericRecords(dirAbs, exclude, repoBaseUrl, branch) {
|
|
@@ -927,6 +945,7 @@ async function build(opts) {
|
|
|
927
945
|
}
|
|
928
946
|
: undefined,
|
|
929
947
|
externalSources: fleet.externalSources,
|
|
948
|
+
internalSources: fleet.internalSources,
|
|
930
949
|
pipelines: fleet.pipelines,
|
|
931
950
|
};
|
|
932
951
|
// サムネイル(デザイン画面等)をサイトに同梱し、ノードのパスをサイト内相対に書き換える
|
package/dist/render.js
CHANGED
|
@@ -339,6 +339,27 @@ a:hover { text-decoration: underline; }
|
|
|
339
339
|
.ds-icon { font-size: 18px; line-height: 1; flex: 0 0 auto; }
|
|
340
340
|
.ds-type { font-size: 12px; font-weight: 600; color: var(--muted); flex: 0 0 auto; }
|
|
341
341
|
.ds-name { font-size: 14.5px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
342
|
+
a.ds-name { color: var(--accent); }
|
|
343
|
+
a.ds-name:hover { text-decoration: underline; }
|
|
344
|
+
.ds-note { color: var(--muted); font-size: 12px; line-height: 1.7; margin: 6px 0 0; }
|
|
345
|
+
.ds-sync { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
|
|
346
|
+
.ds-col { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
|
|
347
|
+
.ds-keys { font-size: 12px; color: var(--muted); line-height: 1.6; }
|
|
348
|
+
.ds-drive-note { font-size: 12px; color: #6b7280; line-height: 1.6; }
|
|
349
|
+
.ds-group { border: none; margin: 0; }
|
|
350
|
+
.ds-group > summary {
|
|
351
|
+
display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; cursor: pointer;
|
|
352
|
+
background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
|
|
353
|
+
padding: 14px 16px; box-shadow: var(--shadow); font-size: 14.5px; font-weight: 600; color: var(--text);
|
|
354
|
+
list-style: none;
|
|
355
|
+
}
|
|
356
|
+
.ds-group > summary::-webkit-details-marker { display: none; }
|
|
357
|
+
.ds-group > summary::after { content: "▸"; margin-left: auto; color: var(--muted); font-size: 12px; }
|
|
358
|
+
.ds-group[open] > summary::after { content: "▾"; }
|
|
359
|
+
.ds-group[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
|
|
360
|
+
.ds-group > .ds-list { margin-top: 8px; padding-left: 12px; border-left: 2px solid var(--border); }
|
|
361
|
+
.badge.ds-sum-ok { background: #e9f7ef; color: #1f7a45; }
|
|
362
|
+
.badge.ds-sum-warn { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
|
|
342
363
|
.ds-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; flex: 0 0 auto; }
|
|
343
364
|
.badge.ds-gold { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
|
|
344
365
|
.badge.ds-excluded { background: #eceef1; color: #6b7280; }
|
|
@@ -355,6 +376,7 @@ a:hover { text-decoration: underline; }
|
|
|
355
376
|
}
|
|
356
377
|
.ds-pipe-label { font-size: 14px; font-weight: 600; color: var(--text); }
|
|
357
378
|
.ds-pipe-time { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
379
|
+
.ds-pipe-status { font-size: 13px; line-height: 1; flex: 0 0 auto; }
|
|
358
380
|
/* ---- 操作タブ ---- */
|
|
359
381
|
.ops-intro { color: var(--muted); font-size: 14px; line-height: 1.8; margin: 4px 0 8px; }
|
|
360
382
|
.ops-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
|
|
@@ -690,6 +712,14 @@ const CLIENT_JS = `
|
|
|
690
712
|
"no_token": { text: "トークン未設定", cls: "ds-gate-muted" },
|
|
691
713
|
"unknown": { text: "不明", cls: "ds-gate-muted" },
|
|
692
714
|
};
|
|
715
|
+
var DS_KIND_ICON = {
|
|
716
|
+
"課題管理": "📋",
|
|
717
|
+
"会議": "🗒️",
|
|
718
|
+
"共有資料": "📎",
|
|
719
|
+
"デザイン": "🎨",
|
|
720
|
+
"開発": "🐙",
|
|
721
|
+
"チャット": "💬",
|
|
722
|
+
};
|
|
693
723
|
function dsFmtTime(iso) {
|
|
694
724
|
var d = new Date(iso);
|
|
695
725
|
if (isNaN(d.getTime())) return "";
|
|
@@ -697,38 +727,88 @@ const CLIENT_JS = `
|
|
|
697
727
|
var mm = ("0" + d.getMinutes()).slice(-2);
|
|
698
728
|
return (d.getMonth() + 1) + "/" + d.getDate() + " " + hh + ":" + mm;
|
|
699
729
|
}
|
|
730
|
+
// 名前表示: url があれば新しいタブで正本を開くリンクにする
|
|
731
|
+
function dsNameEl(text, url) {
|
|
732
|
+
if (url) return el("a", { class: "ds-name", href: url, target: "_blank", rel: "noopener", text: text });
|
|
733
|
+
return el("span", { class: "ds-name", text: text });
|
|
734
|
+
}
|
|
700
735
|
function renderDataSources() {
|
|
736
|
+
var internals = SITE.internalSources || [];
|
|
701
737
|
var sources = SITE.externalSources || [];
|
|
702
738
|
var pipes = SITE.pipelines || [];
|
|
703
|
-
if (!sources.length && !pipes.length) return; //
|
|
739
|
+
if (!internals.length && !sources.length && !pipes.length) return; // すべて無ければセクションごと出さない
|
|
704
740
|
|
|
705
741
|
var sec = el("section", { class: "datasources" });
|
|
706
742
|
sec.appendChild(el("h2", { class: "datasources-head", text: "データソースと自動化" }));
|
|
707
743
|
sec.appendChild(el("p", { class: "datasources-intro", text: "このCortexが接続している情報源と、毎晩自動でGoldに昇格する処理の一覧です。" }));
|
|
708
744
|
|
|
709
|
-
if (
|
|
710
|
-
sec.appendChild(el("div", { class: "ds-sub", text: "
|
|
711
|
-
var
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
var
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
745
|
+
if (internals.length) {
|
|
746
|
+
sec.appendChild(el("div", { class: "ds-sub", text: "リポジトリ内の情報源(自動同期)" }));
|
|
747
|
+
var ilist = el("div", { class: "ds-list" });
|
|
748
|
+
internals.forEach(function (s) {
|
|
749
|
+
// ラベルの下に補足行(会議の照合キー・Drive未設定の注記)を重ねられるよう縦組みにする
|
|
750
|
+
var col = el("div", { class: "ds-col" }, [ dsNameEl(s.label || "", s.url) ]);
|
|
751
|
+
var keys = s.matchKeys || [];
|
|
752
|
+
if (keys.length) {
|
|
753
|
+
var shown = keys.slice(0, 5).join(" / ");
|
|
754
|
+
if (keys.length > 5) shown += " 他" + (keys.length - 5) + "件";
|
|
755
|
+
col.appendChild(el("span", {
|
|
756
|
+
class: "ds-keys",
|
|
757
|
+
text: "取り込み対象の会議名: " + shown,
|
|
758
|
+
title: "会議名にこれらの語が含まれていると、自動でこのCortexに取り込まれます",
|
|
759
|
+
}));
|
|
760
|
+
}
|
|
761
|
+
if (s.driveSync === false) {
|
|
762
|
+
col.appendChild(el("span", { class: "ds-drive-note", text: "Drive自動同期は未設定(手動で置いたファイルの変換のみ)" }));
|
|
763
|
+
}
|
|
720
764
|
var card = el("div", { class: "ds-card" }, [
|
|
721
765
|
el("div", { class: "ds-card-main" }, [
|
|
722
|
-
el("span", { class: "ds-icon", text:
|
|
723
|
-
el("span", { class: "ds-type", text:
|
|
724
|
-
|
|
766
|
+
el("span", { class: "ds-icon", text: DS_KIND_ICON[s.kind] || "📁" }),
|
|
767
|
+
el("span", { class: "ds-type", text: s.kind || "" }),
|
|
768
|
+
col,
|
|
725
769
|
]),
|
|
726
|
-
|
|
727
|
-
|
|
770
|
+
s.lastSync && dsFmtTime(s.lastSync)
|
|
771
|
+
? el("span", { class: "ds-sync", text: "最終同期: " + dsFmtTime(s.lastSync) })
|
|
772
|
+
: null,
|
|
728
773
|
]);
|
|
729
|
-
|
|
774
|
+
ilist.appendChild(card);
|
|
775
|
+
});
|
|
776
|
+
sec.appendChild(ilist);
|
|
777
|
+
sec.appendChild(el("p", { class: "ds-note", text: "これらの更新は毎晩の Gold 昇格が読み取ります。" }));
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
if (sources.length) {
|
|
781
|
+
sec.appendChild(el("div", { class: "ds-sub", text: "外部ソース(ライブ参照)" }));
|
|
782
|
+
// ツール(type)別にグループ化し、多いグループ(4件以上)は折りたたむ
|
|
783
|
+
var groups = [];
|
|
784
|
+
var byType = {};
|
|
785
|
+
sources.forEach(function (s) {
|
|
786
|
+
var g = byType[s.type];
|
|
787
|
+
if (!g) { g = { type: s.type, items: [] }; byType[s.type] = g; groups.push(g); }
|
|
788
|
+
g.items.push(s);
|
|
789
|
+
});
|
|
790
|
+
var UNIT = { "slack": "チャンネル", "github-issues": "リポジトリ", "github-discussions": "リポジトリ" };
|
|
791
|
+
var wrap = el("div", { class: "ds-list" });
|
|
792
|
+
groups.forEach(function (g) {
|
|
793
|
+
var meta = DS_TYPE[g.type] || { icon: "🔗", label: g.type || "その他" };
|
|
794
|
+
var cards = el("div", { class: "ds-list" });
|
|
795
|
+
g.items.forEach(function (s) { cards.appendChild(extSourceCard(s, meta)); });
|
|
796
|
+
if (g.items.length >= 4) {
|
|
797
|
+
// 折りたたみ(既定は閉)。summaryに件数と状態の要約を出す
|
|
798
|
+
var bad = 0;
|
|
799
|
+
g.items.forEach(function (s) { if (s.gate !== "ok") bad++; });
|
|
800
|
+
var sum = el("summary", {}, [
|
|
801
|
+
el("span", { text: meta.icon + " " + meta.label + "(" + g.items.length + (UNIT[g.type] || "件") + ")" }),
|
|
802
|
+
bad === 0
|
|
803
|
+
? el("span", { class: "badge ds-sum-ok", text: "接続OK" })
|
|
804
|
+
: el("span", { class: "badge ds-sum-warn", text: "⚠️ " + bad + "件に問題" }),
|
|
805
|
+
]);
|
|
806
|
+
wrap.appendChild(el("details", { class: "ds-group" }, [sum, cards]));
|
|
807
|
+
} else {
|
|
808
|
+
while (cards.firstChild) wrap.appendChild(cards.firstChild);
|
|
809
|
+
}
|
|
730
810
|
});
|
|
731
|
-
sec.appendChild(
|
|
811
|
+
sec.appendChild(wrap);
|
|
732
812
|
}
|
|
733
813
|
|
|
734
814
|
if (pipes.length) {
|
|
@@ -736,7 +816,13 @@ const CLIENT_JS = `
|
|
|
736
816
|
var plist = el("div", { class: "ds-pipes" });
|
|
737
817
|
pipes.forEach(function (p) {
|
|
738
818
|
var t = p.lastSuccess ? dsFmtTime(p.lastSuccess) : "";
|
|
739
|
-
var children = [
|
|
819
|
+
var children = [];
|
|
820
|
+
if (p.lastConclusion === "success") {
|
|
821
|
+
children.push(el("span", { class: "ds-pipe-status", text: "✅", title: "直近の実行は成功しています" }));
|
|
822
|
+
} else if (p.lastConclusion === "failure") {
|
|
823
|
+
children.push(el("span", { class: "ds-pipe-status", text: "❌", title: "直近の実行が失敗しています" }));
|
|
824
|
+
}
|
|
825
|
+
children.push(el("span", { class: "ds-pipe-label", text: p.label || p.id || "" }));
|
|
740
826
|
if (t) children.push(el("span", { class: "ds-pipe-time", text: "最終成功: " + t }));
|
|
741
827
|
plist.appendChild(el("div", { class: "ds-pipe" }, children));
|
|
742
828
|
});
|
|
@@ -745,6 +831,23 @@ const CLIENT_JS = `
|
|
|
745
831
|
|
|
746
832
|
app.appendChild(sec);
|
|
747
833
|
}
|
|
834
|
+
// 外部ソース1件のカード(グループ化表示・展開表示の両方から使う)
|
|
835
|
+
function extSourceCard(s, meta) {
|
|
836
|
+
var badges = el("div", { class: "ds-badges" });
|
|
837
|
+
if (s.gold === true) badges.appendChild(el("span", { class: "badge ds-gold", text: "Gold昇格の読み取り対象" }));
|
|
838
|
+
else if (s.gold === false) badges.appendChild(el("span", { class: "badge ds-excluded", text: "除外" }));
|
|
839
|
+
if (s.notify === true) badges.appendChild(el("span", { class: "badge ds-notify", text: "通知先" }));
|
|
840
|
+
var gate = DS_GATE[s.gate] || DS_GATE["unknown"];
|
|
841
|
+
return el("div", { class: "ds-card" }, [
|
|
842
|
+
el("div", { class: "ds-card-main" }, [
|
|
843
|
+
el("span", { class: "ds-icon", text: meta.icon }),
|
|
844
|
+
el("span", { class: "ds-type", text: meta.label }),
|
|
845
|
+
dsNameEl(s.name || "", s.url),
|
|
846
|
+
]),
|
|
847
|
+
badges,
|
|
848
|
+
el("span", { class: "ds-gate " + gate.cls, text: gate.text }),
|
|
849
|
+
]);
|
|
850
|
+
}
|
|
748
851
|
|
|
749
852
|
// ---------- 操作タブ(Cortex自体への操作。まずは取り込み。今後この受け皿に機能を足す) ----------
|
|
750
853
|
function renderOps() {
|
package/package.json
CHANGED