@takagaki/cortex-decisions-viewer 0.12.56 → 0.12.57
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/pending-ops.js +32 -7
- package/dist/render.js +96 -15
- package/package.json +1 -1
package/dist/pending-ops.js
CHANGED
|
@@ -202,9 +202,17 @@ function backlogTargetOf(input) {
|
|
|
202
202
|
function pendingIsSlackTeamId(v) {
|
|
203
203
|
return /^[TE][A-Z0-9]{6,20}$/.test(String(v == null ? "" : v));
|
|
204
204
|
}
|
|
205
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* Backlog の接続先の鍵(render.ts の issuesRefOf と同形: ドメイン小文字 / キー大文字)。
|
|
207
|
+
*
|
|
208
|
+
* 🔴 **規則の正本は `infra/lambda/shared/connection-state-keys.mjs` の `issuesRefOf`**(#556)。
|
|
209
|
+
* ここも render.ts も**写し**で、ずれると仮置きの札が実測の行に重ならない
|
|
210
|
+
* (押した直後の札が消えないまま、別の行に本物が出る)。
|
|
211
|
+
* ずれを捕まえる網は `viewer/test/state-ref-parity.test.mjs`。
|
|
212
|
+
*/
|
|
206
213
|
function pendingIssuesRef(domain, projectKey) {
|
|
207
|
-
return String(domain == null ? "" : domain).toLowerCase() + "/" +
|
|
214
|
+
return String(domain == null ? "" : domain).trim().toLowerCase() + "/" +
|
|
215
|
+
String(projectKey == null ? "" : projectKey).trim().toUpperCase();
|
|
208
216
|
}
|
|
209
217
|
// ---- エントリを作る(op → kind / action / targetId の対応表はここ 1 つ) ------------
|
|
210
218
|
/**
|
|
@@ -277,8 +285,13 @@ function pendingOpOf(payload, ctx) {
|
|
|
277
285
|
const name = pendingLabel(payload.name);
|
|
278
286
|
return name ? make("slack", "update", payload.ref, { name: name }) : null;
|
|
279
287
|
}
|
|
280
|
-
case "set-notify":
|
|
281
|
-
|
|
288
|
+
case "set-notify": {
|
|
289
|
+
if (typeof payload.value !== "boolean")
|
|
290
|
+
return null;
|
|
291
|
+
// op は 1 つ。ref の形(spaces/…)で Google Chat と決める(サーバの notifyRefKind と同じ・#572)
|
|
292
|
+
const kind = pendingIsSpaceRef(payload.ref) ? "google-chat" : "slack";
|
|
293
|
+
return make(kind, "update", payload.ref, { notify: payload.value });
|
|
294
|
+
}
|
|
282
295
|
case "add-google-chat-space": {
|
|
283
296
|
const ref = pendingGoogleChatSpaceRef(payload.url);
|
|
284
297
|
// 名前は画面に欄が無い(サーバが引く)。live が来るまでは ref で出す
|
|
@@ -660,6 +673,9 @@ function pendingExternalRow(e) {
|
|
|
660
673
|
row.type = "google-chat";
|
|
661
674
|
row.name = p.name || e.targetId;
|
|
662
675
|
row.ref = e.targetId;
|
|
676
|
+
// add に畳まれた update(通知先 ON)を落とさない(#572・Slack と同じ)
|
|
677
|
+
if (p.notify === true)
|
|
678
|
+
row.notify = true;
|
|
663
679
|
}
|
|
664
680
|
else {
|
|
665
681
|
row.type = p.type || "github-issues";
|
|
@@ -734,14 +750,23 @@ function applyPendingOps(view, list) {
|
|
|
734
750
|
extChanged = true;
|
|
735
751
|
}
|
|
736
752
|
else if (e.action === "add") {
|
|
737
|
-
if (idx >= 0)
|
|
753
|
+
if (idx >= 0) {
|
|
754
|
+
// 本物の行が先に来ている。**add に畳まれた update(通知先の向き)だけは当てる**
|
|
755
|
+
// (#572)——畳んだまま捨てると、追加 → 5 分以内に本物の行 → 通知先 ON の順で
|
|
756
|
+
// 押した人の札が、据え置きの live で戻る
|
|
757
|
+
if (typeof p.notify === "boolean" && (externals[idx].notify === true) !== p.notify) {
|
|
758
|
+
externals[idx] = Object.assign({}, externals[idx], { notify: p.notify });
|
|
759
|
+
extChanged = true;
|
|
760
|
+
}
|
|
738
761
|
continue;
|
|
762
|
+
}
|
|
739
763
|
externals.push(pendingExternalRow(e));
|
|
740
764
|
extChanged = true;
|
|
741
765
|
}
|
|
742
|
-
else if (e.kind === "slack" && idx >= 0) {
|
|
766
|
+
else if ((e.kind === "slack" || e.kind === "google-chat") && idx >= 0) {
|
|
767
|
+
// update: Slack は name / notify、Google Chat は notify だけ(名前はサーバが引く・#572)
|
|
743
768
|
const patch = {};
|
|
744
|
-
if (typeof p.name === "string" && p.name)
|
|
769
|
+
if (e.kind === "slack" && typeof p.name === "string" && p.name)
|
|
745
770
|
patch.name = p.name;
|
|
746
771
|
if (typeof p.notify === "boolean")
|
|
747
772
|
patch.notify = p.notify;
|
package/dist/render.js
CHANGED
|
@@ -18,6 +18,7 @@ exports.sanitizeStateNow = sanitizeStateNow;
|
|
|
18
18
|
exports.overlayStateOnFleet = overlayStateOnFleet;
|
|
19
19
|
exports.chatRowsToAdd = chatRowsToAdd;
|
|
20
20
|
exports.gchatRowsToAdd = gchatRowsToAdd;
|
|
21
|
+
exports.overlayGchatNotify = overlayGchatNotify;
|
|
21
22
|
exports.devRowsToAdd = devRowsToAdd;
|
|
22
23
|
exports.markExcludedPendingRows = markExcludedPendingRows;
|
|
23
24
|
exports.designRowsToAdd = designRowsToAdd;
|
|
@@ -854,7 +855,8 @@ const REGISTERED_CAP_NAMES = {
|
|
|
854
855
|
*/
|
|
855
856
|
const REGISTERED_FIELDS = {
|
|
856
857
|
chat: ["ref", "name", "workspace", "orgUnknown", "origin", "goldState", "notify"],
|
|
857
|
-
|
|
858
|
+
// notify(#572): スペースも通知先にできる。真偽値の扱いは chat の notify と同じ篩
|
|
859
|
+
"google-chat": ["ref", "name", "notify"],
|
|
858
860
|
dev: ["ref", "type"],
|
|
859
861
|
// 🔴 **意図的に外した開発リポジトリ(#391)。** サーバは前から別キーで返していたが、
|
|
860
862
|
// ここに無いので篩が丸ごと落としていた。**これが読めないと「読み取り停止中」の行を
|
|
@@ -1177,10 +1179,58 @@ function gchatRowsToAdd(externals, rows) {
|
|
|
1177
1179
|
continue;
|
|
1178
1180
|
if (have[String(r.ref)])
|
|
1179
1181
|
continue;
|
|
1180
|
-
|
|
1182
|
+
const row = { type: "google-chat", name: r.name || r.ref, ref: r.ref };
|
|
1183
|
+
// 通知先の印(#572)。真偽値の印は true のときだけ載せる(chatRowsToAdd と同じ)
|
|
1184
|
+
if (r.notify === true)
|
|
1185
|
+
row.notify = true;
|
|
1186
|
+
out.push(row);
|
|
1181
1187
|
}
|
|
1182
1188
|
return out;
|
|
1183
1189
|
}
|
|
1190
|
+
/**
|
|
1191
|
+
* まとめ表が既に持っている Google Chat の行に、live(registeredNow)の「通知先」の印を重ねる(#572)。
|
|
1192
|
+
*
|
|
1193
|
+
* 🔴 **engine のまとめ表(fleet-status)は Google Chat の行に `notify` を付けない**
|
|
1194
|
+
* (`resolve-external-sources.mjs` は Slack にだけ付ける)。重ねないと、押した直後の仮置きが
|
|
1195
|
+
* 切れたあと(最長 24 時間後)に、通知先のスペースが「通知先にする」に戻って見える
|
|
1196
|
+
* ——画面では通知先でないのに投稿される、という取り違えになる。
|
|
1197
|
+
*
|
|
1198
|
+
* **Slack の行には触らない**(まとめ表が正しく持っている・挙動を変えない)。live に
|
|
1199
|
+
* `google-chat` のキーが無ければ(読めていない)何も変えない。live に同じ ref の行があれば
|
|
1200
|
+
* その `notify` を正とし(true なら付け、そうでなければ外す)、live に無い行はそのまま
|
|
1201
|
+
* (消す判断は `subtractRemovedRegistered` の責務)。
|
|
1202
|
+
*
|
|
1203
|
+
* **クロージャを持たない純関数に保つこと**(`.toString()` でクライアントへ渡す)。
|
|
1204
|
+
*/
|
|
1205
|
+
function overlayGchatNotify(externals, rows) {
|
|
1206
|
+
const list = externals || [];
|
|
1207
|
+
if (!Array.isArray(rows))
|
|
1208
|
+
return list;
|
|
1209
|
+
const live = {};
|
|
1210
|
+
for (const r of rows) {
|
|
1211
|
+
if (!r || !r.ref)
|
|
1212
|
+
continue;
|
|
1213
|
+
live[String(r.ref)] = r.notify === true;
|
|
1214
|
+
}
|
|
1215
|
+
let changed = false;
|
|
1216
|
+
const out = list.map(function (s) {
|
|
1217
|
+
if (!s || s.type !== "google-chat" || !s.ref)
|
|
1218
|
+
return s;
|
|
1219
|
+
if (!Object.prototype.hasOwnProperty.call(live, String(s.ref)))
|
|
1220
|
+
return s;
|
|
1221
|
+
const want = live[String(s.ref)];
|
|
1222
|
+
if ((s.notify === true) === want)
|
|
1223
|
+
return s;
|
|
1224
|
+
changed = true;
|
|
1225
|
+
const row = Object.assign({}, s);
|
|
1226
|
+
if (want)
|
|
1227
|
+
row.notify = true;
|
|
1228
|
+
else
|
|
1229
|
+
delete row.notify;
|
|
1230
|
+
return row;
|
|
1231
|
+
});
|
|
1232
|
+
return changed ? out : list;
|
|
1233
|
+
}
|
|
1184
1234
|
/**
|
|
1185
1235
|
* 開発の行で、まとめ表がまだ知らないもの。**鍵は `owner/repo` の生文字列。**
|
|
1186
1236
|
*
|
|
@@ -1295,10 +1345,17 @@ function materialRowsToAdd(ids, rows) {
|
|
|
1295
1345
|
* ⚠ 画面の `targetsGenerationOf`(サーバへ送る世代)は同じ規則を持つが、この関数を
|
|
1296
1346
|
* 呼べない——配信物から関数1つを切り出して直接呼ぶテストがあり、外の名前を参照した
|
|
1297
1347
|
* 瞬間にそのテストが動かなくなる。あちらを直すときはここも直す。
|
|
1348
|
+
*
|
|
1349
|
+
* 🔴 **規則の正本は `infra/lambda/shared/connection-state-keys.mjs` の `issuesRefOf`**(#556)。
|
|
1350
|
+
* ここはその**写し**で、`viewer/` は独立した npm パッケージ(`rootDir: src`)なので
|
|
1351
|
+
* 原本を import できない。**ずれを捕まえる網は契約表**——
|
|
1352
|
+
* `infra/test/fixtures/connection-state-contract.json` の `issuesRefOf` の節を、
|
|
1353
|
+
* 原本(infra 側のテスト)と写し(viewer/test/state-ref-parity.test.mjs)の**両方**に流す。
|
|
1354
|
+
* 片方だけ直したら、直していない側が赤くなる。
|
|
1298
1355
|
*/
|
|
1299
1356
|
function issuesRefOf(domain, projectKey) {
|
|
1300
|
-
return String(domain == null ? "" : domain).toLowerCase() + "/" +
|
|
1301
|
-
String(projectKey == null ? "" : projectKey).toUpperCase();
|
|
1357
|
+
return String(domain == null ? "" : domain).trim().toLowerCase() + "/" +
|
|
1358
|
+
String(projectKey == null ? "" : projectKey).trim().toUpperCase();
|
|
1302
1359
|
}
|
|
1303
1360
|
/**
|
|
1304
1361
|
* 課題管理の行で、まとめ表がまだ知らないもの。
|
|
@@ -1578,9 +1635,11 @@ function mergeRegisteredFleet(view, reg) {
|
|
|
1578
1635
|
};
|
|
1579
1636
|
if (!reg)
|
|
1580
1637
|
return out;
|
|
1638
|
+
// Google Chat の行の「通知先」は live が正(#572・まとめ表は持っていない)。足す前に重ねる
|
|
1639
|
+
out.externalSources = overlayGchatNotify(v.externalSources, reg["google-chat"]);
|
|
1581
1640
|
const add = registeredRowsToAdd(v, reg);
|
|
1582
1641
|
if (add.externalSources.length)
|
|
1583
|
-
out.externalSources = (
|
|
1642
|
+
out.externalSources = (out.externalSources || []).concat(add.externalSources);
|
|
1584
1643
|
if (add.design.length || add.materials.length) {
|
|
1585
1644
|
const internals = (v.internalSources || []).slice();
|
|
1586
1645
|
const put = (kind, patch) => {
|
|
@@ -2055,12 +2114,16 @@ function fleetLastSyncOf(internal) {
|
|
|
2055
2114
|
* `issuesRefOf` はこれより**前**に流し込んである)。
|
|
2056
2115
|
*/
|
|
2057
2116
|
function stateRefKey(capId, ref, workspace) {
|
|
2058
|
-
|
|
2117
|
+
// 🔴 **`normalizeStateRef`(connection-state-keys.mjs)の写し**(#556)。ワークスペースを
|
|
2118
|
+
// 足すところだけが画面固有で、ref の畳み方そのものは向こうが正本
|
|
2119
|
+
// (契約表 `normalizeStateRef` の節を両側に流して突き合わせる)
|
|
2120
|
+
var s = String(ref == null ? "" : ref).trim();
|
|
2059
2121
|
if (!s)
|
|
2060
2122
|
return "";
|
|
2061
2123
|
if (capId === "issues") {
|
|
2062
2124
|
var at = s.indexOf("/");
|
|
2063
|
-
|
|
2125
|
+
// ドメインもキーも欠けた値から `issues` の鍵は組めない(原本と同じ判断)
|
|
2126
|
+
if (at <= 0 || at === s.length - 1)
|
|
2064
2127
|
return "";
|
|
2065
2128
|
return issuesRefOf(s.slice(0, at), s.slice(at + 1));
|
|
2066
2129
|
}
|
|
@@ -2094,24 +2157,27 @@ function registeredRefKeys(regKey, rows) {
|
|
|
2094
2157
|
out[issuesRefOf(r.domain, r.projectKey)] = true;
|
|
2095
2158
|
continue;
|
|
2096
2159
|
}
|
|
2160
|
+
// 🔴 **相方(`stateRefKey`)と同じだけ畳む(#556)。** あちらが前後の空白を落とすので、
|
|
2161
|
+
// ここが落とさないと**登録してあるのに「登録簿に無い」と判定される**行ができる
|
|
2162
|
+
// (いまは登録簿の値がサーバ側で trim 済みなので起きないが、片側だけ畳む形を残さない)
|
|
2097
2163
|
if (regKey === "design") {
|
|
2098
2164
|
if (r.key)
|
|
2099
|
-
out[String(r.key)] = true;
|
|
2165
|
+
out[String(r.key).trim()] = true;
|
|
2100
2166
|
continue;
|
|
2101
2167
|
}
|
|
2102
2168
|
if (regKey === "materials") {
|
|
2103
2169
|
if (r.id)
|
|
2104
|
-
out[String(r.id)] = true;
|
|
2170
|
+
out[String(r.id).trim()] = true;
|
|
2105
2171
|
continue;
|
|
2106
2172
|
}
|
|
2107
2173
|
if (!r.ref)
|
|
2108
2174
|
continue;
|
|
2109
2175
|
if (regKey === "chat") {
|
|
2110
|
-
out[String(r.workspace == null ? "" : r.workspace) + "\t" + String(r.ref)] = true;
|
|
2111
|
-
out["\t" + String(r.ref)] = true;
|
|
2176
|
+
out[String(r.workspace == null ? "" : r.workspace) + "\t" + String(r.ref).trim()] = true;
|
|
2177
|
+
out["\t" + String(r.ref).trim()] = true;
|
|
2112
2178
|
continue;
|
|
2113
2179
|
}
|
|
2114
|
-
out[String(r.ref)] = true;
|
|
2180
|
+
out[String(r.ref).trim()] = true;
|
|
2115
2181
|
}
|
|
2116
2182
|
return out;
|
|
2117
2183
|
}
|
|
@@ -4545,6 +4611,7 @@ var PROBE_WAIT_TIMEOUT_TEXT = ${JSON.stringify(exports.PROBE_WAIT_TIMEOUT_TEXT)}
|
|
|
4545
4611
|
${sanitizeRegisteredNow.toString()}
|
|
4546
4612
|
${chatRowsToAdd.toString()}
|
|
4547
4613
|
${gchatRowsToAdd.toString()}
|
|
4614
|
+
${overlayGchatNotify.toString()}
|
|
4548
4615
|
${devRowsToAdd.toString()}
|
|
4549
4616
|
${markExcludedPendingRows.toString()}
|
|
4550
4617
|
${designRowsToAdd.toString()}
|
|
@@ -10624,6 +10691,9 @@ ${calendarAddUrl.toString()}
|
|
|
10624
10691
|
"次回の Gold 昇格(毎晩22時ごろ)から、このスペースは読み取られなくなります。",
|
|
10625
10692
|
"",
|
|
10626
10693
|
"※ 既に Gold 層に入った内容は消えません(Decision・用語集はそのまま残ります)。",
|
|
10694
|
+
// 解除は通知先の宣言(notify.json)を触らない(#572)。通知先のまま解除すると
|
|
10695
|
+
// 行が消えて画面から止められなくなる——先に止める手順をここで言う
|
|
10696
|
+
"※ 通知先にしている場合は、先に「通知を止める」を押してください(解除しても通知先は変わりません)。",
|
|
10627
10697
|
"",
|
|
10628
10698
|
"解除しますか?",
|
|
10629
10699
|
];
|
|
@@ -10682,6 +10752,12 @@ ${calendarAddUrl.toString()}
|
|
|
10682
10752
|
*
|
|
10683
10753
|
* **クロージャを持たない純関数に保つこと**(テストが配信物から切り出して直接呼ぶ)。
|
|
10684
10754
|
* だから issuesRefOf を呼べない(規則の正本はあちら側。直すときは両方直す)。
|
|
10755
|
+
*
|
|
10756
|
+
* ⚠ **ここは前後の空白を落とさない。行の鍵(issuesRefOf)とは別物**(#556)。
|
|
10757
|
+
* 揃えたくなるが、**揃えなくても食い違わない**——サーバは受け取った世代を
|
|
10758
|
+
* normalizeGeneration に通してから比べ、そちらが空白を落とすため。逆に、ここで
|
|
10759
|
+
* 落とす形に変えるなら**サーバの両方**(targetsGeneration と normalizeGeneration)を
|
|
10760
|
+
* 同時に見ること。善意で片側だけ揃えると、正しい操作が毎回 409 になる。
|
|
10685
10761
|
*/
|
|
10686
10762
|
function targetsGenerationOf(list) {
|
|
10687
10763
|
return (list || [])
|
|
@@ -10931,9 +11007,9 @@ ${calendarAddUrl.toString()}
|
|
|
10931
11007
|
// cap と question の両方で絞る。片方だけだと、同じ ref を持つ別の問い
|
|
10932
11008
|
//(将来 issues に別の question が増えたとき)の行を取り込みとして読む
|
|
10933
11009
|
if (!r || r.cap !== "issues" || r.question !== "ingested") continue;
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
if (
|
|
11010
|
+
// 行側も畳み方の正本(stateRefKey = normalizeStateRef の写し)を通す(#556)。
|
|
11011
|
+
// ここで indexOf を自前で切っていた間は、**切り方が5本目**になっていた
|
|
11012
|
+
if (stateRefKey("issues", r.ref) === want) return r;
|
|
10937
11013
|
}
|
|
10938
11014
|
return null;
|
|
10939
11015
|
}
|
|
@@ -13227,6 +13303,11 @@ ${calendarAddUrl.toString()}
|
|
|
13227
13303
|
// だけなので、Slack のような origin の出し分けは不要
|
|
13228
13304
|
if (SITE.intake && s.type === "google-chat" && s.ref) {
|
|
13229
13305
|
card.appendChild(removeSpaceButton(s, card));
|
|
13306
|
+
// 通知先の入り切り(#572)。Slack と同じ notifyToggle・同じ文言・同じ op(サーバは
|
|
13307
|
+
// ref の形(spaces/…)で Google Chat と判定する)。スペースの行に workspace は無いので
|
|
13308
|
+
// 「読み取り専用の接続」の分岐には入らず、常にボタンが出る。仮置きの行(本物の行が
|
|
13309
|
+
// 来るまで)には Slack と同じく出さない
|
|
13310
|
+
if (s.pending !== true) card.appendChild(notifyToggle(s, badges));
|
|
13230
13311
|
}
|
|
13231
13312
|
// GitHubリポの登録から削除。**ON/OFF のトグルは撤去した(2026-08-21)**
|
|
13232
13313
|
//(stateToggle のコメント参照)。
|
package/package.json
CHANGED