@takagaki/cortex-decisions-viewer 0.12.27 → 0.12.29
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 +232 -11
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -2167,6 +2167,10 @@ a:hover { text-decoration: underline; }
|
|
|
2167
2167
|
}
|
|
2168
2168
|
.site-title { font-size: 18px; font-weight: 700; color: var(--text); }
|
|
2169
2169
|
.site-title:hover { text-decoration: none; color: var(--accent); }
|
|
2170
|
+
/* ポータル配下で開いているとき(#379)、案件名はポータルの案件一覧(同一オリジンの /)へ
|
|
2171
|
+
戻るリンクになる。**文言は増やさない**(案件名そのものがリンク)ので、押せることは
|
|
2172
|
+
ホバーの下線で示す。丸(アイコン操作)とは別の口 */
|
|
2173
|
+
.site-title.site-title-portal:hover { text-decoration: underline; text-underline-offset: 3px; }
|
|
2170
2174
|
/* ---- 案件アイコン(#348)----
|
|
2171
2175
|
**ヘッダーの案件名の左に丸を置く。** ヘッダーは全タブ共通なので、
|
|
2172
2176
|
どのタブを開いていても同じ場所に居る。0.12.24 で Home 本文に置いた
|
|
@@ -2219,6 +2223,12 @@ button.site-icon[aria-expanded="true"] .site-icon-hover { opacity: 1; }
|
|
|
2219
2223
|
——押せない丸に指差しカーソルやリングを出すのが、画面の嘘のうちで一番たちが悪い */
|
|
2220
2224
|
button.site-icon { cursor: pointer; }
|
|
2221
2225
|
button.site-icon:hover, button.site-icon[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--accent); }
|
|
2226
|
+
/* **保存中(#378)は丸の上に .busy-overlay(共通部品)が載る。** その間はホバーの「変更」「+」
|
|
2227
|
+
もリングも出さない(スピナーと重なって読めない・押せるように見せない)。
|
|
2228
|
+
ホバー規則と同じ強さなので、**この行はホバー規則より後に置く** */
|
|
2229
|
+
button.site-icon[aria-busy="true"] { cursor: wait; box-shadow: none; }
|
|
2230
|
+
button.site-icon[aria-busy="true"] .site-icon-hover,
|
|
2231
|
+
button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
2222
2232
|
.site-icon-img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
|
|
2223
2233
|
/* 丸を押したときだけ出るメニュー。スロットを基準に浮かせる(ヘッダーは sticky なので
|
|
2224
2234
|
ページを送っても位置がずれない) */
|
|
@@ -3267,6 +3277,28 @@ button.ops-card-btn:disabled { opacity: .6; cursor: default; }
|
|
|
3267
3277
|
.toast-show { opacity: 1; }
|
|
3268
3278
|
.toast-error { background: #b91c1c; }
|
|
3269
3279
|
|
|
3280
|
+
/* 反映待ちのオーバーレイ+スピナー(#378・共通部品。JS の beginOverlaySpinner が載せる)。
|
|
3281
|
+
押した瞬間から結果が返るまで、**押した場所そのものの上に**半透明の白(60%)と
|
|
3282
|
+
ぐるぐるを重ねる——押した反応が無いように見えて押し直す(二重送信)のを止める。
|
|
3283
|
+
載せ先の大きさは変えない(absolute で内側に重ね、角丸は載せ先から継ぐ)。
|
|
3284
|
+
いまは案件アイコンの丸にだけ使う。操作タブの保存にも同じ部品を使える */
|
|
3285
|
+
.busy-overlay {
|
|
3286
|
+
position: absolute; top: 0; left: 0; right: 0; bottom: 0; border-radius: inherit;
|
|
3287
|
+
display: flex; align-items: center; justify-content: center;
|
|
3288
|
+
background: rgba(255, 255, 255, .6); cursor: wait; z-index: 2;
|
|
3289
|
+
}
|
|
3290
|
+
.busy-spinner {
|
|
3291
|
+
width: 18px; height: 18px; border-radius: 50%;
|
|
3292
|
+
border: 2px solid var(--accent-weak); border-top-color: var(--accent);
|
|
3293
|
+
animation: busy-spin .8s linear infinite;
|
|
3294
|
+
}
|
|
3295
|
+
@keyframes busy-spin { to { transform: rotate(360deg); } }
|
|
3296
|
+
/* 読み上げ用の語(「保存中…」)。目には見せない(文言を増やさない) */
|
|
3297
|
+
.busy-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
3298
|
+
/* 動きを減らす設定でも止めはしない——止めると「保存中」と「固まった」の区別が付かない。
|
|
3299
|
+
回転を半分の速さに落とすだけ */
|
|
3300
|
+
@media (prefers-reduced-motion: reduce) { .busy-spinner { animation-duration: 1.6s; } }
|
|
3301
|
+
|
|
3270
3302
|
.site-footer { max-width: 960px; margin: 0 auto; padding: 0 20px 40px; color: var(--muted); font-size: 12px; }
|
|
3271
3303
|
|
|
3272
3304
|
@media (max-width: 600px) {
|
|
@@ -4404,6 +4436,27 @@ ${deriveCapTile.toString()}
|
|
|
4404
4436
|
// document に付ける開閉のリスナーは1組だけ。描き直しのたびに足すと Escape 1回で
|
|
4405
4437
|
// 同じ処理が何度も走る(見た目は同じなので気づけない)
|
|
4406
4438
|
var siteIconGlobalBound = false;
|
|
4439
|
+
// 保存中か(画像を選ぶ/変える/外す の3段が走っている間)。**DOM ではなくこの変数が正本**
|
|
4440
|
+
// (#378)。描き直しで丸が作り直されても、renderSiteIcon がこれを見てオーバーレイを付け直す。
|
|
4441
|
+
// setProjectIcon / removeProjectIcon の入口で見て、走っている間の2回目を捨てる(二重送信防止)
|
|
4442
|
+
var siteIconSaving = false;
|
|
4443
|
+
// いま丸に載っているオーバーレイの外し方(無ければ null)
|
|
4444
|
+
var siteIconBusyEnd = null;
|
|
4445
|
+
|
|
4446
|
+
/**
|
|
4447
|
+
* 丸の保存中の見た目を付ける/外す。丸は disabled にして押せなくする
|
|
4448
|
+
* (メニューの開閉もここで止まる。丸のクリックは siteIconSaving でも見る)
|
|
4449
|
+
*/
|
|
4450
|
+
function setSiteIconBusy(circle, on) {
|
|
4451
|
+
if (siteIconBusyEnd) { siteIconBusyEnd(); siteIconBusyEnd = null; }
|
|
4452
|
+
if (!circle) return;
|
|
4453
|
+
if (on) {
|
|
4454
|
+
siteIconBusyEnd = beginOverlaySpinner(circle, "保存中…");
|
|
4455
|
+
circle.disabled = true;
|
|
4456
|
+
} else {
|
|
4457
|
+
circle.disabled = false;
|
|
4458
|
+
}
|
|
4459
|
+
}
|
|
4407
4460
|
|
|
4408
4461
|
/**
|
|
4409
4462
|
* 案件名の頭文字1字。**ポータルの ProjectIcon.tsx(initialOf)と同じ取り方**にする
|
|
@@ -4486,8 +4539,16 @@ ${deriveCapTile.toString()}
|
|
|
4486
4539
|
}
|
|
4487
4540
|
slot.appendChild(circle);
|
|
4488
4541
|
if (!intake) return;
|
|
4489
|
-
|
|
4490
|
-
|
|
4542
|
+
// 保存中に描き直されても、オーバーレイと押せない状態を引き継ぐ(正本は siteIconSaving)。
|
|
4543
|
+
// いまの呼び出し経路(起動時1回・ui.busy(false) の後の redraw)では保存中に来ないので
|
|
4544
|
+
// 防御。将来タブ切り替え等でヘッダーを描き直すようになっても、ぐるぐるが消えない
|
|
4545
|
+
if (siteIconSaving) setSiteIconBusy(circle, true);
|
|
4546
|
+
|
|
4547
|
+
circle.addEventListener("click", function () {
|
|
4548
|
+
// 保存中は丸が disabled なので click 自体が飛ばない(ブラウザの既定)。これは防御
|
|
4549
|
+
if (siteIconSaving) return;
|
|
4550
|
+
setSiteIconMenu(!siteIconMenuOpen);
|
|
4551
|
+
});
|
|
4491
4552
|
|
|
4492
4553
|
var menu = el("div", { class: "site-icon-menu", role: "menu" });
|
|
4493
4554
|
if (!siteIconMenuOpen) menu.setAttribute("hidden", "");
|
|
@@ -4497,6 +4558,11 @@ ${deriveCapTile.toString()}
|
|
|
4497
4558
|
// 丸へ戻す(キーボードの人が位置を失わない。Escape は document 側なので効く)
|
|
4498
4559
|
redraw: function () {
|
|
4499
4560
|
renderSiteIcon();
|
|
4561
|
+
ui.refocus();
|
|
4562
|
+
},
|
|
4563
|
+
// 丸へフォーカスを戻す。失敗のあとも呼ぶ——押していた項目は disabled にした瞬間に
|
|
4564
|
+
// フォーカスを失って body に落ちるので、戻さないとキーボードの人がやり直す位置を失う
|
|
4565
|
+
refocus: function () {
|
|
4500
4566
|
var s = document.getElementById("site-icon-slot");
|
|
4501
4567
|
var c = s && s.querySelector("button.site-icon");
|
|
4502
4568
|
if (c && typeof c.focus === "function") c.focus();
|
|
@@ -4504,10 +4570,14 @@ ${deriveCapTile.toString()}
|
|
|
4504
4570
|
input: null,
|
|
4505
4571
|
buttons: [],
|
|
4506
4572
|
};
|
|
4507
|
-
//
|
|
4573
|
+
// 送信中は全部を止める(#378: 丸にオーバーレイ+スピナー・丸とメニューを押せなくする)。
|
|
4574
|
+
// **元から押せない項目は押せないまま戻す**——
|
|
4508
4575
|
// 未設定の「画像を外す」が、失敗して戻ったときだけ押せるようになるのを防ぐ
|
|
4509
|
-
ui.
|
|
4576
|
+
ui.busy = function (flag) {
|
|
4577
|
+
siteIconSaving = !!flag;
|
|
4510
4578
|
ui.buttons.forEach(function (b) { b.disabled = flag ? true : !!b.lockedOff; });
|
|
4579
|
+
var s = document.getElementById("site-icon-slot");
|
|
4580
|
+
setSiteIconBusy(s && s.querySelector("button.site-icon"), siteIconSaving);
|
|
4511
4581
|
};
|
|
4512
4582
|
|
|
4513
4583
|
var input = el("input", { type: "file", accept: "image/png,image/jpeg,image/webp", hidden: "" });
|
|
@@ -4559,7 +4629,9 @@ ${deriveCapTile.toString()}
|
|
|
4559
4629
|
* ものを送ると、1MB を上げきってから「大きすぎます」と言うことになる
|
|
4560
4630
|
*/
|
|
4561
4631
|
async function setProjectIcon(file, ui) {
|
|
4562
|
-
|
|
4632
|
+
// 走っている間の2回目は捨てる(丸もメニューも止めてあるが、正本はこの変数)
|
|
4633
|
+
if (siteIconSaving) return;
|
|
4634
|
+
function fail(msg) { showToast("✗ " + msg, true); ui.busy(false); ui.refocus(); }
|
|
4563
4635
|
// 画面側の門。**サーバ側と同じ文言**で、送る前に断る(fail で「✗ 」を揃える)
|
|
4564
4636
|
if (!projectIconExtOfName(file.name)) return fail("PNG・JPEG・WebP の画像を選んでください");
|
|
4565
4637
|
if (file.size > PROJECT_ICON_MAX_BYTES) return fail("1MB までの画像を選んでください");
|
|
@@ -4567,7 +4639,8 @@ ${deriveCapTile.toString()}
|
|
|
4567
4639
|
|
|
4568
4640
|
var intake = SITE.intake;
|
|
4569
4641
|
var ctype = file.type || "application/octet-stream";
|
|
4570
|
-
|
|
4642
|
+
// 押した瞬間からぐるぐる(#378)。成功なら redraw で新しい丸に、失敗なら fail で元の丸に戻る
|
|
4643
|
+
ui.busy(true);
|
|
4571
4644
|
|
|
4572
4645
|
var pres;
|
|
4573
4646
|
try {
|
|
@@ -4602,6 +4675,7 @@ ${deriveCapTile.toString()}
|
|
|
4602
4675
|
// **同じファイルをもう一度選べるようにする。** value を戻さないと、選び直しても
|
|
4603
4676
|
// change が飛ばない(形式で断られた直後に選び直す経路がここで死ぬ)
|
|
4604
4677
|
if (ui.input) ui.input.value = "";
|
|
4678
|
+
ui.busy(false);
|
|
4605
4679
|
// 丸がその場で変わるので、メニューは畳んでよい(結果はトーストが伝える)
|
|
4606
4680
|
setSiteIconMenu(false);
|
|
4607
4681
|
ui.redraw();
|
|
@@ -4610,14 +4684,17 @@ ${deriveCapTile.toString()}
|
|
|
4610
4684
|
|
|
4611
4685
|
/** 画像を外す。**確認は出さない**——押し間違えても、もう一度選び直せば戻る操作 */
|
|
4612
4686
|
async function removeProjectIcon(ui) {
|
|
4613
|
-
|
|
4614
|
-
|
|
4687
|
+
// 保存中はメニューの項目が disabled なので普通は来ない(setProjectIcon と同じ防御)
|
|
4688
|
+
if (siteIconSaving) return;
|
|
4689
|
+
function fail(msg) { showToast("✗ " + msg, true); ui.busy(false); ui.refocus(); }
|
|
4690
|
+
ui.busy(true);
|
|
4615
4691
|
var res;
|
|
4616
4692
|
try {
|
|
4617
4693
|
res = await intakeJson(callIntake("project-icon-remove", { projectKey: SITE.intake.projectKey }));
|
|
4618
4694
|
} catch (net) { return fail("サーバーに接続できませんでした。通信環境を確認して、もう一度お試しください。"); }
|
|
4619
4695
|
if (!res.ok) return fail((res.j && res.j.message) || "外せませんでした");
|
|
4620
4696
|
rememberIconPending("remove", "");
|
|
4697
|
+
ui.busy(false);
|
|
4621
4698
|
setSiteIconMenu(false);
|
|
4622
4699
|
ui.redraw();
|
|
4623
4700
|
showToast("外しました", false);
|
|
@@ -4950,8 +5027,8 @@ ${deriveCapTile.toString()}
|
|
|
4950
5027
|
};
|
|
4951
5028
|
/**
|
|
4952
5029
|
* 表を引くときのアダプタ種別。**probeTypeOf を使わない**——あちらは「op=probe の受け口」の
|
|
4953
|
-
*
|
|
4954
|
-
*
|
|
5030
|
+
* 語彙で、「github-issues」 / 「github-discussions」 を 「github」 に畳むところまでは同じだが、
|
|
5031
|
+
* **実測の口が無い種別に空文字を返す**(この表は実測の有無と無関係にエントリを置く)
|
|
4955
5032
|
*/
|
|
4956
5033
|
function helpTypeOf(type) {
|
|
4957
5034
|
var t = String(type || "");
|
|
@@ -5318,6 +5395,18 @@ ${deriveCapTile.toString()}
|
|
|
5318
5395
|
* 読み取れない——下の説明文は「誰が承認できるか」の話しかしていない。
|
|
5319
5396
|
* 1行だけ添える口を開けておく。**見出しは付けない**(節を増やすと一覧が遠くなる)。
|
|
5320
5397
|
*
|
|
5398
|
+
* ## 承認画面から戻ってきたとき(#343)
|
|
5399
|
+
*
|
|
5400
|
+
* 成功経路は同じタブで遷移するので、**このハンドラには戻す機会が無い**——
|
|
5401
|
+
* 「準備しています…」と disabled を立てたまま画面を離れる。ブラウザバックで
|
|
5402
|
+
* 戻ると bfcache が**離脱直前の DOM とスクリプトの状態をそのまま復元する**ので、
|
|
5403
|
+
* その固まった見た目が再現し、もう一度押せなくなる。だから復帰は
|
|
5404
|
+
* bfcache 復元でだけ発火する pageshow(persisted)で受ける。
|
|
5405
|
+
* 戻す口は**起動時に1本だけ張った listener が data-leaving を DOM から探す**形にした
|
|
5406
|
+
* ——モーダルを開くたびにこのボタンは作り直されるので、登録簿に貯めると
|
|
5407
|
+
* 閉じたモーダルの DOM を掴み続ける。印を付けるのは遷移が確定した瞬間だけで、
|
|
5408
|
+
* 失敗経路(その場でボタンを戻す)には付けない。
|
|
5409
|
+
*
|
|
5321
5410
|
* @param lead 省略可。押す理由の1行(案内の中から呼ぶときは渡さない)
|
|
5322
5411
|
*/
|
|
5323
5412
|
function slackConnectButton(lead) {
|
|
@@ -5346,6 +5435,11 @@ ${deriveCapTile.toString()}
|
|
|
5346
5435
|
}
|
|
5347
5436
|
// **同じタブで遷移する。** 別タブだと、承認後の「接続しました」を見た人が
|
|
5348
5437
|
// 元のタブに戻る動線を自分で見つけることになる
|
|
5438
|
+
//
|
|
5439
|
+
// **遷移が確定したこの瞬間にだけ印を付ける(#343)。** ブラウザバックで
|
|
5440
|
+
// bfcache から復元されたとき、起動時の pageshow の listener がこの印を頼りに
|
|
5441
|
+
// ボタンと「準備しています…」を素の状態へ戻す(restoreLeavingButtons)
|
|
5442
|
+
btn.setAttribute("data-leaving", "1");
|
|
5349
5443
|
location.href = j.url;
|
|
5350
5444
|
} catch (e) {
|
|
5351
5445
|
msg.className = "ds-toggle-msg is-error";
|
|
@@ -7784,6 +7878,10 @@ ${deriveCapTile.toString()}
|
|
|
7784
7878
|
* **開発(GitHub)は #234 で足した。** 判定は shared/github-gate.mjs、次の一手は
|
|
7785
7879
|
* サーバの needed(理由と設定ページのURLを1文で持つ)をそのまま出している
|
|
7786
7880
|
* ——画面に分岐が生まれないよう、言い分けを全部あちらに置いた
|
|
7881
|
+
*
|
|
7882
|
+
* **Google Chat は #347 で足した。** 判定は shared/google-chat-gate.mjs で、夜間の実測と
|
|
7883
|
+
* 同じ叩き先・同じスコープで測る。次の一手(googleChatProbeHelpNodes)は行の常時表示と
|
|
7884
|
+
* 同じ表(DS_GATE の help)から引くだけで、画面に判定の分岐は無い
|
|
7787
7885
|
* ------------------------------------------------------------------------- */
|
|
7788
7886
|
|
|
7789
7887
|
/**
|
|
@@ -7802,9 +7900,13 @@ ${deriveCapTile.toString()}
|
|
|
7802
7900
|
* 確認したいアダプタの種別(「op=probe」 の 「type」)。**画面の種別をそのまま送らない**
|
|
7803
7901
|
* ——「github-issues」 / 「github-discussions」 は同じ1つのリポジトリの読み取りで、
|
|
7804
7902
|
* サーバの受け口は 「github」 の1種別しか知らない(「PROBE_REF_RULES」)。
|
|
7903
|
+
*
|
|
7904
|
+
* **空文字を返した種別にはボタンが出ない**(下の 「extSourceCard」 の条件)。
|
|
7905
|
+
* Google Chat は #347 で足した——サーバの受け口の綴りがそのまま種別になる。
|
|
7805
7906
|
*/
|
|
7806
7907
|
function probeTypeOf(type) {
|
|
7807
7908
|
if (String(type || "").indexOf("github") === 0) return "github";
|
|
7909
|
+
if (type === "google-chat") return "google-chat";
|
|
7808
7910
|
return type === "slack" ? "slack" : "";
|
|
7809
7911
|
}
|
|
7810
7912
|
|
|
@@ -7859,6 +7961,36 @@ ${deriveCapTile.toString()}
|
|
|
7859
7961
|
return [el("p", { class: "ds-probe-help", text: "GitHub の応答:" + (r.error || "不明") + "。時間をおいて再度お試しください。" })];
|
|
7860
7962
|
}
|
|
7861
7963
|
|
|
7964
|
+
/**
|
|
7965
|
+
* Google Chat の確認結果の本文(#347)。
|
|
7966
|
+
*
|
|
7967
|
+
* **判定は infra/lambda/shared/google-chat-gate.mjs にしか無い。** ここが返すのは
|
|
7968
|
+
* 「次の一手」だけで、状態の語(バッジ)は probeVerdict が dsGateOf から取る。
|
|
7969
|
+
*
|
|
7970
|
+
* **文を書き写さない。** 「アプリと統合から追加してください」「管理者の設定が済むと…」は
|
|
7971
|
+
* 行の常時表示(DS_GATE の 「help」)が既に持っている——写経すると、同じ行の常時表示と
|
|
7972
|
+
* 押した結果で語が割れる(この節が何度も直してきた形)。DS_GATE から引いて1文だけ出す。
|
|
7973
|
+
*
|
|
7974
|
+
* ⚠ **403(Workspace 管理者の承認待ち)は Phase 0 の採取まで 「unknown」。** その回は
|
|
7975
|
+
* サーバの機械語(「permission_denied」)をそのまま出す。**「時間をおいて」と言わない**
|
|
7976
|
+
* ——待っても直らない(管理者が承認するまで同じ応答が返る)。
|
|
7977
|
+
*/
|
|
7978
|
+
function googleChatProbeHelpNodes(s, r) {
|
|
7979
|
+
var p = function (t) { return el("p", { class: "ds-probe-help", text: t }); };
|
|
7980
|
+
// 成功。**1行で終わり**(状態の語が既に「接続OK」と出ている)
|
|
7981
|
+
if (r.gate === "ok") return [];
|
|
7982
|
+
// not_in_space / no_credentials は行の常時表示と同じ1文(DS_GATE から引く)。
|
|
7983
|
+
// 押した瞬間に行側の 「.ds-gate-help」 は隠れるので、二重には出ない
|
|
7984
|
+
var help = dsGateOf({ type: s.type, gate: r.gate }).help;
|
|
7985
|
+
if (help) return [p(help)];
|
|
7986
|
+
if (r.gate === "unreachable") {
|
|
7987
|
+
// 帯(「アクセス不可」)が症状を言っている。**ここは一手だけ**
|
|
7988
|
+
return [p("時間をおいて、もう一度「接続を確認」を押してください。")];
|
|
7989
|
+
}
|
|
7990
|
+
// unknown。**生の機械語を隠さない**——「不明」だけだと切り分けが始められない
|
|
7991
|
+
return [p("Google Chat の応答:" + (r.error || "不明") + "。cortex の担当者にこの語をお伝えください。")];
|
|
7992
|
+
}
|
|
7993
|
+
|
|
7862
7994
|
/**
|
|
7863
7995
|
* 「アクセス不可」の次の一手(0.12.2・実オンボーディングで踏んだ)。
|
|
7864
7996
|
*
|
|
@@ -7935,6 +8067,7 @@ ${deriveCapTile.toString()}
|
|
|
7935
8067
|
function probeHelpNodes(s, r) {
|
|
7936
8068
|
var p = function (t) { return el("p", { class: "ds-probe-help", text: t }); };
|
|
7937
8069
|
if (probeTypeOf(s.type) === "github") return githubProbeHelpNodes(r);
|
|
8070
|
+
if (probeTypeOf(s.type) === "google-chat") return googleChatProbeHelpNodes(s, r);
|
|
7938
8071
|
// 成功。**1行で終わり。** 状態の語(「接続OK」)が既に出ているので本文は空
|
|
7939
8072
|
if (r.gate === "ok") return [];
|
|
7940
8073
|
if (r.gate === "not_in_channel") {
|
|
@@ -9380,6 +9513,48 @@ ${deriveCapTile.toString()}
|
|
|
9380
9513
|
};
|
|
9381
9514
|
}
|
|
9382
9515
|
|
|
9516
|
+
/**
|
|
9517
|
+
* 反映待ちのオーバーレイ+スピナー(#378・共通部品)。
|
|
9518
|
+
*
|
|
9519
|
+
* host の**上に**半透明の白(60%)とぐるぐるを重ねる。host の大きさは変えない。
|
|
9520
|
+
* 角丸は host から継ぐので、丸(案件アイコン)でも四角(操作タブのカード・ボタン)でも
|
|
9521
|
+
* 使える。beginBusy が「語を差し替える」形なのに対し、こちらは**語を置けない場所
|
|
9522
|
+
* (画像だけの丸など)**向け。
|
|
9523
|
+
*
|
|
9524
|
+
* **載せ先が static でも壊れない。** オーバーレイは absolute なので、載せ先に
|
|
9525
|
+
* position が無いと**別の祖先いっぱいに広がる**(黙って壊れる)。その場合だけ
|
|
9526
|
+
* relative を入れ、外すときに戻す(案件アイコンの丸は元から relative なので触らない)。
|
|
9527
|
+
*
|
|
9528
|
+
* 支援技術には host の aria-busy で「処理中」を伝える。label は目に見えない語として
|
|
9529
|
+
* 置くだけ(挿入と同時に中身を入れたライブリージョンは読まれないことが多い)。
|
|
9530
|
+
*
|
|
9531
|
+
* @returns 外す関数。beginBusy と同じく**何度呼んでも1回しか効かない**
|
|
9532
|
+
*/
|
|
9533
|
+
function beginOverlaySpinner(host, label) {
|
|
9534
|
+
if (!host) return function () {};
|
|
9535
|
+
var madeRelative = false;
|
|
9536
|
+
try {
|
|
9537
|
+
if (window.getComputedStyle(host).position === "static") {
|
|
9538
|
+
host.style.position = "relative";
|
|
9539
|
+
madeRelative = true;
|
|
9540
|
+
}
|
|
9541
|
+
} catch (e) {}
|
|
9542
|
+
var ov = el("span", { class: "busy-overlay" }, [
|
|
9543
|
+
el("span", { class: "busy-spinner", "aria-hidden": "true" }),
|
|
9544
|
+
el("span", { class: "busy-label", text: label || "処理中…" }),
|
|
9545
|
+
]);
|
|
9546
|
+
host.appendChild(ov);
|
|
9547
|
+
host.setAttribute("aria-busy", "true");
|
|
9548
|
+
var used = false;
|
|
9549
|
+
return function endOverlaySpinner() {
|
|
9550
|
+
if (used) return;
|
|
9551
|
+
used = true;
|
|
9552
|
+
if (ov.parentNode) ov.parentNode.removeChild(ov);
|
|
9553
|
+
host.removeAttribute("aria-busy");
|
|
9554
|
+
if (madeRelative) host.style.position = "";
|
|
9555
|
+
};
|
|
9556
|
+
}
|
|
9557
|
+
|
|
9383
9558
|
/**
|
|
9384
9559
|
* サーバへ設定変更を送る。**一覧は書き換えない**
|
|
9385
9560
|
* (接続状況は夜間バッチのスナップショットなので、「もう効いている」と誤解させないため)。
|
|
@@ -10085,10 +10260,12 @@ ${deriveCapTile.toString()}
|
|
|
10085
10260
|
// 気づいた人がその場で確かめられるほうがよい(オーナー判断)。書き込みになる
|
|
10086
10261
|
// 「表示名を更新する」は、押した結果の中から別のボタンとして出る(probeSection)。
|
|
10087
10262
|
//
|
|
10088
|
-
// **いまは Slack
|
|
10263
|
+
// **いまは Slack・開発(GitHub)・Google Chat。** GitHub は #234 で足した——「アクセス不可 →
|
|
10089
10264
|
// App の Configure でリポジトリを追加 → 直ったか確かめる」が、それまで**翌朝まで
|
|
10090
10265
|
// 待つしかなかった**(受け入れテストでは fleet-status.yml を手で起動して確かめた)。
|
|
10091
10266
|
// 判定と文面は infra/lambda/shared/github-gate.mjs 側(画面に分岐を持たせない)。
|
|
10267
|
+
// **Google Chat は #347(同じ理由)。** スペースにアプリを追加した人が、その場で
|
|
10268
|
+
// 直ったことを確かめられる。判定は infra/lambda/shared/google-chat-gate.mjs 側。
|
|
10092
10269
|
// Backlog / Figma / Drive は実測そのものが新規なので、まだ出さない。
|
|
10093
10270
|
//
|
|
10094
10271
|
// **origin === "explicit" でも出す。** 確認は読むだけで、どの登録ファイル由来かに
|
|
@@ -13485,6 +13662,50 @@ ${deriveCapTile.toString()}
|
|
|
13485
13662
|
}
|
|
13486
13663
|
|
|
13487
13664
|
window.addEventListener("popstate", route);
|
|
13665
|
+
/**
|
|
13666
|
+
* ヘッダーの案件名(#379)。**ポータル配下(/p/<key>/ の下)で開いているときだけ**、
|
|
13667
|
+
* ポータルの案件一覧(同一オリジンの /)へ戻るリンクにする。
|
|
13668
|
+
* Basic 認証の Amplify で開いているときは戻る先が無いので、これまでどおり(href="?")。
|
|
13669
|
+
* 文言は増やさない——案件名そのものがリンクで、説明は title 属性だけ。
|
|
13670
|
+
* 丸(アイコン操作)とは別の口なので、renderSiteIcon には触らない
|
|
13671
|
+
*/
|
|
13672
|
+
(function linkTitleToPortal() {
|
|
13673
|
+
var a = document.getElementById("home-link");
|
|
13674
|
+
if (!a || !/^\\/p\\/[^/]+\\//.test(location.pathname)) return;
|
|
13675
|
+
a.setAttribute("href", "/");
|
|
13676
|
+
a.setAttribute("title", "案件一覧へ");
|
|
13677
|
+
a.classList.add("site-title-portal");
|
|
13678
|
+
})();
|
|
13679
|
+
/**
|
|
13680
|
+
* 外部の承認画面へ送り出したボタンを、戻ってきたときに押せる状態へ戻す(#343)。
|
|
13681
|
+
*
|
|
13682
|
+
* **live DOM を走査する。** 押した時点で登録簿に貯める形にすると、モーダルの
|
|
13683
|
+
* 開閉ごとに作り直されるボタンの、閉じた側の DOM を掴み続ける。
|
|
13684
|
+
* 戻す先は**素の初期状態**——「中断しました」のような文言は足さない
|
|
13685
|
+
*(戻ってきた人が知りたいのは「もう一度押せる」ことで、それは見た目で分かる)。
|
|
13686
|
+
*/
|
|
13687
|
+
function restoreLeavingButtons() {
|
|
13688
|
+
var marked = document.querySelectorAll("[data-leaving]");
|
|
13689
|
+
for (var i = 0; i < marked.length; i++) {
|
|
13690
|
+
var btn = marked[i];
|
|
13691
|
+
btn.disabled = false;
|
|
13692
|
+
btn.removeAttribute("data-leaving");
|
|
13693
|
+
// 「準備しています…」を消すのは**同じ箱の中の**行だけ(他のボタンの結果を消さない)。
|
|
13694
|
+
// 箱が見つからなければボタンだけ戻す
|
|
13695
|
+
var wrap = btn.closest ? btn.closest(".ds-toggle") : null;
|
|
13696
|
+
var msg = wrap ? wrap.querySelector(".ds-toggle-msg") : null;
|
|
13697
|
+
if (msg) {
|
|
13698
|
+
msg.className = "ds-toggle-msg";
|
|
13699
|
+
msg.textContent = "";
|
|
13700
|
+
}
|
|
13701
|
+
}
|
|
13702
|
+
}
|
|
13703
|
+
// **bfcache から復元されたときだけ走る。** 通常のロード(persisted が false)では
|
|
13704
|
+
// DOM ごと作り直されるので、戻すものは無い
|
|
13705
|
+
window.addEventListener("pageshow", function (e) {
|
|
13706
|
+
if (!e.persisted) return;
|
|
13707
|
+
restoreLeavingButtons();
|
|
13708
|
+
});
|
|
13488
13709
|
// ヘッダーの案件アイコン(#348)は #app の外なので、**起動時に1回だけ描く**。
|
|
13489
13710
|
// route() はタブを替えるたびに走るが、ヘッダーは描き替えない——描き直すと
|
|
13490
13711
|
// 保存直後の mirror とメニューの開閉が、タブを移るたびに畳まれる
|
package/package.json
CHANGED