@takagaki/cortex-decisions-viewer 0.12.128 → 0.12.130
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 +453 -600
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -5634,6 +5634,10 @@ a.ds-tile:hover { text-decoration: none; }
|
|
|
5634
5634
|
(flex: 1 1 100%)——.ds-toggle は横並びなので、隣の「誰が承認できるか」の説明と
|
|
5635
5635
|
横に並ぶと、どちらも半分の幅に潰れる(.ds-gate-help と同じ理由) */
|
|
5636
5636
|
.ds-connect-lead { flex: 1 1 100%; }
|
|
5637
|
+
/* 行の一手(.ds-gate-help)の文の途中に置くコピー・[接続する]・[トークンを入れる](c-07)。
|
|
5638
|
+
段落の中に置くので inline。ボタンは role=button のリンクか button のまま */
|
|
5639
|
+
.ds-act-inline { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0 0 0 6px; vertical-align: middle; }
|
|
5640
|
+
.ds-gate-help code.rt-copy-text { font-size: 12px; padding: 1px 8px; }
|
|
5637
5641
|
.ds-toggle-btn { font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border); background: #fff; color: var(--text); cursor: pointer; }
|
|
5638
5642
|
.ds-toggle-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
|
|
5639
5643
|
.ds-toggle-btn:disabled { opacity: .6; cursor: default; }
|
|
@@ -6635,6 +6639,9 @@ ${calendarAddUrl.toString()}
|
|
|
6635
6639
|
var DRIVE_INGEST_ACCOUNT = "cortex-notetaker@classmethod.jp";
|
|
6636
6640
|
// Google Chat の「スペースにアプリを追加する」手順の画像(#389)。理由は
|
|
6637
6641
|
// src/google-chat-guide-images.ts に書いてある
|
|
6642
|
+
// Google Chat アプリの表示名。**Marketplace 公開名(2026-09-03 オーナー決定で「Cortex Bot」から
|
|
6643
|
+
// 改称・#387)。** 行の一手(not_in_space)と依頼文が使う——直書きしない
|
|
6644
|
+
var GCHAT_APP_NAME = "Cortex by Classmethod";
|
|
6638
6645
|
var GCHAT_SHOT_STEP1 = "${google_chat_guide_images_1.GCHAT_APP_STEP1}";
|
|
6639
6646
|
var GCHAT_SHOT_STEP2 = "${google_chat_guide_images_1.GCHAT_APP_STEP2}";
|
|
6640
6647
|
// 案件カレンダーに予定を作る手順の画像(#452)。理由は src/meet-guide-images.ts
|
|
@@ -6644,15 +6651,11 @@ ${calendarAddUrl.toString()}
|
|
|
6644
6651
|
var FIGMA_SHOT_STEP2 = "${figma_guide_images_1.FIGMA_GUIDE_STEP2}";
|
|
6645
6652
|
var FIGMA_SHOT_STEP3 = "${figma_guide_images_1.FIGMA_GUIDE_STEP3}";
|
|
6646
6653
|
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
var field = el("code", { class: "rt-copy-text", text: text });
|
|
6653
|
-
// ボタンの語は既定「コピー」。何を写すかを言い分けたい所(#968 の欄)だけ渡す
|
|
6654
|
-
var btn = el("a", { class: "ds-toggle-btn", role: "button", tabindex: "0", text: label || "コピー" });
|
|
6655
|
-
var msg = el("div", { class: "ds-toggle-msg" });
|
|
6654
|
+
/**
|
|
6655
|
+
* コピーボタンの動き(copyRow と copyInline の共通部分)。clipboard が使えない環境では
|
|
6656
|
+
* 文字列を選択状態にして次の一手を伝える。
|
|
6657
|
+
*/
|
|
6658
|
+
function bindCopy(btn, field, msg, text) {
|
|
6656
6659
|
btn.addEventListener("click", function () {
|
|
6657
6660
|
var done = function () { msg.className = "ds-toggle-msg is-ok"; msg.textContent = "✓ コピーしました。"; };
|
|
6658
6661
|
var fallback = function () {
|
|
@@ -6674,9 +6677,38 @@ ${calendarAddUrl.toString()}
|
|
|
6674
6677
|
} else fallback();
|
|
6675
6678
|
} catch (e) { fallback(); }
|
|
6676
6679
|
});
|
|
6680
|
+
}
|
|
6681
|
+
|
|
6682
|
+
function copyRow(text, label) {
|
|
6683
|
+
// **input と button を使わない。** 追加フォームの中に置くので、input を足すと
|
|
6684
|
+
// 「先頭がURL欄・末尾が名前欄」、button を足すと「最初のボタンが送信」という
|
|
6685
|
+
// フォームの並びが崩れる(実際にテストが壊れて気づいた)。
|
|
6686
|
+
// 表示は code、コピーは role="button" のリンクで代える。
|
|
6687
|
+
var field = el("code", { class: "rt-copy-text", text: text });
|
|
6688
|
+
// ボタンの語は既定「コピー」。何を写すかを言い分けたい所(#968 の欄)だけ渡す
|
|
6689
|
+
var btn = el("a", { class: "ds-toggle-btn", role: "button", tabindex: "0", text: label || "コピー" });
|
|
6690
|
+
var msg = el("div", { class: "ds-toggle-msg" });
|
|
6691
|
+
bindCopy(btn, field, msg, text);
|
|
6677
6692
|
return el("div", { class: "rt-copy" }, [el("div", { class: "rt-url-row" }, [field, btn]), msg]);
|
|
6678
6693
|
}
|
|
6679
6694
|
|
|
6695
|
+
/**
|
|
6696
|
+
* 行の一手(1 段落)の中に置く、文の途中のコピー(c-07)。copyRow は箱(div)なので段落に入らない。
|
|
6697
|
+
* **文面にその文字列が含まれているとき(showText=false)は[コピー]だけ**、含まれていないときは
|
|
6698
|
+
* 文字列(code)と[コピー]。ボタンは role="button" のリンク(行のボタンの並びを変えない)。
|
|
6699
|
+
*/
|
|
6700
|
+
function copyInline(text, showText) {
|
|
6701
|
+
var wrap = el("span", { class: "ds-act-inline" });
|
|
6702
|
+
var field = el("code", { class: "rt-copy-text", text: text });
|
|
6703
|
+
if (showText) wrap.appendChild(field);
|
|
6704
|
+
var btn = el("a", { class: "ds-toggle-btn", role: "button", tabindex: "0", text: "コピー" });
|
|
6705
|
+
var msg = el("span", { class: "ds-toggle-msg" });
|
|
6706
|
+
bindCopy(btn, showText ? field : el("code", { text: text }), msg, text);
|
|
6707
|
+
wrap.appendChild(btn);
|
|
6708
|
+
wrap.appendChild(msg);
|
|
6709
|
+
return wrap;
|
|
6710
|
+
}
|
|
6711
|
+
|
|
6680
6712
|
// 要素を組み立てるヘルパ。
|
|
6681
6713
|
// ⚠️ **el() 自体は無害化しない。** class/text 以外のキーはそのまま setAttribute へ渡すので
|
|
6682
6714
|
// href に javascript: を置けるし、html: は innerHTML への抜け道(実使用は
|
|
@@ -9786,7 +9818,16 @@ ${calendarAddUrl.toString()}
|
|
|
9786
9818
|
"ok": { text: "接続OK", cls: "ds-gate-ok" },
|
|
9787
9819
|
// **状態だけでなく、次にすることを書く。** 「bot未招待」では何をすればよいか分からない
|
|
9788
9820
|
// (公開チャンネルでも招待が要ることは Slack の仕様で、知らない人のほうが多い)
|
|
9789
|
-
|
|
9821
|
+
//
|
|
9822
|
+
// 🔴 **一手は行の中に出す(c-07)。** 札は症状(未招待)、一手は「Cortex が招待されていません:
|
|
9823
|
+
// /invite @Cortex[コピー]」の 1 行。追加の欄の手順 1 にあったコピー行はここへ移した。
|
|
9824
|
+
// help を持たせたので、showsRestingReason は夜間の理由文(機械の語)を重ねない
|
|
9825
|
+
"not_in_channel": {
|
|
9826
|
+
text: "Slackで招待してください",
|
|
9827
|
+
cls: "ds-gate-warn",
|
|
9828
|
+
help: "Cortex が招待されていません:",
|
|
9829
|
+
copy: "/invite @Cortex",
|
|
9830
|
+
},
|
|
9790
9831
|
// **招待では直らない(2026-08-19 の不具合報告)。** 非公開チャンネルで groups:read が
|
|
9791
9832
|
// 足りていたのに、実測がこれを「不明」に潰していたので画面には「接続OK」としか出ず、
|
|
9792
9833
|
// 名前が引けない理由が一切分からなかった(原因の特定に半日かかった)。
|
|
@@ -9803,10 +9844,29 @@ ${calendarAddUrl.toString()}
|
|
|
9803
9844
|
// (DS_GATE_NO_TOKEN と同じ作り。バッジに長文を入れると行が折り返す)。
|
|
9804
9845
|
// 判定を返すのは engine の夜間実測(Phase 2)——画面は語彙と文面だけを先に持つ
|
|
9805
9846
|
// not_in_channel の「招待」とは直す操作が別物なので寄せない
|
|
9847
|
+
//
|
|
9848
|
+
// 🔴 **アプリの追加手順(画面操作・画像 2 枚・管理者の承認)は追加の欄から移した(c-07)。**
|
|
9849
|
+
// help が summary の 1 文・本文は details に畳む(admin_approval_pending と同じ型)。
|
|
9850
|
+
// 画像(shots)は**行の一手(ds-gate-help)にだけ**出し、押した結果・能力タイルには出さない
|
|
9851
|
+
// (gateHelpNodes)
|
|
9806
9852
|
"not_in_space": {
|
|
9807
9853
|
text: "スペースにアプリ未追加",
|
|
9808
9854
|
cls: "ds-gate-warn",
|
|
9809
|
-
help: "
|
|
9855
|
+
help: "スペースの「アプリと統合」から「" + GCHAT_APP_NAME + "」を追加してください。",
|
|
9856
|
+
request: {
|
|
9857
|
+
lines: [
|
|
9858
|
+
{
|
|
9859
|
+
text: "スペース名 →「アプリと統合」→「アプリを追加」で、「" + GCHAT_APP_NAME + "」を検索して追加します。",
|
|
9860
|
+
shots: [
|
|
9861
|
+
{ src: GCHAT_SHOT_STEP1, width: "900", height: "566",
|
|
9862
|
+
alt: "Google Chat のスペースの画面。スペース名の横のメニューが開いていて、その中の「アプリと統合」が赤い枠で示されている。" },
|
|
9863
|
+
{ src: GCHAT_SHOT_STEP2, width: "900", height: "491",
|
|
9864
|
+
alt: "「アプリと統合」の画面。右上の「+ アプリを追加」が赤い枠で示され、その下に、このスペースに追加されているアプリの一覧が並んでいる。" },
|
|
9865
|
+
],
|
|
9866
|
+
},
|
|
9867
|
+
"検索に出ないときは、貴社の Google Workspace 管理者の承認がまだです(承認できるのは管理者だけ・反映まで最大24時間)。",
|
|
9868
|
+
],
|
|
9869
|
+
},
|
|
9810
9870
|
},
|
|
9811
9871
|
// no_token の「トークン未設定」は接続ボタンの無い Google Chat では打つ手を示せないので寄せない。
|
|
9812
9872
|
// 内部語(サービスアカウント・鍵)は出さない——顧客側に打つ手が無い状態のため
|
|
@@ -9831,10 +9891,10 @@ ${calendarAddUrl.toString()}
|
|
|
9831
9891
|
help: "貴社の Google Workspace 管理者がこのアプリを承認すると、読み取りが始まります。",
|
|
9832
9892
|
request: {
|
|
9833
9893
|
lines: [
|
|
9834
|
-
"貴社の Google Workspace 管理者に、次の手順で「
|
|
9894
|
+
"貴社の Google Workspace 管理者に、次の手順で「" + GCHAT_APP_NAME + "」の利用承認をご依頼ください。",
|
|
9835
9895
|
"1. Google 管理コンソール(admin.google.com)を開く",
|
|
9836
9896
|
"2. 「アプリ」→「Google Workspace Marketplace アプリ」を開く",
|
|
9837
|
-
"3. 「アプリを追加」から「
|
|
9897
|
+
"3. 「アプリを追加」から「" + GCHAT_APP_NAME + "」を検索する",
|
|
9838
9898
|
"4. 組織全体(または該当の組織部門)へのインストールを選び、データへのアクセスを許可する",
|
|
9839
9899
|
],
|
|
9840
9900
|
},
|
|
@@ -9934,7 +9994,11 @@ ${calendarAddUrl.toString()}
|
|
|
9934
9994
|
customer: {
|
|
9935
9995
|
text: "トークン未設定",
|
|
9936
9996
|
cls: "ds-gate-muted",
|
|
9937
|
-
|
|
9997
|
+
// 🔴 **一手は「この Slack を Cortex に接続してください。[接続する]」の 1 行(c-07)。**
|
|
9998
|
+
// 常設の[Slack ワークスペースに接続する]は撤去し、接続はこの行の一手が持つ。
|
|
9999
|
+
// 主語は「この Slack」(承認画面はワークスペースを指定できない——slackConnectInline の項)
|
|
10000
|
+
help: "この Slack を Cortex に接続してください。",
|
|
10001
|
+
act: "connect",
|
|
9938
10002
|
},
|
|
9939
10003
|
/* -------------------------------------------------------------------------
|
|
9940
10004
|
* GitHub。**「トークン未設定」と言ってはいけない**(2026-08-21)
|
|
@@ -10016,6 +10080,14 @@ ${calendarAddUrl.toString()}
|
|
|
10016
10080
|
* 「登録から削除」(#354)が担う。区別する信号ができたら probed に足す
|
|
10017
10081
|
*/
|
|
10018
10082
|
var DS_GATE_RESTING_HELP = {
|
|
10083
|
+
// 🔴 **Slack の「理由不明」の一手(c-07)。** 行の中身(社内か・組織不明か・台帳の接続状態)で
|
|
10084
|
+
// 変わるので関数で持つ(DS_GATE.unreachable は help を持たない)。部品の型は
|
|
10085
|
+
// 文字列 / { link, kind } / { copy } / { act: "connect" }(restingHelpNode)
|
|
10086
|
+
slack: {
|
|
10087
|
+
unreachable: {
|
|
10088
|
+
resting: function (row) { return slackRowHelpParts(row); },
|
|
10089
|
+
},
|
|
10090
|
+
},
|
|
10019
10091
|
github: {
|
|
10020
10092
|
// 🔴 **読めない行の中に、理由に合った一手だけを出す(#1233)。** 全体の帯は撤去した。
|
|
10021
10093
|
// 一手は組織の App の導入状況(githubRowHelpParts)で決まるので、関数で持つ
|
|
@@ -10073,20 +10145,73 @@ ${calendarAddUrl.toString()}
|
|
|
10073
10145
|
}
|
|
10074
10146
|
return ["この組織に Cortex の GitHub App を入れてください。", { link: "GitHub App を入れる →", kind: "install" }];
|
|
10075
10147
|
}
|
|
10148
|
+
/**
|
|
10149
|
+
* Slack の「理由不明」の行(unreachable・組織不明の仮置き)に出す一手(c-07)。
|
|
10150
|
+
* **広い方の 1 行**にする——原因は行の分類では絞れない(0.12.2 の実測)ので、片方に賭けない。
|
|
10151
|
+
*
|
|
10152
|
+
* - ワークスペースが分かっていて、台帳の接続が切れている/未接続 → 「この Slack を Cortex に接続してください。[接続する]」
|
|
10153
|
+
* - ワークスペースが分かっていて、接続が生きている → 招待だけ
|
|
10154
|
+
* - 社内・組織不明(分類が当てにならない)→ 招待 + 「お客様の Slack なら、ワークスペースを接続してください。[接続する]」
|
|
10155
|
+
*
|
|
10156
|
+
* 🔴 **投入の口(SITE.intake)が無い案件では接続を出さない**(押せない案内を置かない)。
|
|
10157
|
+
*/
|
|
10158
|
+
function slackRowHelpParts(row) {
|
|
10159
|
+
if (!row) return null;
|
|
10160
|
+
var invite = ["Cortex からこのチャンネルが見えません。Cortex を招待してください:", { copy: "/invite @Cortex" }];
|
|
10161
|
+
var canConnect = !!SITE.intake;
|
|
10162
|
+
if (row.workspace) {
|
|
10163
|
+
var st = tokenStateOf(slackWorkspaces(), row.workspace);
|
|
10164
|
+
if (st === "revoked" || st === "missing") {
|
|
10165
|
+
return canConnect ? ["この Slack を Cortex に接続してください。", { act: "connect" }] : invite;
|
|
10166
|
+
}
|
|
10167
|
+
return invite;
|
|
10168
|
+
}
|
|
10169
|
+
return canConnect
|
|
10170
|
+
? invite.concat([" お客様の Slack なら、ワークスペースを接続してください。", { act: "connect" }])
|
|
10171
|
+
: invite;
|
|
10172
|
+
}
|
|
10076
10173
|
/** 押した結果に添えるパーツ(無ければ null)。行と同じ表から引く(写経しない) */
|
|
10077
10174
|
function probedHelpPartsOf(type, gate) {
|
|
10078
10175
|
var e = restingHelpEntryOf(type, gate);
|
|
10079
10176
|
return (e && e.probed) || null;
|
|
10080
10177
|
}
|
|
10081
|
-
/**
|
|
10178
|
+
/**
|
|
10179
|
+
* パーツを1段落にする。包む要素の class は置き場所で違う(行は ds-gate-help・押した結果は ds-probe-help)。
|
|
10180
|
+
* 部品: 文字列=テキスト / { link, kind } = GitHub App のリンク /
|
|
10181
|
+
* { copy } =コピー付きの 1 語(文字列と[コピー]) / { act } =ボタン(actNode)。
|
|
10182
|
+
* **部品は同じ段落の中に置く**(段を増やさない=行の補足は最大 1 段)。
|
|
10183
|
+
*/
|
|
10082
10184
|
function restingHelpNode(parts, cls) {
|
|
10083
10185
|
var p = el("p", { class: cls });
|
|
10084
10186
|
parts.forEach(function (part) {
|
|
10085
10187
|
if (typeof part === "string") p.appendChild(document.createTextNode(part));
|
|
10086
10188
|
else if (part && part.link) p.appendChild(el("a", { href: githubAppLinkUrl(part.kind), target: "_blank", rel: "noopener", text: part.link }));
|
|
10189
|
+
else if (part && part.copy) p.appendChild(copyInline(part.copy, true));
|
|
10190
|
+
else if (part && part.act) { var an = actNode(part.act); if (an) p.appendChild(an); }
|
|
10087
10191
|
});
|
|
10088
10192
|
return p;
|
|
10089
10193
|
}
|
|
10194
|
+
/**
|
|
10195
|
+
* 行の一手に置くボタン(c-07)。**押せないボタンは作らない**(null)。
|
|
10196
|
+
* - "connect" … [接続する]。Slack の承認画面へ送る(slackConnectInline)。投入の口が無ければ null
|
|
10197
|
+
* - "figma-key" … [トークンを入れる]/[トークンを入れ直す]。下の「Figma のトークン」の欄の入力へ移る
|
|
10198
|
+
* @param label 省略時は既定の語
|
|
10199
|
+
*/
|
|
10200
|
+
function actNode(act, label) {
|
|
10201
|
+
if (!SITE.intake) return null;
|
|
10202
|
+
if (act === "connect") return slackConnectInline(label || "接続する");
|
|
10203
|
+
// 鍵の欄(KEY_SLOTS.figma)が無い構成では、移る先が無いので出さない
|
|
10204
|
+
if (act === "figma-key") return secretKindsShown().indexOf("figma") >= 0 ? figmaKeyJump(label || "トークンを入れる") : null;
|
|
10205
|
+
return null;
|
|
10206
|
+
}
|
|
10207
|
+
/**
|
|
10208
|
+
* 一手の文に添える部品(gate.copy / gate.act)を、**同じ段落の中**へ足す。
|
|
10209
|
+
* copy が文面にそのまま含まれているとき(Drive のアドレス)は[コピー]だけ、含まれていないときは文字列も出す
|
|
10210
|
+
*/
|
|
10211
|
+
function appendGateActs(p, gate) {
|
|
10212
|
+
if (gate.copy) p.appendChild(copyInline(gate.copy, String(gate.help || "").indexOf(gate.copy) < 0));
|
|
10213
|
+
if (gate.act) { var an = actNode(gate.act, gate.actLabel); if (an) p.appendChild(an); }
|
|
10214
|
+
}
|
|
10090
10215
|
/**
|
|
10091
10216
|
* ボタンの detail が「機械語の痕跡」でしかない能力(#548・設計v2 🔴2)。
|
|
10092
10217
|
*
|
|
@@ -10158,7 +10283,8 @@ ${calendarAddUrl.toString()}
|
|
|
10158
10283
|
* (省略=社内。#104 でこの値が画面まで届いていることは slack-workspace.test.mjs が見張る)。
|
|
10159
10284
|
*/
|
|
10160
10285
|
function isInternalSlack(s) {
|
|
10161
|
-
|
|
10286
|
+
// 組織不明(orgUnknown)の行は分類が当てにならない=社内と断定しない(顧客側の一手=接続を出す)
|
|
10287
|
+
return s.type === "slack" && !s.workspace && s.orgUnknown !== true;
|
|
10162
10288
|
}
|
|
10163
10289
|
/**
|
|
10164
10290
|
* Slack チャンネルの表示名。**# は表示のときだけ付ける**(保存値は素・2026-08-19)。
|
|
@@ -10191,7 +10317,7 @@ ${calendarAddUrl.toString()}
|
|
|
10191
10317
|
*
|
|
10192
10318
|
* **ここを通さずに語を書き写さないこと。** 行バッジ・能力タイルの要約・
|
|
10193
10319
|
* 「接続を確認」の結果が同じ関数を通るので、片方だけ古くなることが構造的に起きない
|
|
10194
|
-
* (attentionSummary
|
|
10320
|
+
* (attentionSummary の項に、実際に割れた経緯がある)。
|
|
10195
10321
|
*/
|
|
10196
10322
|
function dsGateOf(s) {
|
|
10197
10323
|
if (s.gate === "no_token") {
|
|
@@ -10233,7 +10359,10 @@ ${calendarAddUrl.toString()}
|
|
|
10233
10359
|
unreachable: {
|
|
10234
10360
|
text: "フォルダを開けません",
|
|
10235
10361
|
cls: "ds-gate-warn",
|
|
10236
|
-
|
|
10362
|
+
// 🔴 **一手は「このフォルダを cortex-notetaker@… に閲覧者として共有してください。[コピー]」の 1 行(c-07)。**
|
|
10363
|
+
// コピーは追加の欄の手順 1 にだけあったので、ここへ移した(help の文面にアドレスが含まれるので[コピー]だけ)
|
|
10364
|
+
help: "このフォルダを " + DRIVE_INGEST_ACCOUNT + " に閲覧者として共有してください。",
|
|
10365
|
+
copy: DRIVE_INGEST_ACCOUNT,
|
|
10237
10366
|
},
|
|
10238
10367
|
no_token: { text: "管理者の設定が必要です", cls: "ds-gate-muted" },
|
|
10239
10368
|
// SharePoint の判定表は管理者の同意を前提のまま(チームの RSC にファイルの権限が無い・PoC C で決める)。
|
|
@@ -10246,12 +10375,26 @@ ${calendarAddUrl.toString()}
|
|
|
10246
10375
|
},
|
|
10247
10376
|
issues: { no_token: { text: "APIキーが未登録です", cls: "ds-gate-muted" } },
|
|
10248
10377
|
design: {
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10378
|
+
// 🔴 **鍵が無い行の一手は、行の中の 1 行(c-07)。** [トークンを入れる]が下の「Figma のトークン」の欄の入力へ移る
|
|
10379
|
+
no_token: {
|
|
10380
|
+
text: "トークンが未登録です",
|
|
10381
|
+
cls: "ds-gate-muted",
|
|
10382
|
+
help: "Figma のトークンを入れてください。",
|
|
10383
|
+
act: "figma-key",
|
|
10384
|
+
},
|
|
10385
|
+
// 「アクセス不可」では、トークンの失効なのか(403)ファイルを共有していないのか(404)が
|
|
10386
|
+
// 画面から見分けられない(理由が文字の中だけ=機械の語に依存した分岐は書かない・c-07)。
|
|
10387
|
+
// **広い方の 1 行に両方を入れる。** engine の理由文(「HTTP 403」「HTTP 404」が混ざる)は
|
|
10388
|
+
// 出さない——help を持たせると appendReachableReason が先にこちらを返す。
|
|
10389
|
+
// Figma は「Cortex の共有アカウント」ではなく**トークンを発行した人のアカウント**で読むので、
|
|
10390
|
+
// 招待先のアドレスは画面が知らない(コピーは付けない。決定メモの分類 B)
|
|
10391
|
+
unreachable: {
|
|
10392
|
+
text: "ファイルを読めません",
|
|
10393
|
+
cls: "ds-gate-warn",
|
|
10394
|
+
help: "このファイルに、トークンを発行したアカウントを閲覧者として招待してください(トークンが切れているときは入れ直してください)。",
|
|
10395
|
+
act: "figma-key",
|
|
10396
|
+
actLabel: "トークンを入れ直す",
|
|
10397
|
+
},
|
|
10255
10398
|
},
|
|
10256
10399
|
};
|
|
10257
10400
|
/**
|
|
@@ -10282,16 +10425,32 @@ ${calendarAddUrl.toString()}
|
|
|
10282
10425
|
* (下の probeSection の stale 処理)ので、混同すると二重表示か消え忘れが起きる
|
|
10283
10426
|
*/
|
|
10284
10427
|
function gateHelpNodes(gate, cls) {
|
|
10428
|
+
// 🔴 **押せない一手は出さない(c-07)。** 接続・トークンの口(SITE.intake)が無い案件に
|
|
10429
|
+
// 「接続してください」だけを置かない(押せない案内)
|
|
10430
|
+
if (gate.act && !SITE.intake) return [];
|
|
10285
10431
|
if (gate.request) {
|
|
10286
10432
|
var det = el("details", { class: cls + " ds-gate-request" }, [
|
|
10287
10433
|
el("summary", { text: gate.help || "詳しい手順" }),
|
|
10288
10434
|
]);
|
|
10289
10435
|
gate.request.lines.forEach(function (line) {
|
|
10290
|
-
|
|
10436
|
+
// 行は文字列か { text, shots }。**画像は行の一手(ds-gate-help)にだけ**出す——押した結果
|
|
10437
|
+
// (ds-probe-help)にも能力タイルにも出さない(同じ画像が 2 か所に並ぶのを避ける)
|
|
10438
|
+
var lineText = typeof line === "string" ? line : (line && line.text) || "";
|
|
10439
|
+
var lp = el("p", { class: "ds-gate-request-line", text: lineText });
|
|
10440
|
+
det.appendChild(lp);
|
|
10441
|
+
if (line && typeof line === "object" && line.shots && cls === "ds-gate-help") {
|
|
10442
|
+
var shotBox = el("div", { class: "ds-gate-request-shots" });
|
|
10443
|
+
line.shots.forEach(function (sh) { shotBox.appendChild(guideShot(sh)); });
|
|
10444
|
+
det.appendChild(shotBox);
|
|
10445
|
+
}
|
|
10291
10446
|
});
|
|
10292
10447
|
return [det];
|
|
10293
10448
|
}
|
|
10294
|
-
if (gate.help)
|
|
10449
|
+
if (gate.help) {
|
|
10450
|
+
var p = el("p", { class: cls, text: gate.help });
|
|
10451
|
+
appendGateActs(p, gate);
|
|
10452
|
+
return [p];
|
|
10453
|
+
}
|
|
10295
10454
|
return [];
|
|
10296
10455
|
}
|
|
10297
10456
|
/**
|
|
@@ -10761,24 +10920,21 @@ ${calendarAddUrl.toString()}
|
|
|
10761
10920
|
}
|
|
10762
10921
|
|
|
10763
10922
|
/**
|
|
10764
|
-
* Slack の承認画面へ進むボタン(2026-08-20
|
|
10923
|
+
* Slack の承認画面へ進むボタン(2026-08-20 に接続カードから切り出し・c-07 で行の一手の中へ移した)。
|
|
10765
10924
|
*
|
|
10766
|
-
* ##
|
|
10925
|
+
* ## 置き場所
|
|
10926
|
+
*
|
|
10927
|
+
* **常設のボタンと、組織不明・接続切れの枠は撤去した(c-07)。** 接続は、必要になった行の一手
|
|
10928
|
+
* 「この Slack を Cortex に接続してください。[接続する]」の中にだけ置く(押す理由はその一文が言う)。
|
|
10929
|
+
* 一手の段落(ds-gate-help・押した結果の ds-probe-help)の**中**に置くので、段は増えない。
|
|
10930
|
+
*
|
|
10931
|
+
* ## 押す人についての注意(説明は上部の説明文に 1 回だけ)
|
|
10767
10932
|
*
|
|
10768
10933
|
* **承認画面はワークスペースを指定できない**(開始の口に team を渡す口が無い)。
|
|
10769
10934
|
* **承認する人がログインしているワークスペース**にボットが入る。だから
|
|
10770
10935
|
* 「〈お客様の名前〉と接続する」とは書けない——保証できないことを書かない。
|
|
10771
|
-
*
|
|
10772
|
-
*
|
|
10773
|
-
* (その Slack の管理者にお願いすることになる)。それを書かないと、
|
|
10774
|
-
* 押しても進まない人が「壊れている」と読む。
|
|
10775
|
-
*
|
|
10776
|
-
* ## 常設の入口として置くときは lead を渡す(0.12.2)
|
|
10777
|
-
*
|
|
10778
|
-
* 「組織不明」の案内の中では、直前の箇条書きが**なぜ接続するのか**を言っている。
|
|
10779
|
-
* 追加フォームの後に単独で置くときは**その文脈が無い**ので、押す理由が画面から
|
|
10780
|
-
* 読み取れない——下の説明文は「誰が承認できるか」の話しかしていない。
|
|
10781
|
-
* 1行だけ添える口を開けておく。**見出しは付けない**(節を増やすと一覧が遠くなる)。
|
|
10936
|
+
* お客様の Slack なら、クラスメソッドの人間は押せないことが多い(その Slack の管理者に
|
|
10937
|
+
* お願いすることになる)。それは、チャットのモーダルの説明文が 1 回だけ言う。
|
|
10782
10938
|
*
|
|
10783
10939
|
* ## 承認画面から戻ってきたとき(#343)
|
|
10784
10940
|
*
|
|
@@ -10790,18 +10946,15 @@ ${calendarAddUrl.toString()}
|
|
|
10790
10946
|
* 戻す口は**起動時に1本だけ張った listener が data-leaving を DOM から探す**形にした
|
|
10791
10947
|
* ——モーダルを開くたびにこのボタンは作り直されるので、登録簿に貯めると
|
|
10792
10948
|
* 閉じたモーダルの DOM を掴み続ける。印を付けるのは遷移が確定した瞬間だけで、
|
|
10793
|
-
*
|
|
10949
|
+
* 失敗経路(その場でボタンを戻す)には付けない。戻すとき結果の文は同じ .ds-toggle の
|
|
10950
|
+
* 中の .ds-toggle-msg を空にする(restoreLeavingButtons)ので、ここも同じ箱の形にしてある。
|
|
10794
10951
|
*
|
|
10795
|
-
* @param
|
|
10952
|
+
* @param label ボタンの語(既定は「接続する」)
|
|
10796
10953
|
*/
|
|
10797
|
-
function
|
|
10798
|
-
var wrap = el("
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
// (承認する人がログインしているワークスペースに入る)ので、
|
|
10802
|
-
// 特定のものを指すような書き方は嘘にもなる
|
|
10803
|
-
var btn = el("button", { class: "ds-toggle-btn", type: "button", text: "Slack ワークスペースに接続する" });
|
|
10804
|
-
var msg = el("div", { class: "ds-toggle-msg" });
|
|
10954
|
+
function slackConnectInline(label) {
|
|
10955
|
+
var wrap = el("span", { class: "ds-toggle ds-act-inline" });
|
|
10956
|
+
var btn = el("button", { class: "ds-toggle-btn", type: "button", text: label || "接続する" });
|
|
10957
|
+
var msg = el("span", { class: "ds-toggle-msg" });
|
|
10805
10958
|
btn.addEventListener("click", async function () {
|
|
10806
10959
|
var intake = SITE.intake;
|
|
10807
10960
|
if (!intake) return;
|
|
@@ -10820,10 +10973,7 @@ ${calendarAddUrl.toString()}
|
|
|
10820
10973
|
}
|
|
10821
10974
|
// **同じタブで遷移する。** 別タブだと、承認後の「接続しました」を見た人が
|
|
10822
10975
|
// 元のタブに戻る動線を自分で見つけることになる
|
|
10823
|
-
//
|
|
10824
|
-
// **遷移が確定したこの瞬間にだけ印を付ける(#343)。** ブラウザバックで
|
|
10825
|
-
// bfcache から復元されたとき、起動時の pageshow の listener がこの印を頼りに
|
|
10826
|
-
// ボタンと「準備しています…」を素の状態へ戻す(restoreLeavingButtons)
|
|
10976
|
+
// **遷移が確定したこの瞬間にだけ印を付ける(#343)**
|
|
10827
10977
|
btn.setAttribute("data-leaving", "1");
|
|
10828
10978
|
location.href = j.url;
|
|
10829
10979
|
} catch (e) {
|
|
@@ -10832,20 +10982,29 @@ ${calendarAddUrl.toString()}
|
|
|
10832
10982
|
btn.disabled = false;
|
|
10833
10983
|
}
|
|
10834
10984
|
});
|
|
10835
|
-
// **lead は「なぜ押すのか」・下の説明は「誰が押せるのか」。** 別のことを言っているので
|
|
10836
|
-
// 1文にまとめない(まとめると、どちらの話なのか読み取れない長文になる)
|
|
10837
|
-
if (lead) wrap.appendChild(el("p", { class: "ds-group-note ds-connect-lead", text: lead }));
|
|
10838
|
-
wrap.appendChild(el("p", {
|
|
10839
|
-
class: "ds-group-note",
|
|
10840
|
-
text: "ボタンを押すと Slack の承認画面が開きます。承認できるのは、その Slack の管理者だけです"
|
|
10841
|
-
+ "(お客様の Slack なら、お客様の管理者にお願いしてください)。"
|
|
10842
|
-
+ "お願いするのは、登録したチャンネルを読む権限と、通知を投稿する権限です。",
|
|
10843
|
-
}));
|
|
10844
10985
|
wrap.appendChild(btn);
|
|
10845
10986
|
wrap.appendChild(msg);
|
|
10846
10987
|
return wrap;
|
|
10847
10988
|
}
|
|
10848
10989
|
|
|
10990
|
+
/**
|
|
10991
|
+
* [トークンを入れる]/[トークンを入れ直す](Figma の行の一手・c-07)。
|
|
10992
|
+
* 一覧の直後にある「Figma のトークン」の欄(KEY_SLOTS.figma)の入力へ移って focus する。
|
|
10993
|
+
* **欄は 0 件のあいだ畳まれている**が、行がある=ファイルが 1 件以上あるので畳まれていない。
|
|
10994
|
+
* 入力が見つからなければ何もしない(鍵の欄を作る口が無い構成)。
|
|
10995
|
+
*/
|
|
10996
|
+
function figmaKeyJump(label) {
|
|
10997
|
+
var btn = el("button", { class: "ds-toggle-btn ds-act-inline", type: "button", text: label || "トークンを入れる" });
|
|
10998
|
+
btn.addEventListener("click", function () {
|
|
10999
|
+
var slot = KEY_SLOTS.figma;
|
|
11000
|
+
var input = slot && slot.querySelector("input, textarea");
|
|
11001
|
+
if (!input) return;
|
|
11002
|
+
try { if (input.scrollIntoView) input.scrollIntoView({ block: "center" }); } catch (e) { /* 動かせなくても focus は試す */ }
|
|
11003
|
+
input.focus();
|
|
11004
|
+
});
|
|
11005
|
+
return btn;
|
|
11006
|
+
}
|
|
11007
|
+
|
|
10849
11008
|
/** 台帳から、そのワークスペースの接続状態を引く(無ければ null=断定しない) */
|
|
10850
11009
|
function tokenStateOf(workspaces, teamId) {
|
|
10851
11010
|
var list = workspaces || [];
|
|
@@ -10892,6 +11051,7 @@ ${calendarAddUrl.toString()}
|
|
|
10892
11051
|
// 「反映したのに何も変わらない」と読まれてもう一度押すことになる
|
|
10893
11052
|
var note = document.querySelector(".ds-org-resolved");
|
|
10894
11053
|
if (!note) return;
|
|
11054
|
+
note.hidden = false;
|
|
10895
11055
|
note.textContent = "✓ " + j.resolved + "件の所属を反映しました(この一覧の表示は次回の更新・毎晩22時ごろから正しくなります)。";
|
|
10896
11056
|
})
|
|
10897
11057
|
.catch(function () {
|
|
@@ -11037,7 +11197,7 @@ ${calendarAddUrl.toString()}
|
|
|
11037
11197
|
var again = !!(x.ref && seenRef[x.ref]);
|
|
11038
11198
|
if (x.ref) seenRef[x.ref] = 1;
|
|
11039
11199
|
var rowCard = extSourceCard(x, DS_TYPE[x.type] || { icon: "🔗", label: x.type || "その他" }, { quietHelp: again });
|
|
11040
|
-
// 同じリポの issues / discussions
|
|
11200
|
+
// 同じリポの issues / discussions の行の目印(同じ dev 行から描くので、判定は 1 つの描き直しで揃う)
|
|
11041
11201
|
if (rowCard && rowCard.setAttribute && x.ref) rowCard.setAttribute("data-ref", x.ref);
|
|
11042
11202
|
return rowCard;
|
|
11043
11203
|
});
|
|
@@ -11057,28 +11217,6 @@ ${calendarAddUrl.toString()}
|
|
|
11057
11217
|
return out;
|
|
11058
11218
|
}
|
|
11059
11219
|
|
|
11060
|
-
/**
|
|
11061
|
-
* 「接続を確認」の結果を、同じリポジトリの兄弟の行(issues / discussions)へそろえる。
|
|
11062
|
-
*
|
|
11063
|
-
* 帯は撤去した(#1233)。残すのは「行は 2 本でも接続は 1 つ」なので押した行と同じ判定に
|
|
11064
|
-
* そろえる仕事だけ。**条件なしで毎回そろえる**(帯の有無・状態の変化に依らない)。
|
|
11065
|
-
* 兄弟は同じ親(一覧・確かめられなかった組織の箱)の直下にいる。
|
|
11066
|
-
*/
|
|
11067
|
-
function syncGithubSiblingRows(card, ref, ok) {
|
|
11068
|
-
var parent = card.parentNode;
|
|
11069
|
-
if (!parent || !ref) return;
|
|
11070
|
-
var gateSrc = card.querySelector(".ds-gate");
|
|
11071
|
-
var sibs = parent.querySelectorAll(":scope > .ds-card[data-ref]");
|
|
11072
|
-
for (var si = 0; gateSrc && si < sibs.length; si++) {
|
|
11073
|
-
var sib = sibs[si];
|
|
11074
|
-
if (sib === card || sib.getAttribute("data-ref") !== ref) continue;
|
|
11075
|
-
var sg = sib.querySelector(".ds-gate");
|
|
11076
|
-
if (sg) { sg.className = gateSrc.className; sg.textContent = gateSrc.textContent; }
|
|
11077
|
-
var sh = sib.querySelectorAll(".ds-gate-help");
|
|
11078
|
-
for (var hi = 0; hi < sh.length; hi++) sh[hi].hidden = ok;
|
|
11079
|
-
}
|
|
11080
|
-
}
|
|
11081
|
-
|
|
11082
11220
|
/** 確かめられなかった組織の案内。**導線は出さない** */
|
|
11083
11221
|
function githubUnsureNodes(g) {
|
|
11084
11222
|
var o = g.meta || {};
|
|
@@ -11109,10 +11247,10 @@ ${calendarAddUrl.toString()}
|
|
|
11109
11247
|
* どの組織かは**行のラベル**が示す(同じチャンネル名が2つの組織に並びうるので、
|
|
11110
11248
|
* ラベル自体は必要)。
|
|
11111
11249
|
*
|
|
11112
|
-
* ##
|
|
11250
|
+
* ## 囲む枠は出さない(c-07)
|
|
11113
11251
|
*
|
|
11114
|
-
*
|
|
11115
|
-
*
|
|
11252
|
+
* 「組織が分かりません」「接続が切れた」の枠は撤去した。困っているのはその行だけなので、
|
|
11253
|
+
* 一手は行の中(slackRowHelpParts・DS_GATE)が持つ。
|
|
11116
11254
|
*/
|
|
11117
11255
|
function slackRows(items, meta) {
|
|
11118
11256
|
var ws = slackWorkspaces();
|
|
@@ -11125,22 +11263,15 @@ ${calendarAddUrl.toString()}
|
|
|
11125
11263
|
// OAuth の戻り先は固定ページ(この画面には戻らない)ので、
|
|
11126
11264
|
// **利用者が操作タブを開き直したこの瞬間**が唯一の合図になる
|
|
11127
11265
|
requestOrgResolve();
|
|
11128
|
-
//
|
|
11129
|
-
//
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
}
|
|
11134
|
-
if (g.key !== "__internal__") {
|
|
11135
|
-
var st = tokenStateOf(ws, g.key);
|
|
11136
|
-
// **接続が切れたときの導線を必ず残す。** それまでは接続カードの中の一覧に
|
|
11137
|
-
// 出していた。カードごと消したので、ここへ移す——移さないと
|
|
11138
|
-
// **接続が切れたことに気づけず、直す手段も画面から消える**
|
|
11139
|
-
if (st === "revoked" || st === "missing") {
|
|
11140
|
-
out.push(orgNoteBox(brokenOrgNodes(g.title, st), cards));
|
|
11141
|
-
return;
|
|
11142
|
-
}
|
|
11266
|
+
// 🔴 **囲む枠は出さない(c-07)。** 判定し直しの結果は、行の前に 1 段(結果が書かれるまで hidden)。
|
|
11267
|
+
// 一手は読めない行の中(slackRowHelpParts)が持つ
|
|
11268
|
+
var resolved = el("p", { class: "ds-group-note ds-org-resolved" });
|
|
11269
|
+
resolved.hidden = true;
|
|
11270
|
+
out.push(resolved);
|
|
11143
11271
|
}
|
|
11272
|
+
// 🔴 **接続が切れた/未接続のワークスペースの枠(brokenOrgNodes)は撤去した(c-07)。**
|
|
11273
|
+
// そのワークスペースの読めていない行が、一手「この Slack を Cortex に接続してください。[接続する]」を
|
|
11274
|
+
// 持つ(slackRowHelpParts と DS_GATE_NO_TOKEN.customer)。入口を失わないための約束は決定メモに書いた
|
|
11144
11275
|
cards.forEach(function (n) { out.push(n); });
|
|
11145
11276
|
});
|
|
11146
11277
|
return out;
|
|
@@ -11161,57 +11292,6 @@ ${calendarAddUrl.toString()}
|
|
|
11161
11292
|
return box;
|
|
11162
11293
|
}
|
|
11163
11294
|
|
|
11164
|
-
/** 「組織不明」の案内。**原因を1つに絞らない** */
|
|
11165
|
-
function unknownOrgNodes() {
|
|
11166
|
-
// **接続だけを勧めると、招待すれば済む人に「直らない処方」を出す。**
|
|
11167
|
-
// 非公開チャンネルは、同じ Slack でも招待前は「存在しない」と返る
|
|
11168
|
-
var out = [];
|
|
11169
|
-
// **「読めませんでした」では、行の「Slackで招待してください」と区別が付かない**
|
|
11170
|
-
//(オーナー指摘・2026-08-20)。どちらも読めていないが、**分かっていることが違う**:
|
|
11171
|
-
// 行に「招待してください」… クラスメソッドのチャンネルだと**分かっている**。招待だけが足りない
|
|
11172
|
-
// この案内 … **どのSlackのものかすら分からない**(どの鍵でも届かなかった)
|
|
11173
|
-
// 状態の名前を「分かりません」に揃える
|
|
11174
|
-
out.push(el("div", { class: "ds-orgnote-title", text: "⚠️ 組織不明のチャンネル" }));
|
|
11175
|
-
out.push(el("p", {
|
|
11176
|
-
class: "ds-group-note",
|
|
11177
|
-
text: "Cortex が持っているどの鍵でも、このチャンネルに届きませんでした。次のどれかです。",
|
|
11178
|
-
}));
|
|
11179
|
-
var ul = el("ul", { class: "ds-group-note" });
|
|
11180
|
-
// **公開との違いをここで言い切る。** 「同じ未招待なのに、なぜ上の行は
|
|
11181
|
-
// 組織が分かっていて、こちらは分からないのか」が読み取れないと、
|
|
11182
|
-
// 利用者は同じ状態が2通りに見えることに戸惑う
|
|
11183
|
-
ul.appendChild(el("li", { text: "非公開チャンネルで、まだ Cortex を招待していない → 下のコマンドを Slack のそのチャンネルに貼ってください" }));
|
|
11184
|
-
ul.appendChild(el("li", { text: "お客様の Slack にあり、まだつながっていない → 下のボタンから接続します" }));
|
|
11185
|
-
ul.appendChild(el("li", { text: "チャンネルがアーカイブ/削除された、URLが違う → 「登録を解除」を押してください" }));
|
|
11186
|
-
out.push(ul);
|
|
11187
|
-
out.push(copyRow("/invite @Cortex"));
|
|
11188
|
-
out.push(slackConnectButton());
|
|
11189
|
-
// 判定し直しの結果を出す場所(何も起きなければ空のまま)
|
|
11190
|
-
out.push(el("p", { class: "ds-group-note ds-org-resolved" }));
|
|
11191
|
-
return out;
|
|
11192
|
-
}
|
|
11193
|
-
|
|
11194
|
-
/** 接続が切れた/未接続のワークスペースの案内 */
|
|
11195
|
-
function brokenOrgNodes(title, state) {
|
|
11196
|
-
var out = [];
|
|
11197
|
-
out.push(el("div", {
|
|
11198
|
-
class: "ds-orgnote-title",
|
|
11199
|
-
text: state === "revoked" ? "⚠️ " + title + " との接続が切れています" : "⚠️ " + title + " はまだ接続されていません",
|
|
11200
|
-
}));
|
|
11201
|
-
out.push(el("p", {
|
|
11202
|
-
class: "ds-group-note",
|
|
11203
|
-
// **revoked と missing を分ける。** 前者は「接続し直して」、後者は「まだ完了していない」で
|
|
11204
|
-
// 次の一手が違う。unknown には何も出さない——繋がっているのに
|
|
11205
|
-
// 「接続し直して」と言う方が、黙っているより悪い
|
|
11206
|
-
text: state === "revoked"
|
|
11207
|
-
? "Slack 側で Cortex のアプリが削除されたか、接続が無効になっています。もう一度接続してください。"
|
|
11208
|
-
: "このワークスペースのチャンネルが登録されていますが、接続が見つかりません。もう一度接続してください。",
|
|
11209
|
-
}));
|
|
11210
|
-
out.push(slackConnectButton());
|
|
11211
|
-
return out;
|
|
11212
|
-
}
|
|
11213
|
-
|
|
11214
|
-
|
|
11215
11295
|
function dsFmtTime(iso) {
|
|
11216
11296
|
var d = new Date(iso);
|
|
11217
11297
|
if (isNaN(d.getTime())) return "";
|
|
@@ -11235,6 +11315,15 @@ ${calendarAddUrl.toString()}
|
|
|
11235
11315
|
if (min < 60 * 24) return Math.floor(min / 60) + "時間前";
|
|
11236
11316
|
return dsFmtTime(iso);
|
|
11237
11317
|
}
|
|
11318
|
+
/**
|
|
11319
|
+
* 「◯分前に確認」の語。**「たった今」だけは「たった今確認」**(「たった今に確認」は日本語として崩れる)。
|
|
11320
|
+
* 読めない値は空文字(呼び側が出し分けを切る)。行・タイル・押した直後の行は全部これを通す
|
|
11321
|
+
*/
|
|
11322
|
+
function agoConfirmedText(iso) {
|
|
11323
|
+
var ago = rtAgo(iso);
|
|
11324
|
+
if (!ago) return "";
|
|
11325
|
+
return ago === "たった今" ? "たった今確認" : ago + "に確認";
|
|
11326
|
+
}
|
|
11238
11327
|
// 名前表示: url があれば新しいタブで正本を開くリンクにする
|
|
11239
11328
|
function dsNameEl(text, url) {
|
|
11240
11329
|
if (url) return el("a", { class: "ds-name", href: url, target: "_blank", rel: "noopener", text: text });
|
|
@@ -11755,8 +11844,8 @@ ${calendarAddUrl.toString()}
|
|
|
11755
11844
|
var v = derivePendingTile(regKey, live, LIVE_STATE);
|
|
11756
11845
|
if (!v) return null;
|
|
11757
11846
|
if (v.kind === "ok") {
|
|
11758
|
-
var ago =
|
|
11759
|
-
return { text: CAP_STATE_MARK.ok + "接続OK" + (ago ? " " + ago
|
|
11847
|
+
var ago = agoConfirmedText(v.at);
|
|
11848
|
+
return { text: CAP_STATE_MARK.ok + "接続OK" + (ago ? " " + ago : ""), cls: "ds-gate-ok" };
|
|
11760
11849
|
}
|
|
11761
11850
|
var first = v.rows[0];
|
|
11762
11851
|
var gate;
|
|
@@ -12427,7 +12516,25 @@ ${calendarAddUrl.toString()}
|
|
|
12427
12516
|
var chatScope = adapter === "slack"
|
|
12428
12517
|
? ""
|
|
12429
12518
|
: " Cortex のアプリは、会話の読み取りと、通知先に設定したスペースへの確認・通知の投稿だけに使われます。読み取った会話は、本文そのものを保存するのではなく、決定事項・用語などの抽出結果としてプロジェクトの記録に反映されます。";
|
|
12430
|
-
|
|
12519
|
+
// 🔴 **追加の欄から外した前提の説明は、ここに 1 回だけ足す(c-07)。** 説明文は 1 段のまま、文だけ足す:
|
|
12520
|
+
// - Slack … お客様の Slack は、その Slack の管理者がワークスペースの接続を承認すると読める
|
|
12521
|
+
// (承認できる人と渡す権限。以前は常設の接続ボタンの下の説明段落が持っていた)
|
|
12522
|
+
// - Google Chat … DM(1 対 1)は対象外(以前は追加の欄の手順 3 が持っていた)
|
|
12523
|
+
// - 混載の 1 枚タイル(アダプタ不明・どちらのフォームも並ぶ)は両方の文を持つ
|
|
12524
|
+
var chatExtra = (adapter !== "google-chat"
|
|
12525
|
+
? " お客様の Slack のチャンネルは、その Slack の管理者がワークスペースの接続を承認すると読めるようになります(チャンネルを読む権限と、通知を投稿する権限を渡します)。"
|
|
12526
|
+
: "")
|
|
12527
|
+
+ (adapter !== "slack" ? " DM(1対1のチャット)は対象外です。" : "");
|
|
12528
|
+
m.modal.appendChild(el("p", { class: "modal-desc", text: "ここに並んでいる" + chatNoun + "は、例外なく全て毎晩の Gold 昇格が読み取り、Decision・用語集の材料になります。読み取りを止めるには「登録を解除」してください。" + chatScope + chatExtra }));
|
|
12529
|
+
} else if (cap === "デザイン" && (!adapter || adapter === "figma")) {
|
|
12530
|
+
// 🔴 **Figma の説明文(c-07・新設)。** 追加の欄の手順 4(何が同期されるか)と手順 1 の前提
|
|
12531
|
+
// (トークンの登録)を、ここに 1 回だけ置く。鍵の欄は 0 件のあいだ畳まれているので、入れる欄が
|
|
12532
|
+
// 出ること(ファイルを足すと出る)も 1 句で言う。発行の手順そのものは鍵の欄(正本)が持つ
|
|
12533
|
+
m.modal.appendChild(el("p", { class: "modal-desc", text: "ここに並んでいる Figma ファイルの画面名とコメントを、Figma へのリンクつきで毎晩同期します(画像は取り込まれません)。あらかじめ Figma のトークンの登録が要ります(ファイルを足すと入れる欄が出ます)。やめるには「このファイルを外す」を押してください。" }));
|
|
12534
|
+
} else if (cap === "共有資料" && (!adapter || adapter === "google-drive")) {
|
|
12535
|
+
// 🔴 **Google Drive 専用の説明文(c-07・新設)。** SharePoint 等の別のアダプタの窓には出さない
|
|
12536
|
+
// (Markdown 化の約束は Drive の取り込みの話)。追加の欄の手順 3 が持っていた文
|
|
12537
|
+
m.modal.appendChild(el("p", { class: "modal-desc", text: "ここに並んでいるフォルダの中身を、毎晩 共有資料 にコピーして Markdown 化します。やめるには「このフォルダを外す」を押してください。" }));
|
|
12431
12538
|
} else if (cap === "開発") {
|
|
12432
12539
|
// 🔴 **開発の開示文は「記録に使う・決定の抽出には使わない」(#660)。** 2026-09-18 の
|
|
12433
12540
|
// オーナー決定でソースの性質は種類で固定になり、GitHub は「作業の記録」に固定された。
|
|
@@ -12467,11 +12574,23 @@ ${calendarAddUrl.toString()}
|
|
|
12467
12574
|
? ""
|
|
12468
12575
|
: (CAP_STATE_TEXT[dNow] || "状態が判定できません") + "(" + detailNow + ")";
|
|
12469
12576
|
}
|
|
12470
|
-
|
|
12471
|
-
//
|
|
12472
|
-
//
|
|
12473
|
-
|
|
12474
|
-
|
|
12577
|
+
// 🔴 **Figma・Drive の「未接続(…が登録されていません)」は作らない(c-07)。** 0 件のとき、
|
|
12578
|
+
// 同じ窓に一覧の ds-empty「…はまだ登録されていません。」が出ていて二重だった。しかも一覧は
|
|
12579
|
+
// liveList で追加に追随するが、この一文は開いた時点の値なので、1 件足すと「未接続」が足した行の
|
|
12580
|
+
// 上に残る。**一覧の 1 行だけ**を残す。off・broken の一文は残す(Backlog・Slack・GitHub も触らない)。
|
|
12581
|
+
// 🔴 **「登録されていません」と言うだけの一文だけを落とす。** 「雛形のプレースホルダです」のように、
|
|
12582
|
+
// 一覧の 1 行が言わない手がかりを運ぶ一文は残す(なぜ未接続扱いなのかが読めなくなる)
|
|
12583
|
+
var unsetDup = noteIsUnset
|
|
12584
|
+
&& /登録されていません/.test(noteText)
|
|
12585
|
+
&& ((cap === "デザイン" && (!adapter || adapter === "figma"))
|
|
12586
|
+
|| (cap === "共有資料" && (!adapter || adapter === "google-drive")));
|
|
12587
|
+
if (!unsetDup) {
|
|
12588
|
+
var noteEl = el("p", { class: "modal-desc", text: noteText });
|
|
12589
|
+
// **消さずに hidden で伏せる。** 節点を残しておかないと、この一文を探している
|
|
12590
|
+
// 検査が「文言が変わった」と「箱ごと無くなった」を見分けられない
|
|
12591
|
+
noteEl.hidden = noteText === "";
|
|
12592
|
+
m.modal.appendChild(noteEl);
|
|
12593
|
+
}
|
|
12475
12594
|
}
|
|
12476
12595
|
if (!items.length) {
|
|
12477
12596
|
m.modal.appendChild(el("p", { class: "ds-empty", text: "この能力にはまだ設定できるものがありません。" }));
|
|
@@ -12934,45 +13053,25 @@ ${calendarAddUrl.toString()}
|
|
|
12934
13053
|
// 0件なら繋ぐ相手もまだ無いので、入口が要る場面にならない。
|
|
12935
13054
|
pushCap("チャット", adders.querySelector('[data-adder="slack"]'), "slack");
|
|
12936
13055
|
/* -------------------------------------------------------------------------
|
|
12937
|
-
* 🔴
|
|
13056
|
+
* 🔴 接続の入口は、必要になった行の一手の中にだけある(c-07)
|
|
12938
13057
|
* -------------------------------------------------------------------------
|
|
12939
|
-
*
|
|
12940
|
-
*
|
|
12941
|
-
*
|
|
12942
|
-
*
|
|
12943
|
-
*
|
|
12944
|
-
*
|
|
12945
|
-
*
|
|
12946
|
-
*
|
|
12947
|
-
*
|
|
12948
|
-
*
|
|
12949
|
-
*
|
|
12950
|
-
*
|
|
12951
|
-
*
|
|
12952
|
-
* **お客様の Slack かどうかは、行の状態から決まらない。** だから入口は
|
|
12953
|
-
* 行の状態と無関係に置く——**組織不明の組が1つも無くても出る**。
|
|
12954
|
-
*
|
|
12955
|
-
* ⚠ **「組織不明」の案内の中のボタンは残す。** あの文脈では、直前の箇条書きが
|
|
12956
|
-
* 「なぜ接続するのか」を言っており、次の一手として正しい。同じ関数を2箇所から
|
|
12957
|
-
* 呼ぶだけで、押したときの動きは1つ(承認の口も1つ)。
|
|
12958
|
-
*
|
|
12959
|
-
* **置き場所は追加フォームの後。** フォームの手順3が「組織不明と出たら…接続する」と
|
|
12960
|
-
* 言っているので、フォームより前に出すと読む順と操作の順が食い違う。
|
|
12961
|
-
*
|
|
12962
|
-
* **投入の口が無い構成では出さない。** 承認の開始は intake Lambda を叩くので、
|
|
12963
|
-
* 無い案件では押しても始まらない(renderExternalAdders も同じ条件で空を返す)。
|
|
13058
|
+
* 以前は[Slack ワークスペースに接続する]を追加の欄の後ろに常設していた(0.12.2・
|
|
13059
|
+
* 印が付かない経路で登録された行に道が無かったため)。**常設は撤去した**——どの行の話かが読めず、
|
|
13060
|
+
* 「先に読ませる画面」になっていた(オーナーの違和感・#1233 と同じ)。
|
|
13061
|
+
* 入口を失わないための約束(決定メモ 20261010-1328):
|
|
13062
|
+
* - 顧客の Slack を足した直後、サーバが鍵で実測して組織を決める(応答の pendingOrg)。
|
|
13063
|
+
* どの鍵でも届かなければ orgUnknown が付き、**その行が[接続する]を持つ**(slackRowHelpParts)
|
|
13064
|
+
* - 台帳の接続が切れている/未接続のワークスペースの読めていない行は、全部その一手を持つ
|
|
13065
|
+
* - 社内の読めていない行も持つ(Slack コネクトの共有チャンネルが社内に分類された実例)。
|
|
13066
|
+
* 社内の no_token だけは持たない(2026-08-18 の事故)
|
|
13067
|
+
* - 投入の口(SITE.intake)が無い案件は、押せないので一手ごと出さない
|
|
13068
|
+
* - 割り切り: 足した行が**まだ測られていない間**は、どの窓にも一手が出ない
|
|
13069
|
+
* ([接続を確認]の結果に一手が付く)
|
|
12964
13070
|
* ----------------------------------------------------------------------- */
|
|
12965
|
-
if (SITE.intake) {
|
|
12966
|
-
// "slack" 札は #153 の合流で付けた——無いと Google Chat の箱にも OAuth ボタンが出る
|
|
12967
|
-
//(Google Chat の承認は Admin install で、押す先の画面が無い)。常設の意図は Slack の箱の中で保つ
|
|
12968
|
-
pushCap("チャット", slackConnectButton(
|
|
12969
|
-
"お客様の Slack や、Slack コネクトで共有されたチャンネルを読むには、先にワークスペースの接続が要ります。",
|
|
12970
|
-
), "slack");
|
|
12971
|
-
}
|
|
12972
13071
|
// Google Chat のフォーム(#153)。接続(OAuth)のボタンは存在しない——顧客の
|
|
12973
13072
|
// Workspace 管理者による Admin install が承認そのもので、画面に押す先が無い。
|
|
12974
|
-
//
|
|
12975
|
-
//
|
|
13073
|
+
// アプリ追加の操作列(画像つき)と管理者の承認は、追加の欄の手順ではなく、**そのスペースの
|
|
13074
|
+
// 行の一手**(DS_GATE.not_in_space の details)が持つ(c-07)
|
|
12976
13075
|
pushCap("チャット", adders.querySelector('[data-adder="google-chat"]'), "google-chat");
|
|
12977
13076
|
// **組織ごとの接続状況は、行と一体にした(2026-08-20・Slack からの横展開)。**
|
|
12978
13077
|
//
|
|
@@ -13796,34 +13895,26 @@ ${calendarAddUrl.toString()}
|
|
|
13796
13895
|
* DS_GATE_NO_TOKEN が持っていて、どちらも dsGateOf を通して取る。ここで文面を
|
|
13797
13896
|
* 書き写すと、**同じ行の状態バッジと確認結果で語が割れる**(この節で3回直した形)。
|
|
13798
13897
|
*
|
|
13898
|
+
* **結果の描画は行の関数 1 本(cortex-engine #1328)。** 押した結果は applyProbeResult が
|
|
13899
|
+
* ストアの行と同じ形で LIVE_STATE に置き、行を描き直す。押下の処理は札・時刻・説明文を
|
|
13900
|
+
* 自分で描かない(以前の probeHelpNodes / probeVerdict は撤去した。開き直した行と形が割れ、
|
|
13901
|
+
* 押した直後に 2 回見た目が変わっていた)。
|
|
13902
|
+
*
|
|
13799
13903
|
* 他アダプタ(Backlog / Figma / Drive)を足すときの拡張点:
|
|
13800
13904
|
* - 判定と語彙は infra/lambda/shared/slack-gate.mjs 側に足す(画面は DS_GATE のまま)
|
|
13801
|
-
* -
|
|
13802
|
-
*
|
|
13803
|
-
*
|
|
13905
|
+
* - **次の一手は DS_GATE の help(行の常時表示と同じ表)に足す。**この節に判定の分岐を作らない
|
|
13906
|
+
* - 送る種別(probeTypeOf)・ストアの能力名(probeCapOfType)と、行に出す条件
|
|
13907
|
+
* (下の extSourceCard)に足す
|
|
13804
13908
|
*
|
|
13805
13909
|
* **開発(GitHub)は #234 で足した。** 判定は shared/github-gate.mjs、次の一手は
|
|
13806
13910
|
* サーバの needed(理由と設定ページのURLを1文で持つ)をそのまま出している
|
|
13807
13911
|
* ——画面に分岐が生まれないよう、言い分けを全部あちらに置いた
|
|
13808
13912
|
*
|
|
13809
13913
|
* **Google Chat は #347 で足した。** 判定は shared/google-chat-gate.mjs で、夜間の実測と
|
|
13810
|
-
*
|
|
13914
|
+
* 同じ叩き先・同じスコープで測る。次の一手は行の常時表示と
|
|
13811
13915
|
* 同じ表(DS_GATE の help)から引くだけで、画面に判定の分岐は無い
|
|
13812
13916
|
* ------------------------------------------------------------------------- */
|
|
13813
13917
|
|
|
13814
|
-
/**
|
|
13815
|
-
* 確認結果の状態バッジ。**既存の dsGateOf をそのまま通す。**
|
|
13816
|
-
*
|
|
13817
|
-
* こうしておくと no_token の社内/顧客の出し分け(DS_GATE_NO_TOKEN)が確認結果にも
|
|
13818
|
-
* そのまま効く。写経すると、同じ画面で行は「管理者の設定が必要です」・確認結果は
|
|
13819
|
-
* 「トークン未設定」になり、社内チャンネルを登録した人が**また**顧客ワークスペースの
|
|
13820
|
-
* 接続へ吸い込まれる(2026-08-18 の不具合そのもの)。
|
|
13821
|
-
*/
|
|
13822
|
-
function probeVerdict(s, r) {
|
|
13823
|
-
// reason は GitHub のテナント外の断り(#841)。無ければ従来どおり
|
|
13824
|
-
return dsGateOf({ type: s.type, workspace: s.workspace, gate: r.gate, reason: r.reason });
|
|
13825
|
-
}
|
|
13826
|
-
|
|
13827
13918
|
/**
|
|
13828
13919
|
* 確認したいアダプタの種別(「op=probe」 の 「type」)。**画面の種別をそのまま送らない**
|
|
13829
13920
|
* ——「github-issues」 / 「github-discussions」 は同じ1つのリポジトリの読み取りで、
|
|
@@ -13861,172 +13952,6 @@ ${calendarAddUrl.toString()}
|
|
|
13861
13952
|
return p;
|
|
13862
13953
|
}
|
|
13863
13954
|
|
|
13864
|
-
/**
|
|
13865
|
-
* 開発(GitHub)の確認結果の本文(#233 / #234)。
|
|
13866
|
-
*
|
|
13867
|
-
* **理由と対処はサーバが1文で持っている**(「shared/github-gate.mjs」 の 「needed」)。
|
|
13868
|
-
* 「App が入っていない」と「App は入っているがこのリポジトリが選ばれていない」の
|
|
13869
|
-
* 言い分けも、設定ページの URL もあちらが決める——**画面で分岐を書き足さない**
|
|
13870
|
-
* (書いた瞬間に判定が2箇所になり、夜間の実測とボタンでずれる)。
|
|
13871
|
-
* **ただし状態に応じた定型の1文だけは画面の表(DS_GATE_RESTING_HELP の probed)から引く**
|
|
13872
|
-
* (#346 → #356)——「request は組織オーナーの承認待ち」のような GitHub 側の意味は、
|
|
13873
|
-
* サーバの2つの書き手が別々に文を作るので、片方だけ古くなる。
|
|
13874
|
-
*
|
|
13875
|
-
* 🔴 **行の常時表示(resting)を押した結果に繰り返さない(#356)。** 0.12.22 では admin の
|
|
13876
|
-
* 4文が行と押した結果の両方に出ていた。行の1文は押した瞬間に隠れ、needed が同じ操作
|
|
13877
|
-
* (Configure から追加)を宛先つきで言うので、ここは needed が言わない1文だけ
|
|
13878
|
-
*/
|
|
13879
|
-
function githubProbeHelpNodes(r) {
|
|
13880
|
-
if (r.gate === "ok") return [];
|
|
13881
|
-
if (r.needed) {
|
|
13882
|
-
var nodes = [neededNode(r.needed)];
|
|
13883
|
-
// 状態に応じた1文は**行と同じ表から引く**(ここに文を直書きすると表と割れる)
|
|
13884
|
-
var probed = probedHelpPartsOf("github", r.gate);
|
|
13885
|
-
if (probed) nodes.push(restingHelpNode(probed, "ds-probe-help"));
|
|
13886
|
-
return nodes;
|
|
13887
|
-
}
|
|
13888
|
-
// needed が無いのは gate に落とし込めなかったとき。**生のエラーは隠さない**
|
|
13889
|
-
return [el("p", { class: "ds-probe-help", text: "GitHub の応答:" + (r.error || "不明") + "。時間をおいて再度お試しください。" })];
|
|
13890
|
-
}
|
|
13891
|
-
|
|
13892
|
-
/**
|
|
13893
|
-
* Google Chat の確認結果の本文(#347)。
|
|
13894
|
-
*
|
|
13895
|
-
* **判定は infra/lambda/shared/google-chat-gate.mjs にしか無い。** ここが返すのは
|
|
13896
|
-
* 「次の一手」だけで、状態の語(バッジ)は probeVerdict が dsGateOf から取る。
|
|
13897
|
-
*
|
|
13898
|
-
* **文を書き写さない。** 「アプリと統合から追加してください」「管理者の設定が済むと…」は
|
|
13899
|
-
* 行の常時表示(DS_GATE の 「help」)が既に持っている——写経すると、同じ行の常時表示と
|
|
13900
|
-
* 押した結果で語が割れる(この節が何度も直してきた形)。DS_GATE から引いて1文だけ出す。
|
|
13901
|
-
*
|
|
13902
|
-
* ⚠ **403(Workspace 管理者の承認待ち)は #521 で「admin_approval_pending」に分類済み。**
|
|
13903
|
-
* 機械語(「permission_denied」)はもう出さない。**「時間をおいて」とも言わない**
|
|
13904
|
-
* ——待っても直らない(管理者が承認するまで同じ応答が返る)。401 / 429 は依然
|
|
13905
|
-
* Phase 0 未採取で「unknown」のまま、サーバの機械語をそのまま出す。
|
|
13906
|
-
*/
|
|
13907
|
-
function googleChatProbeHelpNodes(s, r) {
|
|
13908
|
-
// 成功。**1行で終わり**(状態の語が既に「接続OK」と出ている)
|
|
13909
|
-
if (r.gate === "ok") return [];
|
|
13910
|
-
// not_in_space / no_credentials / admin_approval_pending は行の常時表示と同じ文面
|
|
13911
|
-
// (DS_GATE から引く。依頼文の details も gateHelpNodes 経由で同じものが出る)。
|
|
13912
|
-
// 押した瞬間に行側の 「.ds-gate-help」 は隠れるので、二重には出ない
|
|
13913
|
-
var gate = dsGateOf({ type: s.type, gate: r.gate });
|
|
13914
|
-
var nodes = gateHelpNodes(gate, "ds-probe-help");
|
|
13915
|
-
if (nodes.length) return nodes;
|
|
13916
|
-
var p = function (t) { return el("p", { class: "ds-probe-help", text: t }); };
|
|
13917
|
-
if (r.gate === "unreachable") {
|
|
13918
|
-
// 帯(「アクセス不可」)が症状を言っている。**ここは一手だけ**
|
|
13919
|
-
return [p("時間をおいて、もう一度「接続を確認」を押してください。")];
|
|
13920
|
-
}
|
|
13921
|
-
// unknown。**生の機械語を隠さない**——「不明」だけだと切り分けが始められない
|
|
13922
|
-
return [p("Google Chat の応答:" + (r.error || "不明") + "。cortex の担当者にこの語をお伝えください。")];
|
|
13923
|
-
}
|
|
13924
|
-
|
|
13925
|
-
/**
|
|
13926
|
-
* 「アクセス不可」の次の一手(0.12.2・実オンボーディングで踏んだ)。
|
|
13927
|
-
*
|
|
13928
|
-
* ## なぜ2つの導線を併記するのか
|
|
13929
|
-
*
|
|
13930
|
-
* それまでは「見つからないか、アーカイブされています。不要なら登録を解除」だけを
|
|
13931
|
-
* 出していた。**この行がまさに、まだ読めていない主役の行**なのに、
|
|
13932
|
-
* 生きているチャンネルを読めるようにする道が1本も書かれていなかった。
|
|
13933
|
-
*
|
|
13934
|
-
* 原因は**行の分類では絞れない**:
|
|
13935
|
-
*
|
|
13936
|
-
* - 非公開チャンネルは、招待されるまで「存在しない」と返る(招待で直る)
|
|
13937
|
-
* - Slack コネクトの共有チャンネルは、**URL がどちらの組織のドメインにもなりうる**。
|
|
13938
|
-
* だから「クラスメソッド」に分類された行の正しい対処が
|
|
13939
|
-
* **ワークスペース接続(OAuth)** のこともある
|
|
13940
|
-
* (実測: 招待しようとしたら「組織外のユーザー」で断られた)
|
|
13941
|
-
*
|
|
13942
|
-
* **どちらかに賭けて片方だけ出すと、外したほうの人は詰まる。** 招待だけを出すと
|
|
13943
|
-
* 何度招待しても直らないものを繰り返させ、接続だけを出すと招待で済む人に
|
|
13944
|
-
* 「直らない処方」を渡す。**両方出して、読む人に選ばせる**のが正しい
|
|
13945
|
-
* (組織不明の案内が同じ判断をしている)。
|
|
13946
|
-
*
|
|
13947
|
-
* ## 社内/顧客で出し分けない
|
|
13948
|
-
*
|
|
13949
|
-
* no_token は出し分けている(社内は画面から設定できるものが本当に無い)が、
|
|
13950
|
-
* こちらは**分類そのものが当てにならない**のが問題の本体なので、
|
|
13951
|
-
* 同じ理屈を持ち込むと直したい誤読を画面の側から作り直すことになる。
|
|
13952
|
-
*/
|
|
13953
|
-
function slackUnreachableHelpNodes() {
|
|
13954
|
-
var out = [];
|
|
13955
|
-
out.push(el("p", { class: "ds-probe-help", text: "Cortex からこのチャンネルが見えませんでした。次のどれかです。" }));
|
|
13956
|
-
var ul = el("ul", { class: "ds-probe-help ds-probe-why" });
|
|
13957
|
-
// **押したあと何をするかまで書く。** 直したあと表示が変わらないと「効かなかった」と
|
|
13958
|
-
// 読まれる——この画面の一覧は夜間のスナップショットなので、その場で確かめる手段は
|
|
13959
|
-
// 「接続を確認」をもう一度押すこと以外に無い
|
|
13960
|
-
ul.appendChild(el("li", {
|
|
13961
|
-
text: "非公開チャンネル … 下のコマンドをそのチャンネルに貼って Cortex を招待してから、もう一度「接続を確認」を押してください",
|
|
13962
|
-
}));
|
|
13963
|
-
ul.appendChild(el("li", {
|
|
13964
|
-
text: "お客様の Slack、または Slack コネクトで共有されたチャンネル … "
|
|
13965
|
-
+ "下の「Slack ワークスペースに接続する」から、そのワークスペースに Cortex を追加するリクエストを送ってください。"
|
|
13966
|
-
+ "接続できたら、もう一度「接続を確認」を押してください",
|
|
13967
|
-
}));
|
|
13968
|
-
ul.appendChild(el("li", {
|
|
13969
|
-
text: "アーカイブ・削除された、URL が違う … 「登録を解除」を押してください",
|
|
13970
|
-
}));
|
|
13971
|
-
out.push(ul);
|
|
13972
|
-
// **手で打たせない**(copyRow のコメント)。招待の候補を出したなら、
|
|
13973
|
-
// そのコマンドも同じ場所に無いと、貼る文字列を探しに行くことになる
|
|
13974
|
-
out.push(copyRow("/invite @Cortex"));
|
|
13975
|
-
return out;
|
|
13976
|
-
}
|
|
13977
|
-
|
|
13978
|
-
/**
|
|
13979
|
-
* 判定ごとの表示。**成功は1行で終わらせ、失敗は「理由+次の一手」だけを残す。**
|
|
13980
|
-
*
|
|
13981
|
-
* ## 短くした理由(2026-08-19・オーナー指示)
|
|
13982
|
-
*
|
|
13983
|
-
* 「接続を確認を押して出てくる文言が長ったらしい」。実際、成功時に4行出ていた。
|
|
13984
|
-
* **成功時は「読めている」以上の情報が要らない。**
|
|
13985
|
-
*
|
|
13986
|
-
* ## ただし失敗時は削りすぎない
|
|
13987
|
-
*
|
|
13988
|
-
* 短くしすぎると、今日と同じ「画面を見ても次に何をすればいいか決まらない」状態に戻る
|
|
13989
|
-
* (それで半日かかった)。落とすのは**内部の仕組みの説明**——「設定ファイルの表示名だけが
|
|
13990
|
-
* 書き換わります」「読み取りの対象・範囲は変わりません」のような、読む人の次の行動を
|
|
13991
|
-
* 変えない文。残すのは「何が起きているか」と「次に何をするか」だけ。
|
|
13992
|
-
*
|
|
13993
|
-
* 状態の語そのものは DS_GATE / DS_GATE_NO_TOKEN が持つ(probeVerdict 経由)ので、
|
|
13994
|
-
* ここが返すのは**それに足りない分だけ**。二重に言わない。
|
|
13995
|
-
*
|
|
13996
|
-
* @returns 本文に並べるノード(0〜2個)
|
|
13997
|
-
*/
|
|
13998
|
-
function probeHelpNodes(s, r) {
|
|
13999
|
-
var p = function (t) { return el("p", { class: "ds-probe-help", text: t }); };
|
|
14000
|
-
if (probeTypeOf(s.type) === "github") return githubProbeHelpNodes(r);
|
|
14001
|
-
if (probeTypeOf(s.type) === "google-chat") return googleChatProbeHelpNodes(s, r);
|
|
14002
|
-
// 成功。**1行で終わり。** 状態の語(「接続OK」)が既に出ているので本文は空
|
|
14003
|
-
if (r.gate === "ok") return [];
|
|
14004
|
-
if (r.gate === "not_in_channel") {
|
|
14005
|
-
// 状態の語が「Slackで招待してください」なので、説明は足さずコマンドだけ出す。
|
|
14006
|
-
// **手で打たせない**——打ち間違いは黙って失敗し、「招待したのに読まれない」に見える
|
|
14007
|
-
return [copyRow("/invite @Cortex")];
|
|
14008
|
-
}
|
|
14009
|
-
if (r.gate === "missing_scope") {
|
|
14010
|
-
// 不足スコープは頭のバッジ横に出る(probeSection)。ここは次の一手だけ
|
|
14011
|
-
return [p("招待では直りません。cortex の担当者にこのスコープ名をお伝えください。")];
|
|
14012
|
-
}
|
|
14013
|
-
if (r.gate === "no_token") {
|
|
14014
|
-
// **社内/顧客の出し分けは変えない。** 社内は画面から設定できるものが無いので
|
|
14015
|
-
// 連絡先、顧客は接続へ誘導する(2026-08-18 の不具合の再発防止)。
|
|
14016
|
-
// 長い説明は落とし、次の行動の1行だけ残す
|
|
14017
|
-
return [p(isInternalSlack(s)
|
|
14018
|
-
? "cortex の担当者にご連絡ください。"
|
|
14019
|
-
: "「Slack ワークスペースに接続する」から接続してください。")];
|
|
14020
|
-
}
|
|
14021
|
-
if (r.gate === "unreachable") {
|
|
14022
|
-
// **ここだけ本文が2つ以上になる(0.12.2)。** 原因が3つあり、しかも
|
|
14023
|
-
// 行の分類では絞れないので、候補と導線を並べる(関数側に理由がある)
|
|
14024
|
-
return slackUnreachableHelpNodes();
|
|
14025
|
-
}
|
|
14026
|
-
// unknown。**生のエラーは隠さない**——「不明」だけだと切り分けが始められない
|
|
14027
|
-
return [p("Slack の応答:" + (r.error || "不明") + "。時間をおいて再度お試しください。")];
|
|
14028
|
-
}
|
|
14029
|
-
|
|
14030
13955
|
/**
|
|
14031
13956
|
* 表示名を Slack の実名へ**自動で揃える**(2026-08-19・オーナー判断)。
|
|
14032
13957
|
*
|
|
@@ -14069,6 +13994,9 @@ ${calendarAddUrl.toString()}
|
|
|
14069
13994
|
// 一覧は夜間のスナップショットなので、その場では変わらない。行だけ追いつかせる
|
|
14070
13995
|
var nameEl = card.querySelector(".ds-name");
|
|
14071
13996
|
if (nameEl) nameEl.textContent = slackDisplayName(r.name);
|
|
13997
|
+
// 押した結果で行が描き直されていると、上の card は切り離されている。仮置き(notePendingOp)から描き直す
|
|
13998
|
+
repaintOpenLists();
|
|
13999
|
+
refreshDataSources();
|
|
14072
14000
|
}).catch(function () { /* 揃えられなくても疎通確認の結果は出したまま */ });
|
|
14073
14001
|
}
|
|
14074
14002
|
|
|
@@ -14095,32 +14023,25 @@ ${calendarAddUrl.toString()}
|
|
|
14095
14023
|
*
|
|
14096
14024
|
* @returns { btn, detail } btn は行に、detail は行の下に置く
|
|
14097
14025
|
*/
|
|
14098
|
-
function probeSection(s, card
|
|
14026
|
+
function probeSection(s, card) {
|
|
14099
14027
|
var btn = el("button", { class: "ds-toggle-btn", type: "button", text: "接続を確認" });
|
|
14100
14028
|
var wrap = el("div", { class: "ds-probe" });
|
|
14101
14029
|
var head = el("div", { class: "ds-probe-head" });
|
|
14030
|
+
// 失敗の 1 文だけをここへ出す。**結果(判定・時刻・次の一手)は行そのものが持つ**
|
|
14102
14031
|
var msg = el("span", { class: "ds-toggle-msg" });
|
|
14103
|
-
var at = el("span", { class: "ds-probe-at" });
|
|
14104
|
-
var body = el("div");
|
|
14105
14032
|
head.appendChild(msg);
|
|
14106
|
-
head.appendChild(at);
|
|
14107
14033
|
wrap.appendChild(head);
|
|
14108
|
-
wrap.appendChild(body);
|
|
14109
14034
|
|
|
14110
14035
|
btn.addEventListener("click", async function () {
|
|
14111
14036
|
var intake = SITE.intake;
|
|
14112
14037
|
if (!intake) return;
|
|
14113
|
-
//
|
|
14114
|
-
//
|
|
14038
|
+
// 押している間は**ボタンだけ**が「確認中…」になる(#222・beginBusy の項)。
|
|
14039
|
+
// 🔴 行の中身は変えない——ここで札・時刻・説明文を別の形で描くと、結果が出たあとの
|
|
14040
|
+
// 行(開き直したときと同じ形)と 2 回見た目が変わる(cortex-engine #1328 のちらつき)
|
|
14115
14041
|
var endBusy = beginBusy(btn, "確認中…");
|
|
14116
|
-
|
|
14117
|
-
// それまでは中身が空でも点線だけが全行に出ており、**何も意味していなかった**。
|
|
14118
|
-
// 押した結果があるときだけ、行と結果を分ける線になる
|
|
14119
|
-
wrap.className = "ds-probe is-shown";
|
|
14042
|
+
wrap.className = "ds-probe";
|
|
14120
14043
|
msg.className = "ds-toggle-msg";
|
|
14121
|
-
msg.textContent = "
|
|
14122
|
-
at.textContent = "";
|
|
14123
|
-
body.textContent = "";
|
|
14044
|
+
msg.textContent = "";
|
|
14124
14045
|
// **種別はサーバの語彙に畳む**(github-issues / github-discussions → github)。
|
|
14125
14046
|
// ワークスペースは Slack にしか無い概念なので、他アダプタでは載せない
|
|
14126
14047
|
var payload = { type: probeTypeOf(s.type), ref: s.ref };
|
|
@@ -14130,69 +14051,31 @@ ${calendarAddUrl.toString()}
|
|
|
14130
14051
|
var j = await res.json().catch(function () { return {}; });
|
|
14131
14052
|
if (!res.ok) {
|
|
14132
14053
|
// サーバの文言をそのまま出す(回数制限の案内・未対応のアダプタの説明を含んでいる)
|
|
14054
|
+
wrap.className = "ds-probe is-shown";
|
|
14133
14055
|
msg.className = "ds-toggle-msg is-error";
|
|
14134
14056
|
msg.textContent = "✗ " + (j.message || "確認できませんでした。");
|
|
14135
14057
|
endBusy();
|
|
14136
14058
|
return;
|
|
14137
14059
|
}
|
|
14138
|
-
msg.className = "ds-toggle-msg" + (j.gate === "ok" ? " is-ok" : " is-error");
|
|
14139
|
-
msg.textContent = j.gate === "ok" ? "✓" : "✗";
|
|
14140
|
-
var v = probeVerdict(s, j);
|
|
14141
|
-
gateEl.className = "ds-gate " + v.cls;
|
|
14142
|
-
gateEl.textContent = v.text;
|
|
14143
|
-
// 🔴 **「活動を記録中」の札も、押した結果で出し入れする(#660)。** ここを忘れると、
|
|
14144
|
-
// アクセス不可の行を直して押したときに**行は「接続OK」なのに札だけ消えたまま**に
|
|
14145
|
-
// なり、「決定の材料になっている」と読める(逆向きも同じで、届かなくなった行が
|
|
14146
|
-
// 「記録中」と言い続ける)。**判定は 「devExcludedBadgeVisible」 1 本**——
|
|
14147
|
-
// 描画時と押した後で別の条件を書くと、同じ行が 2 つのことを言う
|
|
14148
|
-
var exBadgeNow = card.querySelector(".badge.ds-not-ingested");
|
|
14149
|
-
if (exBadgeNow) {
|
|
14150
|
-
exBadgeNow.hidden = !devExcludedBadgeVisible({
|
|
14151
|
-
ingestExcluded: s.ingestExcluded, goldState: s.goldState, gate: j.gate,
|
|
14152
|
-
});
|
|
14153
|
-
}
|
|
14154
|
-
// 古い「X分前に確認」を残さない(下に出るいまの結果と、時刻が2つ並ぶ)
|
|
14155
|
-
var oldAt = card.querySelector(".ds-gate-at");
|
|
14156
|
-
if (oldAt) oldAt.remove();
|
|
14157
|
-
// 古い run の導線も残さない(#560)。「いま測った結果」の横に夜間の run のログが並ぶ形になる
|
|
14158
|
-
removeRunTrail(card);
|
|
14159
|
-
// 🔴 **古いスコープ名の札も必ず消してから出し直す。** 行には夜間の判定に添えた
|
|
14160
|
-
// 札が出ていることがあり(段B)、置き換えた「接続OK」の横に古いスコープ名が
|
|
14161
|
-
// 残ると、同じ行が2つのことを言う——この節が何度も直してきた形そのもの。
|
|
14162
|
-
// 押し直すたびに札が増えていくのも、まとめてここで断つ
|
|
14163
|
-
var oldScopes = card.querySelectorAll(".ds-probe-scope");
|
|
14164
|
-
for (var oi = 0; oi < oldScopes.length; oi++) oldScopes[oi].remove();
|
|
14165
|
-
// 不足スコープは**状態の語のすぐ横**に出す(「権限が足りません:groups:read」)。
|
|
14166
|
-
// 本文へ落とすと、いちばん要る情報が説明文に埋もれる。
|
|
14167
|
-
// ⚠ **札にするのは Slack のスコープ名だけ。** GitHub の needed は URL 込みの
|
|
14168
|
-
// 一文なので、札に押し込むとバッジの横で折り返して読めない(本文へ出す)
|
|
14169
|
-
if (j.gate === "missing_scope" && probeTypeOf(s.type) === "slack") {
|
|
14170
|
-
head.appendChild(el("code", { class: "ds-probe-scope", text: j.needed || "不明" }));
|
|
14171
|
-
}
|
|
14172
|
-
at.textContent = "いま測った結果(" + (dsFmtTime(j.checkedAt) || "たった今") + ")";
|
|
14173
|
-
probeHelpNodes(s, j).forEach(function (n) { body.appendChild(n); });
|
|
14174
|
-
// **夜間の判定に添えてあった案内は隠す。** 置き換えた判定と食い違う案内が
|
|
14175
|
-
// 下に残ると、同じ行に2つのことが書いてある状態になる。
|
|
14176
|
-
// **1つ目だけでなく全部隠す(#346)。** 理由文(.ds-gate-reason)・定型補足
|
|
14177
|
-
// (.ds-gate-resting)・DS_GATE の help のどれが付いていても、押した結果と
|
|
14178
|
-
// 食い違う案内を残さない
|
|
14179
|
-
var stale = card.querySelectorAll(".ds-gate-help");
|
|
14180
|
-
for (var si = 0; si < stale.length; si++) stale[si].hidden = true;
|
|
14181
14060
|
// 表示名を Slack の実名へ自動で揃える(差分表示も更新ボタンも出さない)。
|
|
14182
14061
|
// **GitHub は揃えない。** 行の名前は owner/repo そのもので、書き換える口
|
|
14183
14062
|
//(op=config の refresh-channel-name)は channels.json 専用
|
|
14184
14063
|
if (s.type === "slack") autoAlignName(s, j, card);
|
|
14185
|
-
//
|
|
14186
|
-
//
|
|
14187
|
-
//
|
|
14188
|
-
//
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14064
|
+
// 🔴 **結果は、ストアの行と同じ形で LIVE_STATE に置いて、行を描き直す**(applyProbeResult)。
|
|
14065
|
+
// 判定・時刻・「活動を記録中」の札・スコープ名の札・次の一手・兄弟の行(issues /
|
|
14066
|
+
// discussions)の判定は、全部この描き直しが決める。ここで DOM を別の形で書き足すと、
|
|
14067
|
+
// 開き直した行と形が割れる(#1328)
|
|
14068
|
+
try {
|
|
14069
|
+
applyProbeResult(probeCapOfType(s.type), s.ref, s.workspace || "", {
|
|
14070
|
+
gate: j.gate,
|
|
14071
|
+
checkedAt: j.checkedAt,
|
|
14072
|
+
needed: j.needed || "",
|
|
14073
|
+
// サーバがストアへ書く値と同じ(op=probe の保存側の項)
|
|
14074
|
+
detail: j.reason || j.error || (j.gate === "ok" ? "" : j.gate),
|
|
14075
|
+
});
|
|
14076
|
+
} catch (drawErr) { /* 描き直しの不調を「通信に失敗」と言わない(測れた事実は取れている)。続く読み直しに任せる */ }
|
|
14195
14077
|
} catch (e) {
|
|
14078
|
+
wrap.className = "ds-probe is-shown";
|
|
14196
14079
|
msg.className = "ds-toggle-msg is-error";
|
|
14197
14080
|
msg.textContent = "✗ 通信に失敗しました。";
|
|
14198
14081
|
}
|
|
@@ -14201,6 +14084,84 @@ ${calendarAddUrl.toString()}
|
|
|
14201
14084
|
return { btn: btn, detail: wrap };
|
|
14202
14085
|
}
|
|
14203
14086
|
|
|
14087
|
+
/**
|
|
14088
|
+
* 押した直後の結果を、**接続状態ストアの行と同じ形**で LIVE_STATE に置き、一覧を描き直す。
|
|
14089
|
+
*
|
|
14090
|
+
* 🔴 **行の見た目を決める関数は、開き直したときと同じ 1 本(extSourceCard など)。** 押下の処理は
|
|
14091
|
+
* 札・時刻・説明文を自分で描かない。以前は押下が「いま測った結果」の枠を先に描き、直後の
|
|
14092
|
+
* reloadLiveState で行がいつもの形に描き直されて、2 回見た目が変わっていた(cortex-engine #1328)。
|
|
14093
|
+
*
|
|
14094
|
+
* 形はサーバが書く行(by が button の行)と同じに揃える。続く reloadLiveState が本物の行で
|
|
14095
|
+
* 置き換えても DOM は変わらない。**語彙に無い値は行ごと落とす**(sanitizeStateNow)——
|
|
14096
|
+
* その場合は描き直しの代わりに reloadLiveState に任せる。
|
|
14097
|
+
*
|
|
14098
|
+
* @param capId 接続状態ストアの能力名(chat / google-chat / dev / issues / materials / design)
|
|
14099
|
+
* @param r { gate, checkedAt, needed, detail }
|
|
14100
|
+
*/
|
|
14101
|
+
function applyProbeResult(capId, ref, workspace, r) {
|
|
14102
|
+
var row = {
|
|
14103
|
+
cap: capId, question: "reachable", ref: String(ref), status: String(r.gate || ""),
|
|
14104
|
+
at: r.checkedAt ? String(r.checkedAt) : new Date().toISOString(),
|
|
14105
|
+
by: "button", needed: String(r.needed || ""), detail: String(r.detail || ""),
|
|
14106
|
+
};
|
|
14107
|
+
if (workspace) row.workspace = String(workspace);
|
|
14108
|
+
var want = stateRefKey(capId, ref, workspace);
|
|
14109
|
+
var next = (LIVE_STATE || []).filter(function (x) {
|
|
14110
|
+
return !(x && x.cap === capId && x.question === "reachable" && stateRefKey(capId, x.ref, x.workspace) === want);
|
|
14111
|
+
});
|
|
14112
|
+
next.push(row);
|
|
14113
|
+
var clean = sanitizeStateNow(next);
|
|
14114
|
+
// 行が語彙に無く落ちたときは据え置き(reloadLiveState が本物を持ってくる)
|
|
14115
|
+
if (clean && clean.some(function (x) { return x.cap === capId && x.question === "reachable" && x.at === row.at && stateRefKey(capId, x.ref, x.workspace) === want; })) {
|
|
14116
|
+
// 押した結果の控え。**すでに飛んでいる読み直し(押す前の行を返す)や、保存が追いつく前の読み直しが
|
|
14117
|
+
// 届いても、行が古い判定へ戻らない**ように、本物の行が追いつくまで重ねる(「mergeProbeLocal」)
|
|
14118
|
+
PROBE_LOCAL[capId + "\t" + want] = { row: row, t: Date.now() };
|
|
14119
|
+
LIVE_STATE = clean;
|
|
14120
|
+
MERGED = null;
|
|
14121
|
+
repaintOpenLists();
|
|
14122
|
+
refreshDataSources();
|
|
14123
|
+
}
|
|
14124
|
+
// 本物の行を 1 回だけ取りに行く(据え置きのまま・「reloadLiveState」の項)
|
|
14125
|
+
reloadLiveState();
|
|
14126
|
+
}
|
|
14127
|
+
|
|
14128
|
+
/** 押した結果の行の控え(鍵は 能力+畳んだ ref)。本物の行が同じ時刻以降で届いたら捨てる */
|
|
14129
|
+
var PROBE_LOCAL = {};
|
|
14130
|
+
/**
|
|
14131
|
+
* 読み直しで届いた LIVE_STATE に、まだ追いつかれていない押した結果を重ねる。
|
|
14132
|
+
* 🔴 重ねないと、押した瞬間に飛んでいた読み直し(押す前の行)が届いた回だけ、行が古い判定に戻る(#1328)
|
|
14133
|
+
*/
|
|
14134
|
+
function mergeProbeLocal() {
|
|
14135
|
+
var keys = Object.keys(PROBE_LOCAL);
|
|
14136
|
+
if (!keys.length) return;
|
|
14137
|
+
var rows = (LIVE_STATE || []).slice();
|
|
14138
|
+
keys.forEach(function (k) {
|
|
14139
|
+
var local = PROBE_LOCAL[k].row;
|
|
14140
|
+
// 10 分たっても本物が追いつかなければ控えを捨てる(本物の行に任せる)
|
|
14141
|
+
if (Date.now() - PROBE_LOCAL[k].t > 10 * 60 * 1000) { delete PROBE_LOCAL[k]; return; }
|
|
14142
|
+
var want = stateRefKey(local.cap, local.ref, local.workspace);
|
|
14143
|
+
var caught = false;
|
|
14144
|
+
for (var i = 0; i < rows.length; i++) {
|
|
14145
|
+
var x = rows[i];
|
|
14146
|
+
if (x && x.cap === local.cap && x.question === "reachable" && stateRefKey(x.cap, x.ref, x.workspace) === want) {
|
|
14147
|
+
if (String(x.at) >= String(local.at)) caught = true;
|
|
14148
|
+
else rows.splice(i, 1);
|
|
14149
|
+
break;
|
|
14150
|
+
}
|
|
14151
|
+
}
|
|
14152
|
+
if (caught) { delete PROBE_LOCAL[k]; return; }
|
|
14153
|
+
rows.push(local);
|
|
14154
|
+
});
|
|
14155
|
+
LIVE_STATE = sanitizeStateNow(rows);
|
|
14156
|
+
}
|
|
14157
|
+
|
|
14158
|
+
/** 画面の種別 → 接続状態ストアの能力名(「接続を確認」の行) */
|
|
14159
|
+
function probeCapOfType(type) {
|
|
14160
|
+
if (String(type || "").indexOf("github") === 0) return "dev";
|
|
14161
|
+
if (type === "google-chat") return "google-chat";
|
|
14162
|
+
return "chat";
|
|
14163
|
+
}
|
|
14164
|
+
|
|
14204
14165
|
function removeChannelButton(s, card) {
|
|
14205
14166
|
return removeButton({
|
|
14206
14167
|
label: "登録を解除",
|
|
@@ -14652,6 +14613,9 @@ ${calendarAddUrl.toString()}
|
|
|
14652
14613
|
* **この印のものだけ**消す——「取り込み: 〜に成功」の横の語(別の行のもの)は残す
|
|
14653
14614
|
*/
|
|
14654
14615
|
function runTrailNodes(row, kind) {
|
|
14616
|
+
// 🔴 「その場で確認」は「◯分前に確認」の横に出さない(時刻が出ていて、重ねると同じことを 2 度言う)。
|
|
14617
|
+
// 押した直後の行と開き直した行で形が割れないよう、書き手が button の行は語を持たない
|
|
14618
|
+
if (kind === "gate" && row && row.by === "button") return [];
|
|
14655
14619
|
var word = runSourceWordOf(row);
|
|
14656
14620
|
var node = word ? el("span", { class: "ds-run-src", text: word }) : null;
|
|
14657
14621
|
if (!node) return [];
|
|
@@ -14666,15 +14630,6 @@ ${calendarAddUrl.toString()}
|
|
|
14666
14630
|
return f;
|
|
14667
14631
|
}
|
|
14668
14632
|
|
|
14669
|
-
/**
|
|
14670
|
-
* 「いま測った結果」に差し替えるとき、**「◯分前に確認」に添えた**古い出どころの語を外す
|
|
14671
|
-
* (同じ行が 2 つのことを言わない)。「取り込み: 〜に成功」の横の語は別の行のものなので残す
|
|
14672
|
-
*/
|
|
14673
|
-
function removeRunTrail(scope) {
|
|
14674
|
-
var old = scope.querySelectorAll('.ds-run-src[data-trail="gate"]');
|
|
14675
|
-
for (var i = 0; i < old.length; i++) old[i].remove();
|
|
14676
|
-
}
|
|
14677
|
-
|
|
14678
14633
|
/**
|
|
14679
14634
|
* 接続先1件の「取り込み」の表示。**測っていなければ何も出さない(null)。**
|
|
14680
14635
|
*
|
|
@@ -14767,8 +14722,8 @@ ${calendarAddUrl.toString()}
|
|
|
14767
14722
|
if (!r) return row;
|
|
14768
14723
|
var gate = dsGateForCap(capId, r.status);
|
|
14769
14724
|
row.appendChild(el("span", { class: "ds-gate " + gate.cls, text: gate.text }));
|
|
14770
|
-
var when =
|
|
14771
|
-
if (when) row.appendChild(el("span", { class: "ds-gate-at", text: when
|
|
14725
|
+
var when = agoConfirmedText(r.at);
|
|
14726
|
+
if (when) row.appendChild(el("span", { class: "ds-gate-at", text: when }));
|
|
14772
14727
|
// run の無い書き手は出どころの語を添える(#560)
|
|
14773
14728
|
runTrailNodes(r, "gate").forEach(function (n) { row.appendChild(n); });
|
|
14774
14729
|
return row;
|
|
@@ -14812,7 +14767,7 @@ ${calendarAddUrl.toString()}
|
|
|
14812
14767
|
* -------------------------------------------------------------------------
|
|
14813
14768
|
* #548 までは、この3つは中央が鍵を読まない(#105 決定5)ので、押すとその案件の同期が
|
|
14814
14769
|
* 1回起きるだけだった。オーナーがその境界を覆し、いまは「接続を確認」は Slack / GitHub と
|
|
14815
|
-
* 同じく**中央がその場で叩いて答えを返す**(即答・「
|
|
14770
|
+
* 同じく**中央がその場で叩いて答えを返す**(即答・「applyProbeResult」)。同期を1回
|
|
14816
14771
|
* 起こす従来の動きは「今すぐ同期」(送る値に 「sync: true」)に移った。
|
|
14817
14772
|
*
|
|
14818
14773
|
* 待ちの仕組み(下)は「今すぐ同期」と、Backlog が IP 制限で叩けず夜間と同じ経路へ
|
|
@@ -14901,6 +14856,7 @@ ${calendarAddUrl.toString()}
|
|
|
14901
14856
|
* 登録簿が読めない・ロール未登録・起動失敗が、全部ここへ来る)。
|
|
14902
14857
|
*/
|
|
14903
14858
|
function probeDeclined(note, key, j) {
|
|
14859
|
+
note.hidden = false;
|
|
14904
14860
|
note.textContent = (j && j.message) || "確認できませんでした。";
|
|
14905
14861
|
delete PROBE_WAITS[key];
|
|
14906
14862
|
}
|
|
@@ -14920,6 +14876,7 @@ ${calendarAddUrl.toString()}
|
|
|
14920
14876
|
startedAt: Date.now(),
|
|
14921
14877
|
message: (j && j.message) || "",
|
|
14922
14878
|
};
|
|
14879
|
+
note.hidden = false;
|
|
14923
14880
|
probeWaitNote(note, PROBE_WAITS[key]);
|
|
14924
14881
|
// 待っているあいだは取り直しを回す(届いた行で一覧が描き直される)
|
|
14925
14882
|
refreshStateTimer();
|
|
@@ -14930,58 +14887,6 @@ ${calendarAddUrl.toString()}
|
|
|
14930
14887
|
note.textContent = (wait && wait.message) || "";
|
|
14931
14888
|
}
|
|
14932
14889
|
|
|
14933
|
-
/**
|
|
14934
|
-
* 即答(#548 の direct)を行に映す。**「probeSection」 と同じ見た目にする**——
|
|
14935
|
-
* 夜間のスナップショットの判定といま測った判定を**同じ行に並べない**ため
|
|
14936
|
-
* (並べると「⚠️ と 接続OK が同時に出ている」になり、この節で何度も直してきた
|
|
14937
|
-
* 食い違いを画面の側から作ることになる)。置き換えたことが分かるよう、
|
|
14938
|
-
* いつ測ったかを必ず添える。
|
|
14939
|
-
*
|
|
14940
|
-
* 🔴 **札が無い行もある**(一度も測っていない接続先= 「appendReachableChip」 が
|
|
14941
|
-
* 何も足していない行)。その場合は札を作って**ボタンの前**に差し込む——後ろに置くと
|
|
14942
|
-
* 行の読み順(札 → ボタン)が崩れる。
|
|
14943
|
-
*
|
|
14944
|
-
* @param anchor 差し込む位置の目印(1つ目のボタン)
|
|
14945
|
-
*/
|
|
14946
|
-
function showProbeVerdict(row, capId, anchorIn, j) {
|
|
14947
|
-
var gate = dsGateForCap(capId, j.gate);
|
|
14948
|
-
// 差し込む位置は**行の最初のボタン**の前(「外す」が出る行では「外す」の前)。
|
|
14949
|
-
// 「接続を確認」の前に置くと、外せる行だけ「外す → 札 → ボタン」の並びになる(🟡10)
|
|
14950
|
-
var anchor = anchorIn;
|
|
14951
|
-
var btns = row.querySelectorAll(".ds-toggle-btn");
|
|
14952
|
-
for (var bi = 0; bi < btns.length; bi++) {
|
|
14953
|
-
// **行の直下にあるボタンだけ**が目印になれる(入れ子の中のボタンの前には差し込めない)
|
|
14954
|
-
if (btns[bi].parentNode === row) { anchor = btns[bi]; break; }
|
|
14955
|
-
}
|
|
14956
|
-
var chip = row.querySelector(".ds-gate");
|
|
14957
|
-
if (!chip) {
|
|
14958
|
-
chip = el("span", { class: "ds-gate" });
|
|
14959
|
-
row.insertBefore(chip, anchor);
|
|
14960
|
-
}
|
|
14961
|
-
chip.className = "ds-gate " + gate.cls;
|
|
14962
|
-
chip.textContent = gate.text;
|
|
14963
|
-
var at = row.querySelector(".ds-gate-at");
|
|
14964
|
-
if (!at) {
|
|
14965
|
-
at = el("span", { class: "ds-gate-at" });
|
|
14966
|
-
row.insertBefore(at, anchor);
|
|
14967
|
-
}
|
|
14968
|
-
at.textContent = "いま測った結果(" + (dsFmtTime(j.checkedAt) || "たった今") + ")";
|
|
14969
|
-
// 古い run の導線も外す(#560)。残すと「いま測った結果」の横に夜間の run のログが並ぶ
|
|
14970
|
-
removeRunTrail(row);
|
|
14971
|
-
// **夜間の判定に添えてあった案内は隠す。** 置き換えた判定と食い違う案内が下に残ると、
|
|
14972
|
-
// 同じ行が2つのことを言う(probeSection の stale 処理と同じ)
|
|
14973
|
-
var stale = row.querySelectorAll(".ds-gate-help");
|
|
14974
|
-
for (var si = 0; si < stale.length; si++) stale[si].hidden = true;
|
|
14975
|
-
// **押し直しで段が増えないよう、前回の結果は消してから出す**(probeSection の札と同じ)
|
|
14976
|
-
var old = row.querySelectorAll(".ds-probe-help");
|
|
14977
|
-
for (var oi = 0; oi < old.length; oi++) old[oi].remove();
|
|
14978
|
-
// 次の一手は語の表(DS_GATE_CAP)が持っていればそれ。無ければ判定器の1文(detail)
|
|
14979
|
-
// ——どちらも**1段だけ**(帯は症状・行は一手・繰り返さない)
|
|
14980
|
-
var nodes = gateHelpNodes(gate, "ds-probe-help");
|
|
14981
|
-
if (!nodes.length && j.detail) nodes = [el("p", { class: "ds-probe-help", text: String(j.detail) })];
|
|
14982
|
-
nodes.forEach(function (n) { row.appendChild(n); });
|
|
14983
|
-
}
|
|
14984
|
-
|
|
14985
14890
|
/**
|
|
14986
14891
|
* 接続先1件の「接続を確認」「今すぐ同期」(2ボタン+その場の返事1文)を行に足す。
|
|
14987
14892
|
*
|
|
@@ -15010,9 +14915,11 @@ ${calendarAddUrl.toString()}
|
|
|
15010
14915
|
else note.hidden = true;
|
|
15011
14916
|
|
|
15012
14917
|
checkBtn.addEventListener("click", async function () {
|
|
14918
|
+
// 押している間は**ボタンだけ**が「確認中…」になる。行の中身は変えない(#1328)。
|
|
14919
|
+
// 前回の返事(「同期を開始しました」等)は押した時点で消す
|
|
15013
14920
|
var endBusy = beginBusy(checkBtn, "確認中…");
|
|
15014
|
-
note.hidden =
|
|
15015
|
-
note.textContent = "
|
|
14921
|
+
note.hidden = true;
|
|
14922
|
+
note.textContent = "";
|
|
15016
14923
|
// 🔴 **押す前に、いまの行の 「at」 を控える(🔴2)。** 行が無ければ空文字
|
|
15017
14924
|
//(どんな 「at」 が来ても「新しい」と読める)。使うのは IP 制限で倒れた回だけだが、
|
|
15018
14925
|
// 応答が返ってからでは「押す前の行」を控えられない
|
|
@@ -15039,11 +14946,11 @@ ${calendarAddUrl.toString()}
|
|
|
15039
14946
|
delete PROBE_WAITS[key];
|
|
15040
14947
|
note.hidden = true;
|
|
15041
14948
|
note.textContent = "";
|
|
15042
|
-
|
|
15043
|
-
//
|
|
15044
|
-
|
|
15045
|
-
reloadLiveState();
|
|
14949
|
+
// 🔴 結果は行を描く関数に渡して描き直す(札・時刻・次の一手は行が決める。#1328)。
|
|
14950
|
+
// 次の一手は語の表が持っていればそれ、無ければ判定器の 1 文(detail)——どちらも行の側の規則
|
|
14951
|
+
applyProbeResult(capId, ref, "", { gate: j.gate, checkedAt: j.checkedAt, needed: "", detail: j.detail || "" });
|
|
15046
14952
|
} catch (e) {
|
|
14953
|
+
note.hidden = false;
|
|
15047
14954
|
note.textContent = "通信に失敗しました。";
|
|
15048
14955
|
delete PROBE_WAITS[key];
|
|
15049
14956
|
}
|
|
@@ -15742,18 +15649,10 @@ ${calendarAddUrl.toString()}
|
|
|
15742
15649
|
placeholder: "https://drive.google.com/drive/folders/…",
|
|
15743
15650
|
namePlaceholder: "メモ(任意)",
|
|
15744
15651
|
requiredNote: "フォルダのURLを入力してください。",
|
|
15745
|
-
//
|
|
15746
|
-
//
|
|
15747
|
-
//
|
|
15748
|
-
//
|
|
15749
|
-
// **誰を招待すればいいのかが画面から分からなかった**——担当者に聞かないと
|
|
15750
|
-
// 完了できない手順になっていた。
|
|
15751
|
-
// 招待されない限り何も読めないアカウントなので、出す判断をした。
|
|
15752
|
-
hint: [
|
|
15753
|
-
{ text: "読み取りたい Google Drive のフォルダを開き、下のアカウントを閲覧者として招待します(招待が無いと読めません)。", node: copyRow(DRIVE_INGEST_ACCOUNT) },
|
|
15754
|
-
"そのフォルダのURLを下の欄に貼って「追加」を押します。",
|
|
15755
|
-
"追加したフォルダの中身が 共有資料 にコピーされ、Markdown 化されます。止めるときは、その行の「このフォルダを外す」を押します。",
|
|
15756
|
-
],
|
|
15652
|
+
// 🔴 **追加の欄は入力と[追加]だけ(c-07)。** 以前は「アカウントを招待 → URL を貼る → 何が起きるか」の
|
|
15653
|
+
// 手順(コピー行つき)を置いていたが、足してから読めなければ、その行の中が一手を出す
|
|
15654
|
+
// (DS_GATE_CAP.materials.unreachable: 「このフォルダを cortex-notetaker@… に閲覧者として共有してください。[コピー]」)。
|
|
15655
|
+
// 「中身が 共有資料 にコピーされ Markdown 化される・止め方」はモーダル上部の説明文が 1 回だけ持つ。
|
|
15757
15656
|
build: function (url, name) { return { op: "add-drive-folder", url: url, name: name }; },
|
|
15758
15657
|
}));
|
|
15759
15658
|
used = true;
|
|
@@ -15926,18 +15825,9 @@ ${calendarAddUrl.toString()}
|
|
|
15926
15825
|
placeholder: "https://www.figma.com/design/…",
|
|
15927
15826
|
namePlaceholder: "メモ(任意)",
|
|
15928
15827
|
requiredNote: "FigmaのURLを入力してください。",
|
|
15929
|
-
//
|
|
15930
|
-
//
|
|
15931
|
-
//
|
|
15932
|
-
// **手順1・2は要約にとどめ、正本は上の鍵の欄に置く**(SECRET_FORMS.figma の
|
|
15933
|
-
// how / note)。全文をここに移すと二重になり、片方だけ直る形になる
|
|
15934
|
-
// ——カードは接続マップとタイルの注記と条件を揃えているので、動かすと壊れやすい。
|
|
15935
|
-
hint: [
|
|
15936
|
-
"Figma でトークンを発行します(読み取りだけ。スコープ2つ。Dev または Full 席の方が発行)。手順は「Figma のトークン」の欄にあります(ファイルを追加すると上に出ます)。",
|
|
15937
|
-
"発行したアカウントを、読み取りたい Figma ファイルに閲覧者として招待します(招待が無いと、トークンが正しくても読めません)。",
|
|
15938
|
-
"そのファイルのURLを下の欄に貼って「追加」を押します。",
|
|
15939
|
-
"追加したファイルは、画面名と Figma へのリンクが毎晩同期されます(画像は取り込まれません)。",
|
|
15940
|
-
],
|
|
15828
|
+
// 🔴 **追加の欄は入力と[追加]だけ(c-07)。** 以前は「トークンを発行 → 招待 → URL → 何が同期されるか」の
|
|
15829
|
+
// 手順を置いていたが、トークンの発行手順の正本は鍵の欄(SECRET_FORMS.figma の how・note・画像)、
|
|
15830
|
+
// 読めないファイルの一手は行の中(DS_GATE_CAP.design)、「何が同期されるか」は上部の説明文が持つ。
|
|
15941
15831
|
build: function (url, name) { return { op: "add-figma-file", url: url, name: name }; },
|
|
15942
15832
|
}));
|
|
15943
15833
|
used = true;
|
|
@@ -15978,24 +15868,10 @@ ${calendarAddUrl.toString()}
|
|
|
15978
15868
|
// 別名を付けたいときだけ入れてもらう。
|
|
15979
15869
|
namePlaceholder: "表示名(省略するとSlackから取得します)",
|
|
15980
15870
|
requiredNote: "チャンネルのURLを入力してください。",
|
|
15981
|
-
//
|
|
15982
|
-
//
|
|
15983
|
-
//
|
|
15984
|
-
//
|
|
15985
|
-
// 一続きの文章だと、読む人が「自分がいま何をすべきか」を自分で切り出すことになる。
|
|
15986
|
-
//
|
|
15987
|
-
// **接続(お客様の Slack への導入)の説明もここに置く。** 独立した節を
|
|
15988
|
-
// 廃止したので、**繋ぎ方を知る場所はここしか無い**——
|
|
15989
|
-
// 「0件の案件で入口が消える」という過去の事故(renderExternalAdders の
|
|
15990
|
-
// 直上コメント)を、この手順が受け止めている。
|
|
15991
|
-
hint: [
|
|
15992
|
-
// **コマンドは手順1の中に置く。** フォームの下に離すと、どの手順のものか
|
|
15993
|
-
// 対応が読めない(手で打たせない理由は copyRow のコメント)
|
|
15994
|
-
{ text: "読み取りたいチャンネルで、下のコマンドを貼って Cortex を招待します。公開チャンネルでも招待が必要です。", node: copyRow("/invite @Cortex") },
|
|
15995
|
-
"下の欄に、そのチャンネルのリンクを貼って「追加」を押します(チャンネル名を右クリック →「リンクをコピー」)。",
|
|
15996
|
-
"「組織不明」と出たら、そこにある「Slack ワークスペースに接続する」から承認をもらいます。お客様の Slack のチャンネルは、この承認が済むまで読めません(承認できるのはその Slack の管理者です)。",
|
|
15997
|
-
"追加したチャンネルは毎晩の Gold 昇格の対象になり、Decision・用語集の材料になります。止めるときは、その行の「登録を解除」を押します。",
|
|
15998
|
-
],
|
|
15871
|
+
// 🔴 **追加の欄は入力と[追加]だけ(c-07)。** 以前は「/invite を貼る → リンクを貼る → 組織不明なら接続 →
|
|
15872
|
+
// Gold 昇格の対象」の手順 4 行を置いていたが、足してから読めなければ、そのチャンネルの行の中が
|
|
15873
|
+
// 理由に合った一手(「Cortex が招待されていません:/invite @Cortex[コピー]」・「この Slack を Cortex に接続してください。[接続する]」)を出す。
|
|
15874
|
+
// 「毎晩の Gold 昇格の対象・止め方」「お客様の Slack は管理者の承認が要る」は、モーダル上部の説明文が 1 回だけ持つ。
|
|
15999
15875
|
// **選んだワークスペースを送る(#104)。** 空文字=社内ワークスペースなのでキーごと落とす
|
|
16000
15876
|
// (サーバ側は「未宣言・null・空」を区別しない約束で、無いことで既定を表す)
|
|
16001
15877
|
build: function (url, name, workspace) {
|
|
@@ -16038,14 +15914,8 @@ ${calendarAddUrl.toString()}
|
|
|
16038
15914
|
// 承認そのもので、画面に押す先が無い(Slack の接続ボタンを写経しないこと——
|
|
16039
15915
|
// 押しても何も起きないボタンが顧客の画面に出る)。
|
|
16040
15916
|
// **追加時の確認モーダルも出さない**(#167 で「追加のたびの確認」は廃止済み。
|
|
16041
|
-
// 「追加=Gold
|
|
16042
|
-
//
|
|
16043
|
-
// fleet-status にデータが無い案件でもフォームは常設なので、案内も常に出る)
|
|
16044
|
-
//
|
|
16045
|
-
// Google Chat アプリの表示名。**Marketplace 公開名(2026-09-03 オーナー決定で
|
|
16046
|
-
// 「Cortex Bot」から改称・#387。このモーダル分は #389 で済ませた)。**
|
|
16047
|
-
// 検索ワードとして本文に組み込む(コピー行は置かない——コマンドではなく検索語のため)
|
|
16048
|
-
var GCHAT_APP_NAME = "Cortex by Classmethod";
|
|
15917
|
+
// 「追加=Gold 昇格の対象」という重さは、モーダル上部の説明文が 1 回だけ言う)。
|
|
15918
|
+
// Google Chat アプリの表示名は GCHAT_APP_NAME(Marketplace 公開名・#387)。
|
|
16049
15919
|
box.appendChild(addForm({
|
|
16050
15920
|
title: "+ Google Chat スペースを追加",
|
|
16051
15921
|
// **いま画面に出ている形を例示する(#389)。** 旧UIの /room/ を例にしていたので、
|
|
@@ -16053,35 +15923,9 @@ ${calendarAddUrl.toString()}
|
|
|
16053
15923
|
placeholder: "https://chat.google.com/app/chat/XXXXXXXXXXX",
|
|
16054
15924
|
// 素の spaces/<ID> も受ける(#389)ので、URL しか受けないとは書かない
|
|
16055
15925
|
requiredNote: "スペースの URL か spaces/… を入力してください。",
|
|
16056
|
-
//
|
|
16057
|
-
//
|
|
16058
|
-
//
|
|
16059
|
-
// 貼って 400 になってから知るより先に
|
|
16060
|
-
//
|
|
16061
|
-
// **1行1手に詰める(2026-09-03 オーナー指示・#389)。** 手順の中に事情の説明が
|
|
16062
|
-
// 混ざると、読む人が「自分がいま何をすべきか」を自分で切り出すことになる。
|
|
16063
|
-
// 🔴 落とさない語(既存テストが固定している): 「アプリと統合」「Gold 昇格の対象になり」
|
|
16064
|
-
// 「登録を解除」「22時」——重さと止め方を伝える場所がこの手順しか無いため
|
|
16065
|
-
hint: [
|
|
16066
|
-
{
|
|
16067
|
-
text: "読み取りたいスペースに Cortex のアプリを追加します。スペース名 → 「アプリと統合」 → 「アプリを追加」 で、「" + GCHAT_APP_NAME + "」を検索して追加します。",
|
|
16068
|
-
// **画像は補助で、上の1文だけで手順が完結する**(読み上げ・画像が出ない環境)。
|
|
16069
|
-
// 寸法は属性で明示——書かないと、モーダルを開いた瞬間に画像の高さのぶん下の手順がずれる。
|
|
16070
|
-
// loading=lazy は付けない(data: URI には取得が無いので何もしない・Meet と同じ)。
|
|
16071
|
-
// 2枚を div でくるむのは、hintNode の口を広げないため(1手順=1ノードの約束を保つ)。
|
|
16072
|
-
// 🔴 **会議カードと同じ guideShot を通す(#455)。** 3 枚が同じ上限・同じ
|
|
16073
|
-
// クリックの振る舞いになる。ここで幅を書き足すと、その 1 枚だけ揃わなくなる
|
|
16074
|
-
node: el("div", {}, [
|
|
16075
|
-
guideShot({ src: GCHAT_SHOT_STEP1, width: "900", height: "566",
|
|
16076
|
-
alt: "Google Chat のスペースの画面。スペース名の横のメニューが開いていて、その中の「アプリと統合」が赤い枠で示されている。" }),
|
|
16077
|
-
guideShot({ src: GCHAT_SHOT_STEP2, width: "900", height: "491",
|
|
16078
|
-
alt: "「アプリと統合」の画面。右上の「+ アプリを追加」が赤い枠で示され、その下に、このスペースに追加されているアプリの一覧が並んでいる。" }),
|
|
16079
|
-
]),
|
|
16080
|
-
},
|
|
16081
|
-
"検索に出ないときは、貴社の Google Workspace 管理者の承認がまだです(承認できるのは管理者だけ・反映まで最大24時間)。",
|
|
16082
|
-
"下の欄に、ブラウザでスペースを開いたときのURL(chat.google.com/app/chat/… または /room/…)を貼って「追加」を押します。DM(1対1のチャット)は対象外です。",
|
|
16083
|
-
"追加したスペースは毎晩の Gold 昇格の対象になり、Decision・用語集の材料になります。止めるときは、その行の「登録を解除」を押します(今夜のぶんは22時ごろまでに解除すれば取り込まれません)。",
|
|
16084
|
-
],
|
|
15926
|
+
// 🔴 **追加の欄は入力と[追加]だけ(c-07)。** アプリの追加手順(画像つき)と管理者の承認は、
|
|
15927
|
+
// 足したスペースの行の一手(DS_GATE.not_in_space)が持つ。「DM は対象外」「Gold 昇格の対象・止め方」は
|
|
15928
|
+
// モーダル上部の説明文が持つ。URL の形は placeholder と requiredNote。
|
|
16085
15929
|
build: function (url) {
|
|
16086
15930
|
return { op: "add-google-chat-space", url: url };
|
|
16087
15931
|
},
|
|
@@ -16842,7 +16686,7 @@ ${calendarAddUrl.toString()}
|
|
|
16842
16686
|
badges.appendChild(el("span", {
|
|
16843
16687
|
class: "badge ds-workspace ds-workspace-unknown",
|
|
16844
16688
|
text: "組織不明",
|
|
16845
|
-
title: "どの Slack
|
|
16689
|
+
title: "どの Slack のチャンネルか、まだ分かっていません。この行の案内をご覧ください。",
|
|
16846
16690
|
}));
|
|
16847
16691
|
} else {
|
|
16848
16692
|
badges.appendChild(el("span", {
|
|
@@ -16900,7 +16744,7 @@ ${calendarAddUrl.toString()}
|
|
|
16900
16744
|
var gateEl = el("span", { class: "ds-gate " + gate.cls, text: gate.text });
|
|
16901
16745
|
// 状態ストア由来の判定には「いつ確かめたか」を必ず添える
|
|
16902
16746
|
var gateAtEl = s.gateAt
|
|
16903
|
-
? el("span", { class: "ds-gate-at", text:
|
|
16747
|
+
? el("span", { class: "ds-gate-at", text: agoConfirmedText(s.gateAt) })
|
|
16904
16748
|
: null;
|
|
16905
16749
|
// run の無い書き手は出どころの語を添える(#560)。overlay が写した 「gateRunUrl」 / 「gateBy」 から決める
|
|
16906
16750
|
var gateTrail = s.gateAt ? runTrailNodes({ runUrl: s.gateRunUrl || "", by: s.gateBy || "" }, "gate") : [];
|
|
@@ -17016,7 +16860,14 @@ ${calendarAddUrl.toString()}
|
|
|
17016
16860
|
// を付ける——押した結果で置き換えるとき probeSection がまとめて隠す。
|
|
17017
16861
|
// **同じリポジトリの2本目の行(Discussions)には出さない**(opts.quietHelp)。
|
|
17018
16862
|
// 同じ長文が2行に並ぶと一覧が案内で埋まる。URL のリンク化は neededNode(innerHTML は使わない)
|
|
17019
|
-
|
|
16863
|
+
// 🔴 **足した直後の行でも、サーバが「組織不明」と実測して返したときだけは一手を出す(c-07)。**
|
|
16864
|
+
// 常設の接続ボタンを撤去したので、0 件の案件に顧客の Slack を足した人が接続へ進む入口はこの行だけ
|
|
16865
|
+
// (#138 型の穴を塞ぐ)。まだ gate が付いていない行(仮置き・登録の反映だけが先に届いた行)でも、
|
|
16866
|
+
// 印(orgUnknown)があれば出す。**印が無い行(測っていない)には何も出さない**
|
|
16867
|
+
if (s.type === "slack" && s.orgUnknown === true && !s.gate && SITE.intake) {
|
|
16868
|
+
var pendingParts = slackRowHelpParts(s);
|
|
16869
|
+
if (pendingParts) card.appendChild(restingHelpNode(pendingParts, "ds-gate-help ds-gate-resting"));
|
|
16870
|
+
} else if (!(opts && opts.quietHelp) && showsRestingReason(s)) {
|
|
17020
16871
|
var restingParts = restingHelpPartsOf(s.type, s.gate, s);
|
|
17021
16872
|
if (restingParts) card.appendChild(restingHelpNode(restingParts, "ds-gate-help ds-gate-resting"));
|
|
17022
16873
|
else if (!(String(s.type).indexOf("github") === 0 && (s.gate === "unreachable" || s.gate === "no_token") && !githubOrgRefused(s))) {
|
|
@@ -17053,7 +16904,7 @@ ${calendarAddUrl.toString()}
|
|
|
17053
16904
|
// **origin === "explicit" でも出す。** 確認は読むだけで、どの登録ファイル由来かに
|
|
17054
16905
|
// 関係なく効く(書き込みになる「表示名を更新する」だけが由来で出し分かれる)
|
|
17055
16906
|
if (SITE.intake && probeTypeOf(s.type) && s.ref) {
|
|
17056
|
-
var probe = probeSection(s, card
|
|
16907
|
+
var probe = probeSection(s, card);
|
|
17057
16908
|
// **ボタンは行の中(「登録を解除」の隣)。** 独立した段を作ると1行が2段になる
|
|
17058
16909
|
card.appendChild(probe.btn);
|
|
17059
16910
|
appendRowHelp();
|
|
@@ -17437,6 +17288,8 @@ ${calendarAddUrl.toString()}
|
|
|
17437
17288
|
LIVE_REGISTERED = sanitizeRegisteredNow(j && j.registeredNow);
|
|
17438
17289
|
LIVE_REGISTERED_AT = startedAt;
|
|
17439
17290
|
LIVE_STATE = sanitizeStateNow(j && j.stateNow);
|
|
17291
|
+
// 押した結果が本物の行に追いつくまで重ねる(mergeProbeLocal の項)
|
|
17292
|
+
mergeProbeLocal();
|
|
17440
17293
|
// **欄の有無をそのまま覚える。** sanitize を通した後では「読めて0件」が消える
|
|
17441
17294
|
LIVE_STATE_SEEN = !!(j && Array.isArray(j.stateNow));
|
|
17442
17295
|
// **カレンダーの行だけは sanitize の前に数える**(#428・上の宣言の項)
|