@takagaki/cortex-decisions-viewer 0.4.23 → 0.4.25
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 +14 -1
- package/dist/render.js +218 -19
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -149,6 +149,7 @@ async function readFleetSources(repoRoot) {
|
|
|
149
149
|
? s.matchKeys.map((k) => String(k)).filter(Boolean)
|
|
150
150
|
: undefined,
|
|
151
151
|
driveSync: typeof s.driveSync === "boolean" ? s.driveSync : undefined,
|
|
152
|
+
enabled: typeof s.enabled === "boolean" ? s.enabled : undefined,
|
|
152
153
|
}))
|
|
153
154
|
: undefined;
|
|
154
155
|
const pipelines = Array.isArray(obj.pipelines)
|
|
@@ -163,7 +164,18 @@ async function readFleetSources(repoRoot) {
|
|
|
163
164
|
applicable: typeof p.applicable === "boolean" ? p.applicable : undefined,
|
|
164
165
|
}))
|
|
165
166
|
: undefined;
|
|
166
|
-
|
|
167
|
+
// 能力→ツールの宣言マップ(例: { チャット: "slack", 開発: "none" })。"none" は未使用のグレー行表示に使う
|
|
168
|
+
let tools;
|
|
169
|
+
if (obj.tools != null && typeof obj.tools === "object" && !Array.isArray(obj.tools)) {
|
|
170
|
+
tools = {};
|
|
171
|
+
for (const [k, v] of Object.entries(obj.tools)) {
|
|
172
|
+
if (typeof v === "string")
|
|
173
|
+
tools[k] = v;
|
|
174
|
+
}
|
|
175
|
+
if (!Object.keys(tools).length)
|
|
176
|
+
tools = undefined;
|
|
177
|
+
}
|
|
178
|
+
return { externalSources, internalSources, pipelines, tools };
|
|
167
179
|
}
|
|
168
180
|
/** ディレクトリ内の .md を汎用レコードとして読み込む(存在しなければ空配列) */
|
|
169
181
|
async function loadGenericRecords(dirAbs, exclude, repoBaseUrl, branch) {
|
|
@@ -948,6 +960,7 @@ async function build(opts) {
|
|
|
948
960
|
externalSources: fleet.externalSources,
|
|
949
961
|
internalSources: fleet.internalSources,
|
|
950
962
|
pipelines: fleet.pipelines,
|
|
963
|
+
tools: fleet.tools,
|
|
951
964
|
};
|
|
952
965
|
// サムネイル(デザイン画面等)をサイトに同梱し、ノードのパスをサイト内相対に書き換える
|
|
953
966
|
await node_fs_1.promises.mkdir(outAbs, { recursive: true });
|
package/dist/render.js
CHANGED
|
@@ -17,6 +17,8 @@ function renderSite(site) {
|
|
|
17
17
|
// ※ 投入フォーム設定 site.intake は build.ts が --intake-url/--intake-token/--project-key から付与する。
|
|
18
18
|
const dataJson = JSON.stringify(site).replace(/</g, "\\u003c");
|
|
19
19
|
const safeTitle = escapeHtml(site.title);
|
|
20
|
+
// 接続マップ(操作タブ最上部のSVG図)。ビルド時に生成し<template>で埋め込む。fleet情報が無ければ出さない
|
|
21
|
+
const connMap = renderConnectionMap(site);
|
|
20
22
|
const githubBtn = site.repoBaseUrl
|
|
21
23
|
? `<a class="gh-btn" href="${escapeHtml(site.repoBaseUrl)}" target="_blank" rel="noopener" title="コンテキストリポジトリをGitHubで開く">${GITHUB_ICON}</a>`
|
|
22
24
|
: "";
|
|
@@ -45,7 +47,7 @@ function renderSite(site) {
|
|
|
45
47
|
<footer class="site-footer">
|
|
46
48
|
<span id="footer-meta"></span>
|
|
47
49
|
</footer>
|
|
48
|
-
<script type="application/json" id="site-data">${dataJson}</script>
|
|
50
|
+
${connMap ? `<template id="conn-map">${connMap}</template>\n` : ""}<script type="application/json" id="site-data">${dataJson}</script>
|
|
49
51
|
<script>${CLIENT_JS}</script>
|
|
50
52
|
</body>
|
|
51
53
|
</html>`;
|
|
@@ -58,6 +60,106 @@ function escapeHtml(s) {
|
|
|
58
60
|
.replace(/>/g, ">")
|
|
59
61
|
.replace(/"/g, """);
|
|
60
62
|
}
|
|
63
|
+
/** 接続マップの能力定義(表示順・絵文字は詳細カードの流儀を踏襲) */
|
|
64
|
+
const CM_CAPS = [
|
|
65
|
+
{ cap: "課題管理", icon: "📋", pipe: /sync-backlog/ },
|
|
66
|
+
{ cap: "会議", icon: "🎙", pipe: /ingest-minutes/ },
|
|
67
|
+
{ cap: "共有資料", icon: "📁", pipe: /sync-materials/ },
|
|
68
|
+
{ cap: "デザイン", icon: "🎨", pipe: /sync-designs|update-design-notes/ },
|
|
69
|
+
{ cap: "チャット", icon: "💬", pipe: null },
|
|
70
|
+
{ cap: "開発", icon: "🐙", pipe: null },
|
|
71
|
+
];
|
|
72
|
+
/** ツールid→表示名(接続マップのノードラベル用) */
|
|
73
|
+
const CM_TOOL_LABEL = {
|
|
74
|
+
backlog: "Backlog",
|
|
75
|
+
jira: "Jira",
|
|
76
|
+
"google-meet": "Google Meet",
|
|
77
|
+
teams: "Teams",
|
|
78
|
+
"google-drive": "Google Drive",
|
|
79
|
+
box: "Box",
|
|
80
|
+
local: "ローカル",
|
|
81
|
+
figma: "Figma",
|
|
82
|
+
slack: "Slack",
|
|
83
|
+
github: "GitHub",
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* 接続マップ(データソースとの接続を視覚化したSVG)をビルド時に生成する。
|
|
87
|
+
* 上段に6アダプター(能力)ノード、下中央にリポジトリノード、間をベジェの破線で結ぶ。
|
|
88
|
+
* 状態: 健全=色付き+流れるアニメーション / 問題あり=黄+⚠️ / 未使用=グレー。
|
|
89
|
+
* fleet-status由来の情報が何も無ければ null(マップを出さない・後方互換)。
|
|
90
|
+
*/
|
|
91
|
+
function renderConnectionMap(site) {
|
|
92
|
+
const internals = site.internalSources ?? [];
|
|
93
|
+
const externals = site.externalSources ?? [];
|
|
94
|
+
const pipes = site.pipelines ?? [];
|
|
95
|
+
const tools = site.tools ?? {};
|
|
96
|
+
if (!internals.length && !externals.length && !pipes.length && !Object.keys(tools).length) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const slackExts = externals.filter((s) => s.type === "slack");
|
|
100
|
+
const ghExts = externals.filter((s) => s.type.startsWith("github"));
|
|
101
|
+
const nodes = [];
|
|
102
|
+
const links = [];
|
|
103
|
+
const W = 960;
|
|
104
|
+
const REPO_X = W / 2;
|
|
105
|
+
CM_CAPS.forEach((c, i) => {
|
|
106
|
+
const cx = 80 + i * 160;
|
|
107
|
+
const toolVal = tools[c.cap];
|
|
108
|
+
const internal = internals.find((s) => s.kind === c.cap);
|
|
109
|
+
const isLive = c.cap === "チャット" || c.cap === "開発";
|
|
110
|
+
const liveExts = c.cap === "チャット" ? slackExts : c.cap === "開発" ? ghExts : [];
|
|
111
|
+
// 使用中か: tools宣言がnone以外 / internalSourceが存在(enabled:false除く) / ライブ参照の実体がある
|
|
112
|
+
const used = (toolVal != null && toolVal !== "none") ||
|
|
113
|
+
(internal != null && internal.enabled !== false) ||
|
|
114
|
+
(isLive && liveExts.length > 0);
|
|
115
|
+
const off = toolVal === "none" || internal?.enabled === false || !used;
|
|
116
|
+
// 問題あり: ライブ参照はgate≠okが1件以上、同期ソースは対応パイプラインの直近runがfailure
|
|
117
|
+
const warn = !off &&
|
|
118
|
+
(isLive
|
|
119
|
+
? liveExts.some((s) => s.gate !== "ok")
|
|
120
|
+
: pipes.some((p) => c.pipe != null && c.pipe.test(p.id) && p.applicable !== false && p.lastConclusion === "failure"));
|
|
121
|
+
const state = off ? "cm-off" : warn ? "cm-warn" : "cm-ok";
|
|
122
|
+
const toolName = toolVal && toolVal !== "none"
|
|
123
|
+
? CM_TOOL_LABEL[toolVal] ?? toolVal
|
|
124
|
+
: internal
|
|
125
|
+
? CM_TOOL_LABEL[internal.tool] ?? internal.tool
|
|
126
|
+
: isLive && liveExts.length
|
|
127
|
+
? CM_TOOL_LABEL[c.cap === "チャット" ? "slack" : "github"]
|
|
128
|
+
: c.cap;
|
|
129
|
+
const label = `${c.icon} ${off && (toolVal === "none" || !toolName) ? c.cap : toolName}`;
|
|
130
|
+
// ノード下の補足: 未使用 / ライブ参照 / 最終同期(時刻はクライアントでローカルタイム整形するため data-ts で渡す)
|
|
131
|
+
let sub = "";
|
|
132
|
+
if (off) {
|
|
133
|
+
sub = `<text class="cm-sync" x="${cx}" y="60" text-anchor="middle">未使用</text>`;
|
|
134
|
+
}
|
|
135
|
+
else if (isLive) {
|
|
136
|
+
sub = `<text class="cm-sync" x="${cx}" y="60" text-anchor="middle">ライブ参照</text>`;
|
|
137
|
+
}
|
|
138
|
+
else if (internal?.lastSync) {
|
|
139
|
+
sub = `<text class="cm-sync" x="${cx}" y="60" text-anchor="middle" data-ts="${escapeHtml(internal.lastSync)}"></text>`;
|
|
140
|
+
}
|
|
141
|
+
const badge = warn ? `<text class="cm-badge" x="${cx + 62}" y="26" text-anchor="middle">⚠️</text>` : "";
|
|
142
|
+
// クリックでページ内の該当詳細カード(アンカー)へスクロールする
|
|
143
|
+
const anchor = `ds-${c.cap}`;
|
|
144
|
+
nodes.push(`<g class="cm-node ${state}" data-target="${anchor}" tabindex="0" role="link" aria-label="${escapeHtml(c.cap)}の詳細へ">` +
|
|
145
|
+
`<rect x="${cx - 74}" y="16" width="148" height="54" rx="10"></rect>` +
|
|
146
|
+
`<text class="cm-label" x="${cx}" y="40" text-anchor="middle">${escapeHtml(label)}</text>` +
|
|
147
|
+
sub +
|
|
148
|
+
badge +
|
|
149
|
+
`</g>`);
|
|
150
|
+
links.push(`<path class="cm-link ${state}" d="M ${cx} 72 C ${cx} 150, ${REPO_X} 160, ${REPO_X} 238"></path>`);
|
|
151
|
+
});
|
|
152
|
+
const repoTitle = site.title.length > 24 ? site.title.slice(0, 23) + "…" : site.title;
|
|
153
|
+
const repo = `<g class="cm-repo">` +
|
|
154
|
+
`<rect x="${REPO_X - 170}" y="240" width="340" height="52" rx="12"></rect>` +
|
|
155
|
+
`<text class="cm-repo-label" x="${REPO_X}" y="272" text-anchor="middle">📦 コンテキストリポジトリ(${escapeHtml(repoTitle)})</text>` +
|
|
156
|
+
`</g>`;
|
|
157
|
+
return (`<svg class="cm-svg" viewBox="0 0 ${W} 312" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="データソースとの接続マップ">` +
|
|
158
|
+
links.join("") +
|
|
159
|
+
nodes.join("") +
|
|
160
|
+
repo +
|
|
161
|
+
`</svg>`);
|
|
162
|
+
}
|
|
61
163
|
const CSS = `
|
|
62
164
|
:root {
|
|
63
165
|
--bg: #f6f7f9;
|
|
@@ -360,6 +462,35 @@ a.ds-name:hover { text-decoration: underline; }
|
|
|
360
462
|
.ds-group > .ds-list { margin-top: 8px; padding-left: 12px; border-left: 2px solid var(--border); }
|
|
361
463
|
.badge.ds-sum-ok { background: #e9f7ef; color: #1f7a45; }
|
|
362
464
|
.badge.ds-sum-warn { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
|
|
465
|
+
/* ---- 接続マップ(操作タブ最上部のSVG図) ---- */
|
|
466
|
+
.conn-map { overflow-x: auto; margin: 4px 0 20px; }
|
|
467
|
+
.conn-map .cm-svg { display: block; min-width: 760px; width: 100%; height: auto; font-family: inherit; }
|
|
468
|
+
.cm-node { cursor: pointer; outline: none; }
|
|
469
|
+
.cm-node rect { fill: var(--surface); stroke: var(--border); stroke-width: 1.5; }
|
|
470
|
+
.cm-node:hover rect, .cm-node:focus rect { stroke: var(--accent); }
|
|
471
|
+
.cm-node.cm-ok rect { stroke: var(--accent); }
|
|
472
|
+
.cm-node.cm-warn rect { fill: #fffbeb; stroke: #fcd34d; }
|
|
473
|
+
.cm-node.cm-off rect { fill: #f8f9fa; stroke: #d1d5db; stroke-dasharray: 4 3; }
|
|
474
|
+
.cm-label { font-size: 13.5px; font-weight: 600; fill: var(--text); }
|
|
475
|
+
.cm-node.cm-warn .cm-label { fill: #92400e; }
|
|
476
|
+
.cm-node.cm-off .cm-label { fill: #9ca3af; }
|
|
477
|
+
.cm-node.cm-off text { filter: grayscale(1); opacity: .8; }
|
|
478
|
+
.cm-sync { font-size: 10.5px; fill: var(--muted); font-variant-numeric: tabular-nums; }
|
|
479
|
+
.cm-node.cm-off .cm-sync { fill: #9ca3af; }
|
|
480
|
+
.cm-badge { font-size: 13px; }
|
|
481
|
+
.cm-link { fill: none; stroke-width: 1.6; stroke-dasharray: 6 6; stroke: #94a3b8; }
|
|
482
|
+
.cm-link.cm-ok { stroke: var(--accent); animation: cm-flow 1.1s linear infinite; }
|
|
483
|
+
.cm-link.cm-warn { stroke: #d97706; }
|
|
484
|
+
.cm-link.cm-off { stroke: #d1d5db; opacity: .6; }
|
|
485
|
+
@keyframes cm-flow { to { stroke-dashoffset: -24; } }
|
|
486
|
+
@media (prefers-reduced-motion: reduce) { .cm-link.cm-ok { animation: none; } }
|
|
487
|
+
.cm-repo rect { fill: var(--accent-weak); stroke: var(--accent); stroke-width: 1.5; }
|
|
488
|
+
.cm-repo-label { font-size: 14px; font-weight: 700; fill: #1e3a8a; }
|
|
489
|
+
/* 未使用(非活性)行: アダプターとして存在するが、この案件では設定されていないもの */
|
|
490
|
+
.ds-card.ds-inactive, .ds-pipe.ds-inactive { background: #f8f9fa; border-style: dashed; box-shadow: none; }
|
|
491
|
+
.ds-inactive .ds-icon { filter: grayscale(1); opacity: .55; }
|
|
492
|
+
.ds-inactive .ds-type, .ds-inactive .ds-name, .ds-inactive a.ds-name, .ds-inactive .ds-pipe-label { color: #9ca3af; }
|
|
493
|
+
.ds-inactive-note { font-size: 12px; color: #9ca3af; line-height: 1.6; flex: 0 0 auto; }
|
|
363
494
|
.ds-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; flex: 0 0 auto; }
|
|
364
495
|
.badge.ds-gold { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
|
|
365
496
|
.badge.ds-excluded { background: #eceef1; color: #6b7280; }
|
|
@@ -511,8 +642,11 @@ const CLIENT_JS = `
|
|
|
511
642
|
if (SITE.graph && SITE.graph.nodes.length > 0) {
|
|
512
643
|
TABS.push({ key: "graph", label: "ナレッジグラフ" });
|
|
513
644
|
}
|
|
514
|
-
// Cortex
|
|
515
|
-
|
|
645
|
+
// Cortex自体を操作するアクションと、接続・自動化の情報の受け皿(取り込み・接続マップ・データソース)。
|
|
646
|
+
// 投入フォーム設定 or fleet-status由来の接続情報のどちらかがあれば出す。
|
|
647
|
+
var HAS_FLEET = !!((SITE.internalSources || []).length || (SITE.externalSources || []).length ||
|
|
648
|
+
(SITE.pipelines || []).length || SITE.tools);
|
|
649
|
+
if (SITE.intake || HAS_FLEET) {
|
|
516
650
|
TABS.push({ key: "ops", label: "操作" });
|
|
517
651
|
}
|
|
518
652
|
|
|
@@ -695,7 +829,6 @@ const CLIENT_JS = `
|
|
|
695
829
|
var homeBody = el("div", { class: "body" });
|
|
696
830
|
app.appendChild(homeBody);
|
|
697
831
|
loadBody(h, homeBody);
|
|
698
|
-
renderDataSources();
|
|
699
832
|
}
|
|
700
833
|
|
|
701
834
|
// ---------- データソースと自動化(fleet-status.json 由来。無ければ非表示) ----------
|
|
@@ -735,10 +868,12 @@ const CLIENT_JS = `
|
|
|
735
868
|
function renderDataSources() {
|
|
736
869
|
var internals = SITE.internalSources || [];
|
|
737
870
|
var sources = SITE.externalSources || [];
|
|
738
|
-
|
|
739
|
-
//
|
|
740
|
-
var
|
|
741
|
-
|
|
871
|
+
var pipes = SITE.pipelines || [];
|
|
872
|
+
// 能力→ツールの宣言(例: チャット: "none")。"none" の能力は「未使用」のグレー行で存在だけ見せる
|
|
873
|
+
var tools = SITE.tools || {};
|
|
874
|
+
var chatOff = tools["チャット"] === "none";
|
|
875
|
+
var devOff = tools["開発"] === "none";
|
|
876
|
+
if (!internals.length && !sources.length && !pipes.length && !chatOff && !devOff) return; // すべて無ければセクションごと出さない
|
|
742
877
|
|
|
743
878
|
var sec = el("section", { class: "datasources" });
|
|
744
879
|
sec.appendChild(el("h2", { class: "datasources-head", text: "データソースと自動化" }));
|
|
@@ -763,13 +898,19 @@ const CLIENT_JS = `
|
|
|
763
898
|
if (s.driveSync === false) {
|
|
764
899
|
col.appendChild(el("span", { class: "ds-drive-note", text: "Drive自動同期は未設定(手動で置いたファイルの変換のみ)" }));
|
|
765
900
|
}
|
|
766
|
-
|
|
901
|
+
// 未使用(enabled: false)はグレー行。アダプターの存在は見せつつ、この案件では設定されていないことを示す
|
|
902
|
+
var inactive = s.enabled === false;
|
|
903
|
+
if (inactive) {
|
|
904
|
+
col.appendChild(el("span", { class: "ds-inactive-note", text: "未使用(この案件では設定されていません)" }));
|
|
905
|
+
}
|
|
906
|
+
// id は接続マップのノードclickの飛び先(アンカー)
|
|
907
|
+
var card = el("div", { class: "ds-card" + (inactive ? " ds-inactive" : ""), id: "ds-" + (s.kind || "") }, [
|
|
767
908
|
el("div", { class: "ds-card-main" }, [
|
|
768
909
|
el("span", { class: "ds-icon", text: DS_KIND_ICON[s.kind] || "📁" }),
|
|
769
910
|
el("span", { class: "ds-type", text: s.kind || "" }),
|
|
770
911
|
col,
|
|
771
912
|
]),
|
|
772
|
-
s.lastSync && dsFmtTime(s.lastSync)
|
|
913
|
+
!inactive && s.lastSync && dsFmtTime(s.lastSync)
|
|
773
914
|
? el("span", { class: "ds-sync", text: "最終同期: " + dsFmtTime(s.lastSync) })
|
|
774
915
|
: null,
|
|
775
916
|
]);
|
|
@@ -779,7 +920,7 @@ const CLIENT_JS = `
|
|
|
779
920
|
sec.appendChild(el("p", { class: "ds-note", text: "これらの更新は毎晩の Gold 昇格が読み取ります。" }));
|
|
780
921
|
}
|
|
781
922
|
|
|
782
|
-
if (sources.length) {
|
|
923
|
+
if (sources.length || chatOff || devOff) {
|
|
783
924
|
sec.appendChild(el("div", { class: "ds-sub", text: "外部ソース(ライブ参照)" }));
|
|
784
925
|
// ツール(type)別にグループ化し、多いグループ(4件以上)は折りたたむ
|
|
785
926
|
var groups = [];
|
|
@@ -791,8 +932,16 @@ const CLIENT_JS = `
|
|
|
791
932
|
});
|
|
792
933
|
var UNIT = { "slack": "チャンネル", "github-issues": "リポジトリ", "github-discussions": "リポジトリ" };
|
|
793
934
|
var wrap = el("div", { class: "ds-list" });
|
|
935
|
+
// チャット未使用: Slackグループの位置(先頭)に「存在するが未設定」のグレー行を出す
|
|
936
|
+
if (chatOff) wrap.appendChild(inactiveSourceRow("💬", "チャット", "ds-チャット"));
|
|
937
|
+
var chatAnchored = chatOff;
|
|
938
|
+
var devAnchored = devOff;
|
|
794
939
|
groups.forEach(function (g) {
|
|
795
940
|
var meta = DS_TYPE[g.type] || { icon: "🔗", label: g.type || "その他" };
|
|
941
|
+
// 接続マップのノードclickの飛び先(アンカー)。チャット=Slack群の先頭・開発=GitHub群の先頭
|
|
942
|
+
var anchorId = null;
|
|
943
|
+
if (g.type === "slack" && !chatAnchored) { anchorId = "ds-チャット"; chatAnchored = true; }
|
|
944
|
+
if (g.type.indexOf("github") === 0 && !devAnchored) { anchorId = "ds-開発"; devAnchored = true; }
|
|
796
945
|
var cards = el("div", { class: "ds-list" });
|
|
797
946
|
g.items.forEach(function (s) { cards.appendChild(extSourceCard(s, meta)); });
|
|
798
947
|
if (g.items.length >= 4) {
|
|
@@ -805,11 +954,16 @@ const CLIENT_JS = `
|
|
|
805
954
|
? el("span", { class: "badge ds-sum-ok", text: "接続OK" })
|
|
806
955
|
: el("span", { class: "badge ds-sum-warn", text: "⚠️ " + bad + "件に問題" }),
|
|
807
956
|
]);
|
|
808
|
-
|
|
957
|
+
var det = el("details", { class: "ds-group" }, [sum, cards]);
|
|
958
|
+
if (anchorId) det.id = anchorId;
|
|
959
|
+
wrap.appendChild(det);
|
|
809
960
|
} else {
|
|
961
|
+
if (anchorId && cards.firstChild) cards.firstChild.id = anchorId;
|
|
810
962
|
while (cards.firstChild) wrap.appendChild(cards.firstChild);
|
|
811
963
|
}
|
|
812
964
|
});
|
|
965
|
+
// 開発未使用: GitHubグループの位置(末尾)にグレー行を出す
|
|
966
|
+
if (devOff) wrap.appendChild(inactiveSourceRow("🐙", "GitHub", "ds-開発"));
|
|
813
967
|
sec.appendChild(wrap);
|
|
814
968
|
}
|
|
815
969
|
|
|
@@ -817,6 +971,15 @@ const CLIENT_JS = `
|
|
|
817
971
|
sec.appendChild(el("div", { class: "ds-sub", text: "自動化パイプライン" }));
|
|
818
972
|
var plist = el("div", { class: "ds-pipes" });
|
|
819
973
|
pipes.forEach(function (p) {
|
|
974
|
+
// tools宣言上この案件の対象外(applicable: false)はグレー行。✅❌や最終成功は出さない
|
|
975
|
+
// (スキップ正常終了のrunが成功表示に見えるため)。存在自体は見せる
|
|
976
|
+
if (p.applicable === false) {
|
|
977
|
+
plist.appendChild(el("div", { class: "ds-pipe ds-inactive" }, [
|
|
978
|
+
el("span", { class: "ds-pipe-label", text: p.label || p.id || "" }),
|
|
979
|
+
el("span", { class: "ds-inactive-note", text: "未使用" }),
|
|
980
|
+
]));
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
820
983
|
var t = p.lastSuccess ? dsFmtTime(p.lastSuccess) : "";
|
|
821
984
|
var children = [];
|
|
822
985
|
if (p.lastConclusion === "success") {
|
|
@@ -833,6 +996,17 @@ const CLIENT_JS = `
|
|
|
833
996
|
|
|
834
997
|
app.appendChild(sec);
|
|
835
998
|
}
|
|
999
|
+
// 未使用能力のプレースホルダ行(アダプターとして存在するが、この案件では設定されていないもの)
|
|
1000
|
+
function inactiveSourceRow(icon, typeLabel, anchorId) {
|
|
1001
|
+
return el("div", { class: "ds-card ds-inactive", id: anchorId }, [
|
|
1002
|
+
el("div", { class: "ds-card-main" }, [
|
|
1003
|
+
el("span", { class: "ds-icon", text: icon }),
|
|
1004
|
+
el("span", { class: "ds-type", text: typeLabel }),
|
|
1005
|
+
el("span", { class: "ds-name", text: "未使用" }),
|
|
1006
|
+
]),
|
|
1007
|
+
el("span", { class: "ds-inactive-note", text: "この案件では設定されていません" }),
|
|
1008
|
+
]);
|
|
1009
|
+
}
|
|
836
1010
|
// 外部ソース1件のカード(グループ化表示・展開表示の両方から使う)
|
|
837
1011
|
function extSourceCard(s, meta) {
|
|
838
1012
|
var badges = el("div", { class: "ds-badges" });
|
|
@@ -851,14 +1025,39 @@ const CLIENT_JS = `
|
|
|
851
1025
|
]);
|
|
852
1026
|
}
|
|
853
1027
|
|
|
854
|
-
// ----------
|
|
1028
|
+
// ---------- 操作タブ(接続マップ・データソースと自動化・取り込み。今後この受け皿に機能を足す) ----------
|
|
855
1029
|
function renderOps() {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
1030
|
+
renderConnMap();
|
|
1031
|
+
renderDataSources();
|
|
1032
|
+
if (SITE.intake) {
|
|
1033
|
+
app.appendChild(el("p", { class: "ops-intro", text: "Cortex にコンテキストを取り込む操作です。ファイルを選ぶかテキストを貼って送信すると、自動で取り込まれます(数分で反映)。" }));
|
|
1034
|
+
app.appendChild(el("div", { class: "section-label", text: "取り込み" }));
|
|
1035
|
+
var grid = el("div", { class: "ops-grid" });
|
|
1036
|
+
grid.appendChild(opsCard("🗒️", "会議の文字起こしを追加", "顧客主催の会議など、自動取り込みできない会議の文字起こしファイル(.txt / .docx 等)から議事録を生成します。", "transcript", "文字起こしを追加"));
|
|
1037
|
+
grid.appendChild(opsCard("📎", "共有資料を追加", "提案書・仕様書・議事メモなどの資料を Markdown 化して 共有資料 に取り込みます。", "material", "資料を追加"));
|
|
1038
|
+
app.appendChild(grid);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// ---------- 接続マップ(ビルド時生成のSVGを<template>から取り出して表示) ----------
|
|
1043
|
+
function renderConnMap() {
|
|
1044
|
+
var tpl = document.getElementById("conn-map");
|
|
1045
|
+
if (!tpl) return; // fleet情報が無い(旧fleet-status等)→ マップなし
|
|
1046
|
+
var wrap = el("div", { class: "conn-map" });
|
|
1047
|
+
wrap.appendChild(tpl.content.cloneNode(true));
|
|
1048
|
+
// 最終同期の時刻はブラウザのローカルタイムで整形(詳細カードの表示と揃える)
|
|
1049
|
+
wrap.querySelectorAll("[data-ts]").forEach(function (t) {
|
|
1050
|
+
var s = dsFmtTime(t.getAttribute("data-ts"));
|
|
1051
|
+
if (s) t.textContent = "最終同期 " + s;
|
|
1052
|
+
});
|
|
1053
|
+
// ノードclickで、下の該当詳細カード(アンカー)へスクロール
|
|
1054
|
+
wrap.addEventListener("click", function (ev) {
|
|
1055
|
+
var g = ev.target && ev.target.closest ? ev.target.closest("[data-target]") : null;
|
|
1056
|
+
if (!g) return;
|
|
1057
|
+
var target = document.getElementById(g.getAttribute("data-target"));
|
|
1058
|
+
if (target && target.scrollIntoView) target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1059
|
+
});
|
|
1060
|
+
app.appendChild(wrap);
|
|
862
1061
|
}
|
|
863
1062
|
function opsCard(icon, title, desc, kind, btnLabel) {
|
|
864
1063
|
var btn = el("button", { class: "ops-card-btn", text: "+ " + btnLabel });
|
package/package.json
CHANGED