@takagaki/cortex-decisions-viewer 0.12.173 → 0.12.174
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 +63 -10
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -4923,6 +4923,10 @@ a:hover { text-decoration: underline; }
|
|
|
4923
4923
|
.mface { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; overflow: hidden; background: var(--border, #e5e7eb); color: var(--muted, #6b7280); font-size: 13px; font-weight: 700; line-height: 1; text-decoration: none; box-sizing: border-box; }
|
|
4924
4924
|
a.mface:hover { box-shadow: 0 0 0 2px var(--accent, #4f46e5); }
|
|
4925
4925
|
.mface svg { width: 18px; height: 18px; display: block; }
|
|
4926
|
+
.mface-loading { animation: mface-pulse 1.4s ease-in-out infinite; }
|
|
4927
|
+
.mface-loading img { opacity: 0; }
|
|
4928
|
+
@keyframes mface-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
|
|
4929
|
+
@media (prefers-reduced-motion: reduce) { .mface-loading { animation: none; } }
|
|
4926
4930
|
.mface img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
4927
4931
|
.detail-namerow .mface { width: 36px; height: 36px; font-size: 16px; }
|
|
4928
4932
|
.detail-namerow .mface svg { width: 22px; height: 22px; }
|
|
@@ -7741,36 +7745,82 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
7741
7745
|
var mfAsked = {};
|
|
7742
7746
|
var mfWaiting = [];
|
|
7743
7747
|
var mfTimer = null;
|
|
7748
|
+
/** 頼んでいて答え待ちの人 -> その人の丸(待っている間はスケルトン) */
|
|
7749
|
+
var mfInflight = {};
|
|
7750
|
+
var MF_ASK_TIMEOUT_MS = 8000;
|
|
7751
|
+
var MF_IMG_TIMEOUT_MS = 8000;
|
|
7752
|
+
/** 待ちの形から最後の形へ(loading を外す)。state: photo=写真が読めた/initial=頭文字 */
|
|
7753
|
+
function mfSettle(box, state) {
|
|
7754
|
+
if (box.getAttribute("data-state") !== "loading") return;
|
|
7755
|
+
box.classList.remove("mface-loading");
|
|
7756
|
+
box.setAttribute("data-state", state);
|
|
7757
|
+
if (state === "initial") {
|
|
7758
|
+
var img = box.querySelector("img");
|
|
7759
|
+
if (img && img.parentNode) img.parentNode.removeChild(img);
|
|
7760
|
+
box.appendChild(el("span", { class: "mface-initial", text: box.getAttribute("data-initial") || "" }));
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
/** 取れた写真を読み込む。読めるまではスケルトンのまま・失敗か時間切れで頭文字(止まり続けない) */
|
|
7744
7764
|
function mfAttach(box, path) {
|
|
7745
|
-
if (
|
|
7765
|
+
if (box.getAttribute("data-state") !== "loading") return;
|
|
7746
7766
|
var img = document.createElement("img");
|
|
7767
|
+
var timer = setTimeout(function () { mfSettle(box, "initial"); }, MF_IMG_TIMEOUT_MS);
|
|
7747
7768
|
img.setAttribute("alt", "");
|
|
7748
7769
|
img.setAttribute("referrerpolicy", "no-referrer");
|
|
7749
|
-
img.
|
|
7750
|
-
img.addEventListener("error", function () {
|
|
7770
|
+
img.addEventListener("load", function () { clearTimeout(timer); mfSettle(box, "photo"); });
|
|
7771
|
+
img.addEventListener("error", function () { clearTimeout(timer); mfSettle(box, "initial"); });
|
|
7751
7772
|
img.setAttribute("src", PORTAL_ORIGIN + path);
|
|
7752
7773
|
box.appendChild(img);
|
|
7753
7774
|
}
|
|
7775
|
+
/** もう答えが分かっている人の丸を決める(写真のパスがあれば読みに行き、無ければ頭文字) */
|
|
7776
|
+
function mfResolve(box, id) {
|
|
7777
|
+
if (mfFaces[id]) mfAttach(box, mfFaces[id]);
|
|
7778
|
+
else mfSettle(box, "initial");
|
|
7779
|
+
}
|
|
7754
7780
|
function mfFlush() {
|
|
7755
7781
|
mfTimer = null;
|
|
7756
7782
|
var waiting = mfWaiting;
|
|
7757
7783
|
mfWaiting = [];
|
|
7758
|
-
if (!waiting.length
|
|
7784
|
+
if (!waiting.length) return;
|
|
7785
|
+
if (!SITE.intake || !actorTicket()) { waiting.forEach(function (w) { mfSettle(w.box, "initial"); }); return; }
|
|
7759
7786
|
var ids = [];
|
|
7760
7787
|
waiting.forEach(function (w) {
|
|
7761
|
-
if (Object.prototype.hasOwnProperty.call(mfFaces, w.id)) {
|
|
7762
|
-
|
|
7788
|
+
if (Object.prototype.hasOwnProperty.call(mfFaces, w.id)) { mfResolve(w.box, w.id); return; }
|
|
7789
|
+
var asked = Object.prototype.hasOwnProperty.call(mfAsked, w.id);
|
|
7790
|
+
if (!asked && ids.indexOf(w.id) < 0) {
|
|
7791
|
+
// 1 回に頼むのは 200 人まで。あふれた人は待たせず頭文字(スケルトンのまま止まらない)
|
|
7792
|
+
if (ids.length >= 200) { mfSettle(w.box, "initial"); return; }
|
|
7793
|
+
ids.push(w.id);
|
|
7794
|
+
}
|
|
7795
|
+
(mfInflight[w.id] = mfInflight[w.id] || []).push(w.box);
|
|
7763
7796
|
});
|
|
7764
7797
|
if (!ids.length) return;
|
|
7765
7798
|
ids.forEach(function (id) { mfAsked[id] = 1; });
|
|
7799
|
+
var finished = false;
|
|
7800
|
+
// 答えが出た(または諦めた)人の待ち行列を空にして、全部の丸を最後の形へ
|
|
7801
|
+
var drain = function () {
|
|
7802
|
+
ids.forEach(function (id) {
|
|
7803
|
+
var boxes = mfInflight[id] || [];
|
|
7804
|
+
delete mfInflight[id];
|
|
7805
|
+
boxes.forEach(function (b) { mfResolve(b, id); });
|
|
7806
|
+
});
|
|
7807
|
+
};
|
|
7766
7808
|
var give = function (j) {
|
|
7767
7809
|
(j.people || []).forEach(function (one) {
|
|
7768
7810
|
if (one && typeof one.userId === "string" && typeof one.avatarUrl === "string" && MF_AVATAR.test(one.avatarUrl)) mfFaces[one.userId] = one.avatarUrl;
|
|
7769
7811
|
});
|
|
7770
7812
|
ids.forEach(function (id) { if (!Object.prototype.hasOwnProperty.call(mfFaces, id)) mfFaces[id] = null; });
|
|
7771
|
-
|
|
7813
|
+
if (!finished) { finished = true; clearTimeout(giveUp); drain(); }
|
|
7814
|
+
};
|
|
7815
|
+
// 失敗・断り・時間切れは覚えない(あとで画面を開き直せば取り直す)。待っていた丸は頭文字に落とす
|
|
7816
|
+
var forget = function () {
|
|
7817
|
+
if (finished) return;
|
|
7818
|
+
finished = true;
|
|
7819
|
+
clearTimeout(giveUp);
|
|
7820
|
+
ids.forEach(function (id) { delete mfAsked[id]; });
|
|
7821
|
+
drain();
|
|
7772
7822
|
};
|
|
7773
|
-
var
|
|
7823
|
+
var giveUp = setTimeout(forget, MF_ASK_TIMEOUT_MS);
|
|
7774
7824
|
intakeJson(callIntake("member-faces", { op: "member-faces", userIds: ids })).then(function (res) {
|
|
7775
7825
|
var j = (res && res.j) || {};
|
|
7776
7826
|
if (res && res.ok && j.ok === true && Array.isArray(j.people)) give(j);
|
|
@@ -7805,15 +7855,18 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
7805
7855
|
return plain;
|
|
7806
7856
|
}
|
|
7807
7857
|
var name = Array.from(humanTitle(rec.title))[0] || "";
|
|
7858
|
+
// 🔴 画像を取りに行っている間は頭文字を出さず、丸の形のスケルトン(確定した表示がすり替わって見えないように)。
|
|
7859
|
+
// 頭文字は「取れなかった・読めなかった・時間切れ」の最後の形にだけ出す。読み上げには「読み込み中」を足さない
|
|
7808
7860
|
var a = el("a", {
|
|
7809
|
-
class: "mface mface-portal",
|
|
7861
|
+
class: "mface mface-portal mface-loading",
|
|
7810
7862
|
"data-face": "portal",
|
|
7863
|
+
"data-state": "loading",
|
|
7864
|
+
"data-initial": name,
|
|
7811
7865
|
href: PORTAL_ORIGIN + "/people/" + encodeURIComponent(id),
|
|
7812
7866
|
target: "_blank",
|
|
7813
7867
|
rel: "noopener",
|
|
7814
7868
|
title: "ポータルでこの人のページを開く",
|
|
7815
7869
|
});
|
|
7816
|
-
a.appendChild(el("span", { class: "mface-initial", text: name }));
|
|
7817
7870
|
// 行ごと(カード・詳細)の click に伝えない(カードを押した扱いで詳細へ移らない)
|
|
7818
7871
|
a.addEventListener("click", function (ev) { ev.stopPropagation(); });
|
|
7819
7872
|
mfWant(id, a);
|
package/package.json
CHANGED