@takagaki/cortex-decisions-viewer 0.12.150 → 0.12.152
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 +123 -4
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -4972,6 +4972,19 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
4972
4972
|
.card-facet-yomi { font-size: 11.5px; }
|
|
4973
4973
|
.card-titlerow { display: flex; align-items: baseline; gap: 12px; margin: 0 0 6px; }
|
|
4974
4974
|
.card-titlerow .card-title { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; margin: 2px 0 0; }
|
|
4975
|
+
/* 関係者のアイコン(行の右端・一覧と各ページで同じ見た目。名前は他の区画と同じく左詰め)。portal.id がある人はポータルの人のページへのリンク */
|
|
4976
|
+
.card-namerow { display: flex; align-items: center; gap: 10px; margin: 2px 0 6px; }
|
|
4977
|
+
.card-namerow .card-title { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; margin: 0; }
|
|
4978
|
+
.card-titlerow .mface { align-self: center; margin-left: auto; }
|
|
4979
|
+
.card-namerow .mface, .detail-namerow .mface { margin-left: auto; }
|
|
4980
|
+
.detail-namerow { display: flex; align-items: center; gap: 12px; margin: 0 0 10px; }
|
|
4981
|
+
.detail-namerow .detail-title { margin: 0; min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }
|
|
4982
|
+
.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; }
|
|
4983
|
+
a.mface:hover { box-shadow: 0 0 0 2px var(--accent, #4f46e5); }
|
|
4984
|
+
.mface svg { width: 18px; height: 18px; display: block; }
|
|
4985
|
+
.mface img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
4986
|
+
.detail-namerow .mface { width: 36px; height: 36px; font-size: 16px; }
|
|
4987
|
+
.detail-namerow .mface svg { width: 22px; height: 22px; }
|
|
4975
4988
|
/* card-title はカードの見出し(#1 新しいタブでも開けるよう <a> にした)。見た目は元の <div> と揃える */
|
|
4976
4989
|
.card-title { display: block; font-size: 16px; font-weight: 650; margin: 2px 0 6px; color: var(--text); }
|
|
4977
4990
|
.card-summary { color: #3b424c; font-size: 14px; margin: 0; }
|
|
@@ -7595,6 +7608,105 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
7595
7608
|
var id = ask && ask.subject && ask.subject.userId;
|
|
7596
7609
|
return typeof id === "string" && /^[0-9A-Za-z_-]{1,64}$/.test(id) ? PORTAL_ORIGIN + "/people/" + encodeURIComponent(id) : null;
|
|
7597
7610
|
}
|
|
7611
|
+
// ---------- 関係者のアイコン(行の右端・cortex-engine #1775) ----------
|
|
7612
|
+
//
|
|
7613
|
+
// 🔴 **正は記録の frontmatter の portal.id**(V4 の boundIds の重なりで人を探さない)。portal の欄が無い・形が違う人は
|
|
7614
|
+
// 人型のデフォルト(押せない)。portal.id がある人は「頭文字の丸」を押せるリンクで出し、ポータルの人のページへ行く。
|
|
7615
|
+
// 🔴 **画像の URL は配布物に焼かない。** 画面に出ている人の portal.id を集めて intake の member-faces を 1 回呼び
|
|
7616
|
+
// (失敗は覚えない)、返った相対パスを PORTAL_ORIGIN につないで img にする。取れない・読み込めないときは頭文字のまま。
|
|
7617
|
+
// 🔴 portal の欄の中身(email を持つ)は画面に生で出さない(アイコンとリンクにだけ使う・member.no-email)。
|
|
7618
|
+
// 🔴 値は全部 textContent / setAttribute で入れる。img は alt=""(名前は横に出ている)・no-referrer・lazy。
|
|
7619
|
+
var MF_ID = /^[0-9A-Za-z_-]{1,64}$/;
|
|
7620
|
+
var MF_AVATAR = /^\\/icons\\/u\\/[0-9A-Za-z_-]+\\.(?:jpg|jpeg|png|webp|gif)$/;
|
|
7621
|
+
/** 記録の portal.id(形が違えば空文字) */
|
|
7622
|
+
function mfPortalId(rec) {
|
|
7623
|
+
var p = rec && rec.fm ? rec.fm.portal : null;
|
|
7624
|
+
var id = p && typeof p === "object" && !Array.isArray(p) ? p.id : "";
|
|
7625
|
+
return typeof id === "string" && MF_ID.test(id) ? id : "";
|
|
7626
|
+
}
|
|
7627
|
+
/** 取れた画像の相対パス(userId -> パス)・もう頼んだ人・まだ待っている子 */
|
|
7628
|
+
var mfFaces = {};
|
|
7629
|
+
var mfAsked = {};
|
|
7630
|
+
var mfWaiting = [];
|
|
7631
|
+
var mfTimer = null;
|
|
7632
|
+
function mfAttach(box, path) {
|
|
7633
|
+
if (!box.isConnected && !box.parentNode) return;
|
|
7634
|
+
var img = document.createElement("img");
|
|
7635
|
+
img.setAttribute("alt", "");
|
|
7636
|
+
img.setAttribute("referrerpolicy", "no-referrer");
|
|
7637
|
+
img.setAttribute("loading", "lazy");
|
|
7638
|
+
img.addEventListener("error", function () { if (img.parentNode) img.parentNode.removeChild(img); });
|
|
7639
|
+
img.setAttribute("src", PORTAL_ORIGIN + path);
|
|
7640
|
+
box.appendChild(img);
|
|
7641
|
+
}
|
|
7642
|
+
function mfFlush() {
|
|
7643
|
+
mfTimer = null;
|
|
7644
|
+
var waiting = mfWaiting;
|
|
7645
|
+
mfWaiting = [];
|
|
7646
|
+
if (!waiting.length || !SITE.intake || !actorTicket()) return;
|
|
7647
|
+
var ids = [];
|
|
7648
|
+
waiting.forEach(function (w) {
|
|
7649
|
+
if (Object.prototype.hasOwnProperty.call(mfFaces, w.id)) { if (mfFaces[w.id]) mfAttach(w.box, mfFaces[w.id]); return; }
|
|
7650
|
+
if (!Object.prototype.hasOwnProperty.call(mfAsked, w.id) && ids.indexOf(w.id) < 0 && ids.length < 200) ids.push(w.id);
|
|
7651
|
+
});
|
|
7652
|
+
if (!ids.length) return;
|
|
7653
|
+
ids.forEach(function (id) { mfAsked[id] = 1; });
|
|
7654
|
+
var give = function (j) {
|
|
7655
|
+
(j.people || []).forEach(function (one) {
|
|
7656
|
+
if (one && typeof one.userId === "string" && typeof one.avatarUrl === "string" && MF_AVATAR.test(one.avatarUrl)) mfFaces[one.userId] = one.avatarUrl;
|
|
7657
|
+
});
|
|
7658
|
+
ids.forEach(function (id) { if (!Object.prototype.hasOwnProperty.call(mfFaces, id)) mfFaces[id] = null; });
|
|
7659
|
+
waiting.forEach(function (w) { if (mfFaces[w.id]) mfAttach(w.box, mfFaces[w.id]); });
|
|
7660
|
+
};
|
|
7661
|
+
var forget = function () { ids.forEach(function (id) { delete mfAsked[id]; }); };
|
|
7662
|
+
intakeJson(callIntake("member-faces", { op: "member-faces", userIds: ids })).then(function (res) {
|
|
7663
|
+
var j = (res && res.j) || {};
|
|
7664
|
+
if (res && res.ok && j.ok === true && Array.isArray(j.people)) give(j);
|
|
7665
|
+
else forget();
|
|
7666
|
+
}, forget);
|
|
7667
|
+
}
|
|
7668
|
+
function mfWant(id, box) {
|
|
7669
|
+
mfWaiting.push({ id: id, box: box });
|
|
7670
|
+
if (!mfTimer) mfTimer = setTimeout(mfFlush, 0);
|
|
7671
|
+
}
|
|
7672
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
7673
|
+
/** 人型のデフォルト(インライン SVG・はてなは使わない) */
|
|
7674
|
+
function mfDefaultSvg() {
|
|
7675
|
+
var svg = document.createElementNS(SVG_NS, "svg");
|
|
7676
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
7677
|
+
svg.setAttribute("aria-hidden", "true");
|
|
7678
|
+
svg.setAttribute("focusable", "false");
|
|
7679
|
+
var c = document.createElementNS(SVG_NS, "circle");
|
|
7680
|
+
c.setAttribute("cx", "12"); c.setAttribute("cy", "8"); c.setAttribute("r", "4"); c.setAttribute("fill", "currentColor");
|
|
7681
|
+
var b = document.createElementNS(SVG_NS, "path");
|
|
7682
|
+
b.setAttribute("d", "M4 21c0-4.4 3.6-7 8-7s8 2.6 8 7z"); b.setAttribute("fill", "currentColor");
|
|
7683
|
+
svg.appendChild(c);
|
|
7684
|
+
svg.appendChild(b);
|
|
7685
|
+
return svg;
|
|
7686
|
+
}
|
|
7687
|
+
/** 関係者 1 人のアイコン。一覧のカードも詳細も、この 1 つの関数で組む */
|
|
7688
|
+
function mfAvatar(rec) {
|
|
7689
|
+
var id = mfPortalId(rec);
|
|
7690
|
+
if (!id) {
|
|
7691
|
+
var plain = el("span", { class: "mface mface-default", "data-face": "default" });
|
|
7692
|
+
plain.appendChild(mfDefaultSvg());
|
|
7693
|
+
return plain;
|
|
7694
|
+
}
|
|
7695
|
+
var name = Array.from(humanTitle(rec.title))[0] || "";
|
|
7696
|
+
var a = el("a", {
|
|
7697
|
+
class: "mface mface-portal",
|
|
7698
|
+
"data-face": "portal",
|
|
7699
|
+
href: PORTAL_ORIGIN + "/people/" + encodeURIComponent(id),
|
|
7700
|
+
target: "_blank",
|
|
7701
|
+
rel: "noopener",
|
|
7702
|
+
title: "ポータルでこの人のページを開く",
|
|
7703
|
+
});
|
|
7704
|
+
a.appendChild(el("span", { class: "mface-initial", text: name }));
|
|
7705
|
+
// 行ごと(カード・詳細)の click に伝えない(カードを押した扱いで詳細へ移らない)
|
|
7706
|
+
a.addEventListener("click", function (ev) { ev.stopPropagation(); });
|
|
7707
|
+
mfWant(id, a);
|
|
7708
|
+
return a;
|
|
7709
|
+
}
|
|
7598
7710
|
/**
|
|
7599
7711
|
* 断られたときの 1 行(code ごとに一手)。**帯は症状・行は一手・繰り返さない。**
|
|
7600
7712
|
* final: 押し直しても同じ答えになる(ボタンを畳む)/false: 時間をおけば通りうる(ボタンを残す)
|
|
@@ -8005,7 +8117,7 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
8005
8117
|
}
|
|
8006
8118
|
|
|
8007
8119
|
/** 一覧カードの頭(上の段 + 題)を組む。左側の中身(札・日付・エラーの札)が 1 つも無いときは
|
|
8008
|
-
* 空の .card-meta
|
|
8120
|
+
* 空の .card-meta を作らず、題の行に「🕸 つながり」を置く(#1094)。関係者のアイコンはどちらの経路でも行の最後(右端)。 */
|
|
8009
8121
|
function cardHead(rec, leftNodes, titleExtra) {
|
|
8010
8122
|
var trace = el("a", { class: "mc-trace", href: "?tab=graph", text: "🕸 つながり" });
|
|
8011
8123
|
trace.addEventListener("click", function (ev) { ev.preventDefault(); ev.stopPropagation(); openExplorerFor(rec); });
|
|
@@ -8013,9 +8125,11 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
8013
8125
|
var eb = fmErrorBadge(rec);
|
|
8014
8126
|
if (eb) meta.appendChild(eb);
|
|
8015
8127
|
var title = cardTitleLink(rec, titleExtra);
|
|
8016
|
-
|
|
8128
|
+
// 関係者は行の右端にアイコン(詳細と同じ mfAvatar・名前は左詰め)
|
|
8129
|
+
var face = isMemberRec(rec) ? mfAvatar(rec) : null;
|
|
8130
|
+
if (!meta.childNodes.length) return [el("div", { class: "card-titlerow" }, [title, trace, face])];
|
|
8017
8131
|
meta.appendChild(trace);
|
|
8018
|
-
return [meta, title];
|
|
8132
|
+
return [meta, face ? el("div", { class: "card-namerow" }, [title, face]) : title];
|
|
8019
8133
|
}
|
|
8020
8134
|
|
|
8021
8135
|
/**
|
|
@@ -20131,7 +20245,10 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
20131
20245
|
if (detailPagerG) app.appendChild(detailPagerG);
|
|
20132
20246
|
|
|
20133
20247
|
var head = el("div", { class: "detail-head" });
|
|
20134
|
-
|
|
20248
|
+
var titleH1 = el("h1", { class: "detail-title", text: humanTitle(r.title) });
|
|
20249
|
+
head.appendChild(isMemberRec(r)
|
|
20250
|
+
? el("div", { class: "detail-namerow" }, [ titleH1, mfAvatar(r) ])
|
|
20251
|
+
: el("div", {}, [ titleH1 ]));
|
|
20135
20252
|
var traceBtn2 = el("a", { class: "trace-btn", href: "?tab=graph", text: "🕸 つながり" });
|
|
20136
20253
|
traceBtn2.addEventListener("click", function (ev) { ev.preventDefault(); openExplorerFor(r); });
|
|
20137
20254
|
var editRowR = el("div", { class: "detail-actions-row" });
|
|
@@ -21472,6 +21589,8 @@ ${story_1.splitByNameLinks.toString()}
|
|
|
21472
21589
|
panel.appendChild(el("summary", { class: "fm-title", text: "レコード情報(frontmatter)" }));
|
|
21473
21590
|
var grid = el("div", { class: "fm-grid" });
|
|
21474
21591
|
Object.keys(fm).forEach(function (k) {
|
|
21592
|
+
// 🔴 portal(中にポータルのアカウントのメールを持つ)は生で出さない。アイコンとリンクにだけ使う(member.no-email)
|
|
21593
|
+
if (k === "portal") return;
|
|
21475
21594
|
grid.appendChild(el("div", { class: "fm-key", text: k }));
|
|
21476
21595
|
var cell = el("div", { class: "fm-val" });
|
|
21477
21596
|
var v = fm[k];
|
package/package.json
CHANGED