@takagaki/cortex-decisions-viewer 0.10.5 → 0.10.6
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/render.js +109 -3
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.chatRowsToAdd = chatRowsToAdd;
|
|
|
12
12
|
exports.devRowsToAdd = devRowsToAdd;
|
|
13
13
|
exports.designRowsToAdd = designRowsToAdd;
|
|
14
14
|
exports.materialRowsToAdd = materialRowsToAdd;
|
|
15
|
+
exports.issuesRefOf = issuesRefOf;
|
|
15
16
|
exports.issueRowsToAdd = issueRowsToAdd;
|
|
16
17
|
exports.unsettledRegisteredCount = unsettledRegisteredCount;
|
|
17
18
|
exports.registeredRowsToAdd = registeredRowsToAdd;
|
|
@@ -734,6 +735,25 @@ function materialRowsToAdd(ids, rows) {
|
|
|
734
735
|
}
|
|
735
736
|
return out;
|
|
736
737
|
}
|
|
738
|
+
/**
|
|
739
|
+
* 課題管理(Backlog)の接続先1件を1つの鍵にする。**ドメインは小文字・キーは大文字。**
|
|
740
|
+
*
|
|
741
|
+
* 🔴 **この規則の正本はここ1つ。** 設定ファイルの値は人が書いたもので大小が揃って
|
|
742
|
+
* いないので、揃えずに突き合わせると**同じ接続先を別物と見る**。それが起きる場所が
|
|
743
|
+
* 3つある——行の重複判定(`issueRowsToAdd`)、登録から消えた行の引き算
|
|
744
|
+
* (`subtractRemovedRegistered`)、そして接続状態ストアの行との突き合わせ
|
|
745
|
+
* (画面の `ingestedStateOf`。ストアの `ref` も engine 側がこの規則で書く)。
|
|
746
|
+
*
|
|
747
|
+
* **クロージャを持たないこと**(クライアントへ `.toString()` で流し込む)。
|
|
748
|
+
*
|
|
749
|
+
* ⚠ 画面の `targetsGenerationOf`(サーバへ送る世代)は同じ規則を持つが、この関数を
|
|
750
|
+
* 呼べない——配信物から関数1つを切り出して直接呼ぶテストがあり、外の名前を参照した
|
|
751
|
+
* 瞬間にそのテストが動かなくなる。あちらを直すときはここも直す。
|
|
752
|
+
*/
|
|
753
|
+
function issuesRefOf(domain, projectKey) {
|
|
754
|
+
return String(domain == null ? "" : domain).toLowerCase() + "/" +
|
|
755
|
+
String(projectKey == null ? "" : projectKey).toUpperCase();
|
|
756
|
+
}
|
|
737
757
|
/**
|
|
738
758
|
* 課題管理の行で、まとめ表がまだ知らないもの。
|
|
739
759
|
*
|
|
@@ -742,7 +762,7 @@ function materialRowsToAdd(ids, rows) {
|
|
|
742
762
|
* 二重に並ぶ(片方は削除ボタンを持たない)。
|
|
743
763
|
*/
|
|
744
764
|
function issueRowsToAdd(targets, rows) {
|
|
745
|
-
const key =
|
|
765
|
+
const key = issuesRefOf;
|
|
746
766
|
const have = {};
|
|
747
767
|
for (const t of targets || [])
|
|
748
768
|
if (t && t.domain && t.projectKey)
|
|
@@ -899,7 +919,7 @@ function subtractRemovedRegistered(view, reg) {
|
|
|
899
919
|
if (Array.isArray(reg.issues)) {
|
|
900
920
|
// 鍵の畳み方は足す側(issueRowsToAdd)と同じにする——別の畳み方にすると
|
|
901
921
|
// 大小の違いで「引いた直後に別綴りで足し直される」形になる
|
|
902
|
-
const issueKey = (t) =>
|
|
922
|
+
const issueKey = (t) => issuesRefOf(t.domain, t.projectKey);
|
|
903
923
|
const keys = {};
|
|
904
924
|
for (const r of reg.issues)
|
|
905
925
|
if (r)
|
|
@@ -2051,6 +2071,12 @@ a.ds-name:hover { text-decoration: underline; }
|
|
|
2051
2071
|
.ds-all-connected { color: var(--muted); }
|
|
2052
2072
|
.ds-gate { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 600; flex: 0 0 auto; }
|
|
2053
2073
|
.ds-gate-at { font-size: 11px; color: var(--muted); flex: 0 0 auto; }
|
|
2074
|
+
/* 接続先1件ごとの「取り込み」(段C・2026-08-24)。**「最終同期」(.ds-sync・run単位)とは
|
|
2075
|
+
別の行に並ぶ**ので、同じ強さにしない——run の時刻より弱い添え物として読ませる。
|
|
2076
|
+
失敗だけは .ds-gate-warn と同じ色にする(同じ画面で警告の色が2種類あると、
|
|
2077
|
+
どちらが重いのか読めない) */
|
|
2078
|
+
.ds-ingest { font-size: 11px; color: var(--muted); flex: 0 0 auto; font-variant-numeric: tabular-nums; }
|
|
2079
|
+
.ds-ingest-failed { color: #b45309; font-weight: 600; }
|
|
2054
2080
|
.ds-gate::before { content: ""; width: 8px; height: 8px; border-radius: 999px; background: currentColor; }
|
|
2055
2081
|
.ds-gate-ok { color: #1f7a45; }
|
|
2056
2082
|
.ds-gate-warn { color: #b45309; }
|
|
@@ -2324,6 +2350,7 @@ ${capabilityAdapter.toString()}
|
|
|
2324
2350
|
${capabilityRawState.toString()}
|
|
2325
2351
|
${capabilityDisplayState.toString()}
|
|
2326
2352
|
${backlogTargetOf.toString()}
|
|
2353
|
+
${issuesRefOf.toString()}
|
|
2327
2354
|
${sourceNeedsAttention.toString()}
|
|
2328
2355
|
${capabilityState.toString()}
|
|
2329
2356
|
// 反映待ち(⏳ 反映中)の判定。**期限・間隔・対応表もビルド時の定義から流し込む**
|
|
@@ -5608,6 +5635,7 @@ ${nextStateDelay.toString()}
|
|
|
5608
5635
|
* ——食い違わないことは backlog-targets-ui.test.mjs が実物どうしで突き合わせている。
|
|
5609
5636
|
*
|
|
5610
5637
|
* **クロージャを持たない純関数に保つこと**(テストが配信物から切り出して直接呼ぶ)。
|
|
5638
|
+
* だから issuesRefOf を呼べない(規則の正本はあちら側。直すときは両方直す)。
|
|
5611
5639
|
*/
|
|
5612
5640
|
function targetsGenerationOf(list) {
|
|
5613
5641
|
return (list || [])
|
|
@@ -5710,6 +5738,75 @@ ${nextStateDelay.toString()}
|
|
|
5710
5738
|
return domains.length === 1 ? domains[0] : "";
|
|
5711
5739
|
}
|
|
5712
5740
|
|
|
5741
|
+
/**
|
|
5742
|
+
* その接続先の「取り込み」の行(接続状態ストア・段C)。**無ければ null。**
|
|
5743
|
+
*
|
|
5744
|
+
* 🔴 **overlayStateOnFleet は通らない。** あれは externalSources(チャット / 開発)に
|
|
5745
|
+
* 重ねる仕組みで、**Backlog の行はそこに存在しない**(まとめ表を作る側が作るのは
|
|
5746
|
+
* slack と github 系だけ)。だから接続先の行を描くこちらがストアを直接引く。
|
|
5747
|
+
*
|
|
5748
|
+
* **突き合わせは両側とも issuesRefOf を通す。** 設定ファイルの値は人が書いたもので
|
|
5749
|
+
* 大小が揃っておらず("CM1.Backlog.JP" / "pj_a" が実在する)、素の文字列で比べると
|
|
5750
|
+
* **取り込めているのに何も出ない**——「測っていないものは何も言わない」設計なので、
|
|
5751
|
+
* 突き合わせに失敗しても画面は静かに黙るだけで、誰も気づけない。
|
|
5752
|
+
*/
|
|
5753
|
+
function ingestedStateOf(domain, projectKey) {
|
|
5754
|
+
var rows = LIVE_STATE;
|
|
5755
|
+
if (!rows || !rows.length || !domain || !projectKey) return null;
|
|
5756
|
+
var want = issuesRefOf(domain, projectKey);
|
|
5757
|
+
for (var i = 0; i < rows.length; i++) {
|
|
5758
|
+
var r = rows[i];
|
|
5759
|
+
// cap と question の両方で絞る。片方だけだと、同じ ref を持つ別の問い
|
|
5760
|
+
//(将来 issues に別の question が増えたとき)の行を取り込みとして読む
|
|
5761
|
+
if (!r || r.cap !== "issues" || r.question !== "ingested") continue;
|
|
5762
|
+
var at = String(r.ref || "").indexOf("/");
|
|
5763
|
+
if (at < 0) continue;
|
|
5764
|
+
if (issuesRefOf(String(r.ref).slice(0, at), String(r.ref).slice(at + 1)) === want) return r;
|
|
5765
|
+
}
|
|
5766
|
+
return null;
|
|
5767
|
+
}
|
|
5768
|
+
|
|
5769
|
+
/**
|
|
5770
|
+
* 接続先1件の「取り込み」の表示。**測っていなければ何も出さない(null)。**
|
|
5771
|
+
*
|
|
5772
|
+
* 段A・段Bと同じ原則。行が無いのは「取り込みが動いていない」ではなく
|
|
5773
|
+
* 「まだ誰も書いていない」(engine の版が古い案件・一度も同期していない案件)で、
|
|
5774
|
+
* そこに「未取り込み」と書くと**直す必要があると読ませる嘘**になる。
|
|
5775
|
+
*
|
|
5776
|
+
* **「最終同期」(.ds-sync)を置き換えない。** あちらは run 全体の最終成功時刻で、
|
|
5777
|
+
* どの接続先のことか分からない。こちらは接続先1件の成否。意味が違うので併記する。
|
|
5778
|
+
*/
|
|
5779
|
+
function ingestedEl(r) {
|
|
5780
|
+
if (!r) return null;
|
|
5781
|
+
var when = rtAgo(r.at);
|
|
5782
|
+
var text = "";
|
|
5783
|
+
if (r.status === "ok") text = when ? "取り込み: " + when + "に成功" : "取り込み: 成功";
|
|
5784
|
+
else if (r.status === "failed") text = when ? "取り込み: " + when + "に失敗" : "取り込み: 失敗";
|
|
5785
|
+
else if (r.status === "skipped") text = "取り込み: スキップ";
|
|
5786
|
+
if (!text) return null;
|
|
5787
|
+
return el("span", {
|
|
5788
|
+
class: "ds-ingest" + (r.status === "failed" ? " ds-ingest-failed" : ""),
|
|
5789
|
+
text: text,
|
|
5790
|
+
});
|
|
5791
|
+
}
|
|
5792
|
+
|
|
5793
|
+
/**
|
|
5794
|
+
* いま一覧に出ている接続先の「取り込み」をひとつの文字列にする(差し替えの要否の判定用)。
|
|
5795
|
+
*
|
|
5796
|
+
* 🔴 **接続先の世代(targetsGenerationOf)だけでは足りない。** モーダルを開くと
|
|
5797
|
+
* その能力の状況をもう一度取りに行くので、**応答が返る前に開いた人は取り込みの行を
|
|
5798
|
+
* 1件も持っていない**。届いた応答で接続先の集合が変わっていなければ、世代だけを見る
|
|
5799
|
+
* 早期return が描き直しを飛ばし、**閉じて開き直すまで空のまま**になる。
|
|
5800
|
+
* 空表示は「まだ誰も測っていない」と区別が付かないので、**取り込みの失敗を黙る**という
|
|
5801
|
+
* この機能が殺そうとしている欠陥そのものが、別の経路で復活する。
|
|
5802
|
+
*/
|
|
5803
|
+
function ingestSigOf(list) {
|
|
5804
|
+
return (list || []).map(function (t) {
|
|
5805
|
+
var r = ingestedStateOf(t.domain, t.projectKey);
|
|
5806
|
+
return r ? r.status + "@" + r.at : "-";
|
|
5807
|
+
}).join(",");
|
|
5808
|
+
}
|
|
5809
|
+
|
|
5713
5810
|
/**
|
|
5714
5811
|
* 「課題管理」カードの接続先(一覧+追加+削除・#127)。
|
|
5715
5812
|
*
|
|
@@ -5768,6 +5865,8 @@ ${nextStateDelay.toString()}
|
|
|
5768
5865
|
el("span", { class: "ds-type", text: "Backlog" }),
|
|
5769
5866
|
dsNameEl(t.domain + " / " + t.projectKey, "https://" + t.domain + "/projects/" + t.projectKey),
|
|
5770
5867
|
]),
|
|
5868
|
+
// この接続先の取り込みが最後にどうなったか(段C)。測っていなければ null
|
|
5869
|
+
ingestedEl(ingestedStateOf(t.domain, t.projectKey)),
|
|
5771
5870
|
]);
|
|
5772
5871
|
if (!editable) return row;
|
|
5773
5872
|
var btn = el("button", { class: "ds-toggle-btn ds-danger", type: "button", text: "この接続先を外す" });
|
|
@@ -5912,6 +6011,8 @@ ${nextStateDelay.toString()}
|
|
|
5912
6011
|
// 箱が無いと最初の描画で「未設定」の行が出ない
|
|
5913
6012
|
var box = el("div", { "data-live-cap": REGISTERED_CAP_NAMES.issues }, [listEl]);
|
|
5914
6013
|
paint();
|
|
6014
|
+
/** いま描いてある取り込みの状態(段C)。接続先の集合とは別に変わるので、別に覚える */
|
|
6015
|
+
var lastIngestSig = ingestSigOf(targets);
|
|
5915
6016
|
/**
|
|
5916
6017
|
* 取り直しで新しい値が届いたときの差し替え(段階1)。**一覧だけを描き直す。**
|
|
5917
6018
|
*
|
|
@@ -5923,8 +6024,13 @@ ${nextStateDelay.toString()}
|
|
|
5923
6024
|
// 🔴 応答に添えられた一覧(adoptTargets)のほうが新しい。上書きしない
|
|
5924
6025
|
if (adopted) return;
|
|
5925
6026
|
var next = backlogTargetsNow(internalSourceOf(REGISTERED_CAP_NAMES.issues));
|
|
5926
|
-
|
|
6027
|
+
// 🔴 **変化が無いと言えるのは、接続先の集合と取り込みの状態が両方同じときだけ(段C)。**
|
|
6028
|
+
// 世代だけで判断すると、**応答を待たずにモーダルを開いた人には取り込みが永久に出ない**
|
|
6029
|
+
//(届いた応答で集合は変わらないので、ここで飛ばされる)。ingestSigOf の項に経緯
|
|
6030
|
+
var sig = ingestSigOf(next);
|
|
6031
|
+
if (targetsGenerationOf(next) === targetsGenerationOf(targets) && sig === lastIngestSig) return;
|
|
5927
6032
|
targets = next;
|
|
6033
|
+
lastIngestSig = sig;
|
|
5928
6034
|
paint();
|
|
5929
6035
|
};
|
|
5930
6036
|
// 接続先がまだ無い案件の受け皿は、0件の1行の直後に置く(行が無いので中へ入れられない)
|
package/package.json
CHANGED