@takagaki/cortex-decisions-viewer 0.12.37 → 0.12.38
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 +317 -1
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -34,6 +34,9 @@ exports.secretStateFromNow = secretStateFromNow;
|
|
|
34
34
|
exports.secretRegisteredAnywhere = secretRegisteredAnywhere;
|
|
35
35
|
exports.sanitizeCapabilitiesNow = sanitizeCapabilitiesNow;
|
|
36
36
|
exports.sanitizeGithubOwnersNow = sanitizeGithubOwnersNow;
|
|
37
|
+
exports.sanitizeOnboardingNow = sanitizeOnboardingNow;
|
|
38
|
+
exports.claudeAppRepoSlug = claudeAppRepoSlug;
|
|
39
|
+
exports.claudeAppRequestText = claudeAppRequestText;
|
|
37
40
|
exports.splitNeededParts = splitNeededParts;
|
|
38
41
|
exports.ingestedAtOf = ingestedAtOf;
|
|
39
42
|
exports.keyMissingText = keyMissingText;
|
|
@@ -1792,6 +1795,100 @@ function sanitizeGithubOwnersNow(v) {
|
|
|
1792
1795
|
}
|
|
1793
1796
|
return out.length ? out : null;
|
|
1794
1797
|
}
|
|
1798
|
+
/**
|
|
1799
|
+
* 立ち上げの申請の印(`registeredNow.onboarding`・#94)の語彙。
|
|
1800
|
+
* サーバ側 `CLAUDE_APP_STATES`(`infra/lambda/intake/logic.mjs`)の写し。
|
|
1801
|
+
*
|
|
1802
|
+
* 🔴 **増やすときは `logic.mjs` の `CLAUDE_APP_STATES` と `registeredOnboarding` を
|
|
1803
|
+
* 同じ便で直すこと。順番は「サーバが先・画面が後」。**
|
|
1804
|
+
*
|
|
1805
|
+
* 片方だけ増やすと、その語の扱いが写しの間でずれる:
|
|
1806
|
+
* - 画面だけ増やす … サーバが `null` に倒した語を画面が受け取ることは無いので実害は
|
|
1807
|
+
* 出ないが、次に触る人は「画面は知っているのに出ない」を追うことになる
|
|
1808
|
+
* - サーバだけ増やす … サーバが新しい語を返し始めるのに画面の篩が落とす。
|
|
1809
|
+
* `sanitizeOnboardingNow` は落としたものを `null` にするので、**印を出してはいけない
|
|
1810
|
+
* 案件へ節が出る**方向には倒れないが、印を出すべき案件で節が二度と出なくなる
|
|
1811
|
+
*
|
|
1812
|
+
* **写しを互いに固定する検査は置けない**(intake とビューアは別パッケージで、
|
|
1813
|
+
* ビューアは infra を実行時に読まない)。だから順番をここに書いて守る。
|
|
1814
|
+
*/
|
|
1815
|
+
const CLAUDE_APP_STATES = ["unrequested", "requested"];
|
|
1816
|
+
/** op=state に足す能力名。**`STATE_CAP_NAMES` には入れない**(`ALL_STATE_CAPS` の項) */
|
|
1817
|
+
const ONBOARDING_CAP = "onboarding";
|
|
1818
|
+
/**
|
|
1819
|
+
* `registeredNow.onboarding`(立ち上げの印)の許可リスト。
|
|
1820
|
+
*
|
|
1821
|
+
* **他の registeredNow のキーとは器が違う**——あちらは行の配列、こちらは1つの状態
|
|
1822
|
+
* (`{ claudeGithubApp }`)なので、`sanitizeRegisteredNow` には混ぜない
|
|
1823
|
+
* (混ぜると配列を期待している篩がオブジェクトを踏む)。
|
|
1824
|
+
*
|
|
1825
|
+
* 🔴 **知らない語は `null` に倒す。** 画面は `"unrequested"` のときだけ節を出すので、
|
|
1826
|
+
* `null` に倒れる=**印を出さない側**へ倒れる。ここを truthy 判定に緩めると、
|
|
1827
|
+
* サーバが新しい語を返し始めた日に、印を出してはいけない案件へ節が出る。
|
|
1828
|
+
* `_note` のような運用メモは通さない(誰も確認していない文章を顧客の画面に出さない)。
|
|
1829
|
+
*/
|
|
1830
|
+
function sanitizeOnboardingNow(v) {
|
|
1831
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
1832
|
+
return null;
|
|
1833
|
+
const s = typeof v.claudeGithubApp === "string" ? v.claudeGithubApp : "";
|
|
1834
|
+
if (CLAUDE_APP_STATES.indexOf(s) < 0)
|
|
1835
|
+
return null;
|
|
1836
|
+
return { claudeGithubApp: s };
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* 申請文に埋める `owner/repo`(`repoBaseUrl` から導く。追加入力なし)。
|
|
1840
|
+
*
|
|
1841
|
+
* 🔴 **正規表現をクライアント側に書き写さないこと。** 埋め込みJSはテンプレート
|
|
1842
|
+
* リテラルの中なので、`\/` がリテラルの解釈で潰れて**別物の正規表現**になる
|
|
1843
|
+
* (`splitNeededParts` / `backlogTargetOf` と同じ理由。実際にここで一度壊した)。
|
|
1844
|
+
*
|
|
1845
|
+
* **`repoNameOf` とは別に持つ。** あちらは画面に出す短い名前(owner を落とす)で、
|
|
1846
|
+
* こちらは申請の宛先を一意に決める値——**owner を落としてはいけない**。
|
|
1847
|
+
*
|
|
1848
|
+
* **github.com のURLだけを受ける。** 別ホストの slug で申請文を作ると、
|
|
1849
|
+
* 存在しないリポジトリの追加を依頼させることになる。
|
|
1850
|
+
* owner だけの URL(github.com/owner)は空文字(呼び出し側が節ごと出さない)。
|
|
1851
|
+
*
|
|
1852
|
+
* **クロージャを持たない純関数に保つこと**(`.toString()` でクライアントへ渡す)。
|
|
1853
|
+
*/
|
|
1854
|
+
function claudeAppRepoSlug(repoBaseUrl) {
|
|
1855
|
+
const m = /^https?:\/\/github\.com\/(.+)$/.exec(String(repoBaseUrl == null ? "" : repoBaseUrl));
|
|
1856
|
+
if (!m)
|
|
1857
|
+
return "";
|
|
1858
|
+
const slug = m[1].replace(/\/+$/, "").replace(/\.git$/, "");
|
|
1859
|
+
return slug.indexOf("/") > 0 ? slug : "";
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Claude GitHub App の追加申請の申請文(画面がコピーして Slack へ貼る)。
|
|
1863
|
+
*
|
|
1864
|
+
* 🔴 **申請者本人の GitHub アカウント名はここで決めない。** 画面はログインしている人の
|
|
1865
|
+
* GitHub アカウントを知らない(ビューアは Basic 認証で、GitHub とは繋がっていない)ので、
|
|
1866
|
+
* **本人が書き足す**と文中で頼む——ポータルの `buildApplicationText` と同じ判断で、
|
|
1867
|
+
* 間違ったアカウントを admin に入れる事故を防ぐ。
|
|
1868
|
+
*
|
|
1869
|
+
* ⚠ 装飾のない素のテキスト。申請の宛先(Slack のチャンネル)は Markdown を解釈しない。
|
|
1870
|
+
*
|
|
1871
|
+
* **クロージャを持たない純関数に保つこと**(`.toString()` でクライアントへ渡す)。
|
|
1872
|
+
*
|
|
1873
|
+
* **案件名も入れる。** 承認する側(GitHub の管理チーム)はリポジトリ名だけでは
|
|
1874
|
+
* どの案件の話か分からず、名前が似た案件が並ぶと取り違えの元になる。
|
|
1875
|
+
*
|
|
1876
|
+
* @param repoSlug `owner/repo`。取れなければ空文字(呼び出し側が節ごと出さない)
|
|
1877
|
+
* @param projectName この案件の表示名(画面のタイトル)。空なら行ごと落とす
|
|
1878
|
+
*/
|
|
1879
|
+
function claudeAppRequestText(repoSlug, projectName) {
|
|
1880
|
+
const name = typeof projectName === "string" ? projectName.trim() : "";
|
|
1881
|
+
return [
|
|
1882
|
+
"Claude GitHub App の追加をお願いします。",
|
|
1883
|
+
"",
|
|
1884
|
+
// **空の「案件: 」を出さない。** 名前の無い行は、書き忘れたようにしか読めない
|
|
1885
|
+
...(name ? ["案件: " + name] : []),
|
|
1886
|
+
"対象リポジトリ: " + repoSlug,
|
|
1887
|
+
"用途: Cortex(AI 案件ビューア)のコンテキストリポジトリを Claude Code から読む",
|
|
1888
|
+
"",
|
|
1889
|
+
"申請者: (ここにご自身の GitHub アカウント名を書いてください)",
|
|
1890
|
+
].join("\n");
|
|
1891
|
+
}
|
|
1795
1892
|
/**
|
|
1796
1893
|
* サーバが返した「次の一手」(`needed`)を、素の文字列と URL に切り分ける。
|
|
1797
1894
|
*
|
|
@@ -3380,6 +3477,24 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
3380
3477
|
@media (max-width: 600px) {
|
|
3381
3478
|
.tut-actions { flex-direction: column; align-items: flex-start; }
|
|
3382
3479
|
}
|
|
3480
|
+
/* ---- Claude GitHub App の追加申請(#94)----
|
|
3481
|
+
接続マップの直後・「データソースと自動化」の前に出る。**印を持つ案件にしか出ない**ので、
|
|
3482
|
+
常設の節と同じ見た目にはしない(一度きりの手続き)。
|
|
3483
|
+
🔴 **枠は症状・行は一手。** 帯にしないのは、いま何かが壊れているわけではないから。 */
|
|
3484
|
+
.claude-app { margin-top: 28px; }
|
|
3485
|
+
.claude-app-head { font-size: 16px; font-weight: 700; color: var(--text); margin: 0 0 6px; }
|
|
3486
|
+
.claude-app-lead { color: var(--text); font-size: 13.5px; line-height: 1.8; margin: 0 0 10px; }
|
|
3487
|
+
/* 申請文。**選べる形で出す**(コピーボタンが使えない環境でも手で取れるように)。
|
|
3488
|
+
等幅にするのは、貼り先(Slack)で改行がそのまま効くことを見せるため */
|
|
3489
|
+
.claude-app-text {
|
|
3490
|
+
width: 100%; box-sizing: border-box; min-height: 130px; resize: vertical;
|
|
3491
|
+
border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
|
|
3492
|
+
background: var(--surface); color: var(--text);
|
|
3493
|
+
font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
3494
|
+
font-size: 12px; line-height: 1.7;
|
|
3495
|
+
}
|
|
3496
|
+
.claude-app-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
|
|
3497
|
+
.claude-app-done { color: #1a7f37; font-size: 13px; margin: 0; }
|
|
3383
3498
|
/* ---- データソースと自動化 ---- */
|
|
3384
3499
|
.datasources { margin-top: 34px; }
|
|
3385
3500
|
.datasources-head { font-size: 18px; font-weight: 700; color: var(--text); margin: 0 0 4px; }
|
|
@@ -4174,6 +4289,14 @@ ${secretStateFromNow.toString()}
|
|
|
4174
4289
|
${secretRegisteredAnywhere.toString()}
|
|
4175
4290
|
${sanitizeCapabilitiesNow.toString()}
|
|
4176
4291
|
${sanitizeGithubOwnersNow.toString()}
|
|
4292
|
+
// 立ち上げの申請の印(#94)。**判定の実体はビルド時の定義**——画面側に書き写すと
|
|
4293
|
+
// 語彙の許可リストが2枚になる。
|
|
4294
|
+
// 🔴 この2つの定数行を落とすと、流し込んだ関数が未定義を参照して画面が丸ごと死ぬ
|
|
4295
|
+
var CLAUDE_APP_STATES = ${JSON.stringify(CLAUDE_APP_STATES)};
|
|
4296
|
+
var ONBOARDING_CAP = ${JSON.stringify(ONBOARDING_CAP)};
|
|
4297
|
+
${sanitizeOnboardingNow.toString()}
|
|
4298
|
+
${claudeAppRepoSlug.toString()}
|
|
4299
|
+
${claudeAppRequestText.toString()}
|
|
4177
4300
|
${splitNeededParts.toString()}
|
|
4178
4301
|
${ingestedAtOf.toString()}
|
|
4179
4302
|
var TILE_CAPS = ${JSON.stringify(TILE_CAPS)};
|
|
@@ -7393,6 +7516,27 @@ ${calendarAddUrl.toString()}
|
|
|
7393
7516
|
* 指すのか説明できなくなる(realtime を別に持っているのと同じ理由)。
|
|
7394
7517
|
*/
|
|
7395
7518
|
var LIVE_REGISTERED = null;
|
|
7519
|
+
/**
|
|
7520
|
+
* 立ち上げの申請の印(op=state の registeredNow.onboarding・#94)。
|
|
7521
|
+
* 中身は claudeGithubApp の1欄("unrequested" / "requested")か null。**取得前も null。**
|
|
7522
|
+
*
|
|
7523
|
+
* 🔴 **null と "requested" を区別しないこと**——どちらも「節を出さない」で正しい。
|
|
7524
|
+
* 取得前に出す形にすると、印を持たない既存案件(34 件)で**一瞬だけ節が出る**。
|
|
7525
|
+
*
|
|
7526
|
+
* **LIVE_REGISTERED とは別に持つ。** あちらは能力ごとの行の配列で、こちらは
|
|
7527
|
+
* 1つの状態。同じ入れ物に混ぜると、配列を期待している篩とマージがオブジェクトを踏む。
|
|
7528
|
+
*
|
|
7529
|
+
* 注: ここは埋め込みJSのテンプレートリテラル内。**コメントでもバッククォートを使わない**
|
|
7530
|
+
*/
|
|
7531
|
+
var LIVE_ONBOARDING = null;
|
|
7532
|
+
/**
|
|
7533
|
+
* この画面で「申請済み」を押して、サーバが保存を確定したか(#94)。
|
|
7534
|
+
*
|
|
7535
|
+
* **メモリだけに持つ**(localStorage には書かない)。押した直後に取り直す正本が
|
|
7536
|
+
* 遅れた・落ちた回に、**役目を終えた申請文とボタンが戻ってくる**のを止めるためだけの旗で、
|
|
7537
|
+
* 再読み込みすれば案件側のファイル(正本)を読み直す——だから正本は2つにならない。
|
|
7538
|
+
*/
|
|
7539
|
+
var CLAUDE_APP_DONE = false;
|
|
7396
7540
|
/**
|
|
7397
7541
|
* いまの LIVE_REGISTERED を取りに行った時刻(op=state の要求を出した時刻・#388)。
|
|
7398
7542
|
* 仮置きの失効「保存より後の live が同じことを言っている」の根拠。届いた時刻ではなく
|
|
@@ -12062,7 +12206,12 @@ ${calendarAddUrl.toString()}
|
|
|
12062
12206
|
* ⚠ **並べ替えてから送る。** サーバのキャッシュキーは caps を並べ替えて繋ぐが、
|
|
12063
12207
|
* こちらも定数の並びを固定しておく(同じ集合が何通りにも増えない)。
|
|
12064
12208
|
*/
|
|
12065
|
-
|
|
12209
|
+
// 🔴 **立ち上げの印(#94)は STATE_CAP_NAMES には足さず、ここで足す。** あちらは
|
|
12210
|
+
// 「能力名の対応表」で、capabilitiesNow の行・接続状態ストアの引き当てにも使われる
|
|
12211
|
+
// ——足すと、能力でも何でもない onboarding の行が能力の一覧に生える。
|
|
12212
|
+
// ここに足すのは**サーバへ「このファイルも読んで」と伝える**ためだけ(操作タブを
|
|
12213
|
+
// 開いているときは常に要求される。要求は常に全量なので、載せれば必ず入る)。
|
|
12214
|
+
var ALL_STATE_CAPS = Object.keys(STATE_CAP_NAMES).concat([ONBOARDING_CAP]).sort();
|
|
12066
12215
|
/**
|
|
12067
12216
|
* 一度でも開いた能力。**送る caps とは無関係**(送るのは常に全量)。
|
|
12068
12217
|
*
|
|
@@ -12177,6 +12326,11 @@ ${calendarAddUrl.toString()}
|
|
|
12177
12326
|
// (=立ち上げ直後=この仕組みが一番効く案件)は下で throw するので、
|
|
12178
12327
|
// ここより後に置くと**その案件だけ素通り**する
|
|
12179
12328
|
LIVE_REGISTERED = sanitizeRegisteredNow(j && j.registeredNow);
|
|
12329
|
+
// 🔴 **立ち上げの印も fleet より先に読む(#94)。** 印を持つのは
|
|
12330
|
+
// **新しく作った案件だけ**=まとめ表(fleet-status.json)をまだ持たない案件で、
|
|
12331
|
+
// 下の「fleet が無ければ throw」の経路に入る。ここより後に置くと、
|
|
12332
|
+
// **この節が一番効くはずの案件でだけ**印が出ない
|
|
12333
|
+
LIVE_ONBOARDING = sanitizeOnboardingNow(j && j.registeredNow && j.registeredNow.onboarding);
|
|
12180
12334
|
LIVE_REGISTERED_AT = startedAt;
|
|
12181
12335
|
LIVE_STATE = sanitizeStateNow(j && j.stateNow);
|
|
12182
12336
|
// **欄の有無をそのまま覚える。** sanitize を通した後では「読めて0件」が消える
|
|
@@ -12212,6 +12366,8 @@ ${calendarAddUrl.toString()}
|
|
|
12212
12366
|
syncAiLinks();
|
|
12213
12367
|
// Home を開いていれば「使用ツール」の状態を実測で描き直す(#275)
|
|
12214
12368
|
syncHomeTools();
|
|
12369
|
+
// 立ち上げの申請の印(#94)。**ライブが届いて初めて出る**(それまでは空の受け皿)
|
|
12370
|
+
paintClaudeAppSection();
|
|
12215
12371
|
// 取得中に保存が効いていたら、迂回付きでもう一度取りに行く
|
|
12216
12372
|
if (freshWanted) loadLiveFleet();
|
|
12217
12373
|
})
|
|
@@ -12243,13 +12399,173 @@ ${calendarAddUrl.toString()}
|
|
|
12243
12399
|
// 🔴 **ここでも「使用ツール」を描き直す(#275)。** 実測(stateNow)は fleet より
|
|
12244
12400
|
// 先に読んでいるので、まとめ表を持たない案件でもこの経路で状態が確定する
|
|
12245
12401
|
syncHomeTools();
|
|
12402
|
+
// 🔴 **ここでも印を描き直す(#94)。** まとめ表(fleet-status.json)をまだ
|
|
12403
|
+
// 持たない案件は上で throw してここへ来る——**印を持つのはまさにその案件**なので、
|
|
12404
|
+
// ここに置かないと、この節が一番効くはずの新規案件でだけ何も出ない。
|
|
12405
|
+
// 通信そのものが失敗した回は LIVE_ONBOARDING が null のままで、何も出ない
|
|
12406
|
+
paintClaudeAppSection();
|
|
12246
12407
|
// 取得中に保存が効いていたら、迂回付きでもう一度取りに行く
|
|
12247
12408
|
if (freshWanted) loadLiveFleet();
|
|
12248
12409
|
});
|
|
12249
12410
|
}
|
|
12250
12411
|
|
|
12412
|
+
/* ---------------------------------------------------------------------------
|
|
12413
|
+
* Claude GitHub App の追加申請(#94)
|
|
12414
|
+
* ---------------------------------------------------------------------------
|
|
12415
|
+
* 案件の自動セットアップが終わったあと、「Claude Code からこのリポジトリを使うには
|
|
12416
|
+
* 追加申請が要る」ことを伝える節。承認の完了は機械で検知しないので、
|
|
12417
|
+
* **本人が「申請済み」を押すまで出し続ける。**
|
|
12418
|
+
*
|
|
12419
|
+
* 🔴 **仮置き(notePendingOp / pending-ops / localStorage)は使わない。**
|
|
12420
|
+
* 印の正本は**案件側のファイル**(Cortex/onboarding.json)で、そこへの push は
|
|
12421
|
+
* Cortex/** の変更としてビューアの再ビルドを起こす——つまり静的側もいずれ追いつく。
|
|
12422
|
+
* localStorage に持つと、
|
|
12423
|
+
* - 別の端末・別の人が開いたときに印が戻る(正本が2つになる)
|
|
12424
|
+
* - 案件側のファイルを手で直しても画面が追いつかない
|
|
12425
|
+
* という、正本を1つにすることで避けているズレを自分で作ることになる。
|
|
12426
|
+
* 押した直後の追いつきは loadLiveFleet(true)(据え置きの迂回)1本で足りる。
|
|
12427
|
+
*
|
|
12428
|
+
* 🔴 **出す条件はライブの unrequested だけ。** null(取得前・取得失敗・知らない値)と
|
|
12429
|
+
* requested では帯も行も出さない——取得前に出すと、**印を持たない既存案件で
|
|
12430
|
+
* 一瞬だけ節が出る**(そしてその案件では押しても 404 で断られる)。
|
|
12431
|
+
*
|
|
12432
|
+
* 注: ここは埋め込みJSのテンプレートリテラル内。**コメントでもバッククォートを使わない**
|
|
12433
|
+
* (リテラルが閉じて構文エラーになる。実際にそれで壊した)。
|
|
12434
|
+
* ------------------------------------------------------------------------- */
|
|
12435
|
+
|
|
12436
|
+
/**
|
|
12437
|
+
* 節の中身を作る。**呼ばれるのは unrequested のときだけ**(判定は paint 側)。
|
|
12438
|
+
*
|
|
12439
|
+
* 中身は「見出し・一手の1行・申請文・コピー・申請済み」だけ。
|
|
12440
|
+
* **帯は症状・行は一手・繰り返さない**——申請文に書いてあることを行でもう一度言わない。
|
|
12441
|
+
*/
|
|
12442
|
+
function buildClaudeAppSection(slug) {
|
|
12443
|
+
var sec = el("section", { class: "claude-app" });
|
|
12444
|
+
sec.appendChild(el("h2", { class: "claude-app-head", text: "Claude GitHub App" }));
|
|
12445
|
+
sec.appendChild(el("p", {
|
|
12446
|
+
class: "claude-app-lead",
|
|
12447
|
+
text: "Claude Code からこのリポジトリを使うには、追加申請が必要です。",
|
|
12448
|
+
}));
|
|
12449
|
+
// 申請の宛先。**どこへ出すのかが無いと、文面だけあっても一手にならない**
|
|
12450
|
+
sec.appendChild(el("p", {
|
|
12451
|
+
class: "sec-how",
|
|
12452
|
+
text: "Slack の #tf-github-classmethod で @g-cm-jsys-github-admin 宛てに、下の申請文を貼って依頼してください。",
|
|
12453
|
+
}));
|
|
12454
|
+
// 案件名は SITE.title(画面のタイトル=この案件の表示名)。承認する側が
|
|
12455
|
+
// リポジトリ名だけでは案件を特定できないので、両方を載せる
|
|
12456
|
+
var text = claudeAppRequestText(slug, SITE.title);
|
|
12457
|
+
// 選んで手でコピーできる形にする(コピーボタンが使えない環境のため。ポータルの②と同じ作法)
|
|
12458
|
+
var field = el("textarea", {
|
|
12459
|
+
class: "claude-app-text",
|
|
12460
|
+
readonly: "readonly",
|
|
12461
|
+
spellcheck: "false",
|
|
12462
|
+
rows: "7",
|
|
12463
|
+
});
|
|
12464
|
+
field.value = text;
|
|
12465
|
+
sec.appendChild(field);
|
|
12466
|
+
var msg = el("div", { class: "ds-toggle-msg" });
|
|
12467
|
+
var copyBtn = el("button", { class: "ds-toggle-btn", type: "button", text: "コピー" });
|
|
12468
|
+
copyBtn.addEventListener("click", function () {
|
|
12469
|
+
// コピーの作法は realtimeSyncCard と同じ(clipboard API → 選択 → 手でコピーの案内)。
|
|
12470
|
+
// **黙って何も起きないにしない**
|
|
12471
|
+
var done = function () { msg.className = "ds-toggle-msg is-ok"; msg.textContent = "✓ コピーしました。"; };
|
|
12472
|
+
var fallback = function () {
|
|
12473
|
+
try {
|
|
12474
|
+
field.focus();
|
|
12475
|
+
field.select();
|
|
12476
|
+
if (document.execCommand && document.execCommand("copy")) return done();
|
|
12477
|
+
} catch (e) { /* 下の案内へ */ }
|
|
12478
|
+
msg.className = "ds-toggle-msg is-error";
|
|
12479
|
+
msg.textContent = "⚠ 自動コピーできませんでした。選択された文字列を手でコピーしてください。";
|
|
12480
|
+
};
|
|
12481
|
+
try {
|
|
12482
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
12483
|
+
navigator.clipboard.writeText(text).then(done, fallback);
|
|
12484
|
+
} else fallback();
|
|
12485
|
+
} catch (e) { fallback(); }
|
|
12486
|
+
});
|
|
12487
|
+
var doneBtn = el("button", { class: "ds-toggle-btn", type: "button", text: "申請済み" });
|
|
12488
|
+
doneBtn.addEventListener("click", function () { markClaudeAppRequested(doneBtn, msg); });
|
|
12489
|
+
sec.appendChild(el("div", { class: "claude-app-actions" }, [copyBtn, doneBtn, msg]));
|
|
12490
|
+
return sec;
|
|
12491
|
+
}
|
|
12492
|
+
|
|
12493
|
+
/**
|
|
12494
|
+
* 「申請済み」を押したとき。
|
|
12495
|
+
*
|
|
12496
|
+
* **sendConfig は通さない。** あちらは成功のたびに仮置き(notePendingOp)を書く
|
|
12497
|
+
* 経路で、この機能は仮置きを持たないと決めてある(上の項)。使うのは同じ callIntake。
|
|
12498
|
+
*
|
|
12499
|
+
* 成功したら**その場で節を1行に差し替え**(押した手応えを返す)、
|
|
12500
|
+
* loadLiveFleet(true) で正本を取り直す。失敗したら**サーバーが返した文をそのまま出す**
|
|
12501
|
+
* ——ファイルを持たない案件の 404 の文面も、そのまま読めば何が無いのか分かる。
|
|
12502
|
+
*/
|
|
12503
|
+
async function markClaudeAppRequested(btn, msg) {
|
|
12504
|
+
if (!SITE.intake) return;
|
|
12505
|
+
var endBusy = beginBusy(btn);
|
|
12506
|
+
msg.className = "ds-toggle-msg";
|
|
12507
|
+
msg.textContent = "保存中…";
|
|
12508
|
+
try {
|
|
12509
|
+
var res = await callIntake("config", { op: "claude-app-requested" });
|
|
12510
|
+
var j = await res.json().catch(function () { return {}; });
|
|
12511
|
+
if (!res.ok) {
|
|
12512
|
+
msg.className = "ds-toggle-msg is-error";
|
|
12513
|
+
msg.textContent = "✗ " + (j.message || "保存できませんでした。");
|
|
12514
|
+
endBusy();
|
|
12515
|
+
return;
|
|
12516
|
+
}
|
|
12517
|
+
// **節ごと1行に差し替える。** 申請文もボタンも役目を終えているので残さない。
|
|
12518
|
+
// 旗を先に立てるのは、下の取り直しが届いたときの描き直しでも1行のままにするため
|
|
12519
|
+
CLAUDE_APP_DONE = true;
|
|
12520
|
+
paintClaudeAppSection();
|
|
12521
|
+
// **正本を取り直す**(据え置きを迂回)。ここで印は requested になり、
|
|
12522
|
+
// 次に描き直したときには節が出ない
|
|
12523
|
+
loadLiveFleet(true);
|
|
12524
|
+
} catch (e) {
|
|
12525
|
+
msg.className = "ds-toggle-msg is-error";
|
|
12526
|
+
msg.textContent = "✗ 通信に失敗しました。";
|
|
12527
|
+
endBusy();
|
|
12528
|
+
}
|
|
12529
|
+
}
|
|
12530
|
+
|
|
12531
|
+
/**
|
|
12532
|
+
* 節を描き直す。**冪等**(何度呼んでも同じ状態に落ち着く)。
|
|
12533
|
+
*
|
|
12534
|
+
* ライブの応答は操作タブを描いたあとに届くので、loadLiveFleet の成功・失敗の
|
|
12535
|
+
* どちらからも呼ぶ(届くまでは受け皿が空のまま=何も出ない)。
|
|
12536
|
+
*/
|
|
12537
|
+
function paintClaudeAppSection() {
|
|
12538
|
+
var slot = app.querySelector(".claude-app-slot");
|
|
12539
|
+
if (!slot) return;
|
|
12540
|
+
slot.textContent = "";
|
|
12541
|
+
// 🔴 **正本が追いついたら旗を落とす。** 落とさないと「✓ 申請済みとして記録しました。」が
|
|
12542
|
+
// リロードするまでセッション中ずっと残る——旗は「正本が届くまでのつなぎ」でしかない。
|
|
12543
|
+
// 落とせば、押した経路も最初から requested だった経路も**同じ「何も出ない」**に落ち着く
|
|
12544
|
+
if (LIVE_ONBOARDING && LIVE_ONBOARDING.claudeGithubApp === "requested") CLAUDE_APP_DONE = false;
|
|
12545
|
+
// 押した直後(サーバが保存を確定した)は、正本が届く前でも1行だけ残す。
|
|
12546
|
+
// **正本が requested を返せば、この旗が無くても同じ「何も出ない」に落ち着く**
|
|
12547
|
+
if (CLAUDE_APP_DONE) {
|
|
12548
|
+
slot.appendChild(el("section", { class: "claude-app" }, [
|
|
12549
|
+
el("p", { class: "claude-app-done", text: "✓ 申請済みとして記録しました。" }),
|
|
12550
|
+
]));
|
|
12551
|
+
return;
|
|
12552
|
+
}
|
|
12553
|
+
// 🔴 **ライブの unrequested のときだけ。** null・未取得・requested では何も出さない
|
|
12554
|
+
if (!LIVE_ONBOARDING || LIVE_ONBOARDING.claudeGithubApp !== "unrequested") return;
|
|
12555
|
+
// 申請文にリポジトリ名を埋められないなら、押しても宛先の分からない依頼になる
|
|
12556
|
+
var slug = claudeAppRepoSlug(SITE.repoBaseUrl);
|
|
12557
|
+
if (!slug) return;
|
|
12558
|
+
// 押す先(intake)が無い構成では、押せないボタンだけを出さない
|
|
12559
|
+
if (!SITE.intake) return;
|
|
12560
|
+
slot.appendChild(buildClaudeAppSection(slug));
|
|
12561
|
+
}
|
|
12562
|
+
|
|
12251
12563
|
function renderOps() {
|
|
12252
12564
|
renderConnMap();
|
|
12565
|
+
// 🔴 **受け皿は接続マップの直後・「データソースと自動化」より前**(利用者が最初に見る位置)。
|
|
12566
|
+
// 中身が入るのはライブの応答が届いてからで、それまでは**空の受け皿**=何も出ない
|
|
12567
|
+
app.appendChild(el("div", { class: "claude-app-slot" }));
|
|
12568
|
+
paintClaudeAppSection();
|
|
12253
12569
|
// 🔴 **先読みが飛行中なら、いま作った図を確認中へ倒す(#264)。**
|
|
12254
12570
|
// 先読み(起動時の loadLiveFleet)は操作タブを開く前に走るので、
|
|
12255
12571
|
// 確認中へ倒す口(loadLiveFleet の connMapConfirmingShown の1回)は
|
package/package.json
CHANGED