@unson/brainbase-mcp 0.41.13 → 0.42.0
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/local-web-host.d.ts +6 -0
- package/dist/local-web-host.js +35 -1
- package/dist/personal-memory.d.ts +101 -0
- package/dist/personal-memory.js +204 -0
- package/dist/ssot.d.ts +3 -1
- package/dist/ssot.js +4 -0
- package/package.json +9 -2
- package/ui/judgment-history.js +74 -3
- package/ui/local-web-shell.js +56 -2
- package/ui/personal-memory-http-port.js +72 -0
- package/ui/personal-memory.css +254 -0
- package/ui/personal-memory.js +677 -0
package/ui/local-web-shell.js
CHANGED
|
@@ -26,6 +26,8 @@ import { createMeetingMinutesUI } from './meeting-minutes.js';
|
|
|
26
26
|
import { createMeetingMinutesStorageExtension } from './meeting-minutes-storage.js';
|
|
27
27
|
import { createMeetingMinutesLineageExtension } from './meeting-minutes-lineage-http.js';
|
|
28
28
|
import { createWorldModelView } from './world-model-view.js';
|
|
29
|
+
import { createPersonalMemoryUI, parsePersonalMemoryRoute, personalMemoryRouteTarget } from './personal-memory.js';
|
|
30
|
+
import { createPersonalMemoryHttpPort } from './personal-memory-http-port.js';
|
|
29
31
|
import { createGraphClient } from './graph-view-shared.js';
|
|
30
32
|
import { installNativeScrollbars } from './native-scrollbars.js';
|
|
31
33
|
import { browserAreaStorage, createAreaMemory, createAreaNav } from './area-nav.js';
|
|
@@ -53,6 +55,8 @@ const NAV_ICON_PATHS = Object.freeze({
|
|
|
53
55
|
minutes: ['M6 3.5h9l3 3V20.5H6z', 'M15 3.5v4h3', 'M9 12h6m-6 3h6'],
|
|
54
56
|
// Two people (the organization edition's 人と会社 uses the same shape).
|
|
55
57
|
people: ['M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z', 'M2.5 20a6.5 6.5 0 0 1 13 0', 'M16 4.5a3.5 3.5 0 0 1 0 6.5', 'M18 14a6.5 6.5 0 0 1 3.5 6'],
|
|
58
|
+
// あなたの記憶 (ledger D15): one person and a lock, seen only by the owner.
|
|
59
|
+
memory: ['M10 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z', 'M3.5 20a6.5 6.5 0 0 1 10-5.5', 'M15 15h6v5h-6z', 'M16.5 15v-1.5a1.5 1.5 0 0 1 3 0V15'],
|
|
56
60
|
// Kinds of information and how they connect (settings, ledger D14): three linked boxes.
|
|
57
61
|
ontology: ['M4 4h6v6H4z', 'M14 14h6v6h-6z', 'M14 4h6v6h-6z', 'M10 7h4', 'M17 10v4'],
|
|
58
62
|
// World view (extension id `world`, ledger P17).
|
|
@@ -75,7 +79,7 @@ const NAV_AREAS = Object.freeze([
|
|
|
75
79
|
Object.freeze({ id: 'purpose', label: null, order: ['objectives'], icon: 'objectives' }),
|
|
76
80
|
Object.freeze({ id: 'work', label: '仕事', order: ['projects', 'minutes'], defaultScreen: 'projects', icon: 'area:work' }),
|
|
77
81
|
Object.freeze({ id: 'outcomes', label: '成果', order: ['value-proofs'], icon: 'value-proofs' }),
|
|
78
|
-
Object.freeze({ id: 'information', label: '情報と関係', order: ['graph', 'people'], defaultScreen: 'graph', icon: 'graph' }),
|
|
82
|
+
Object.freeze({ id: 'information', label: '情報と関係', order: ['graph', 'people', 'memory'], defaultScreen: 'graph', icon: 'graph' }),
|
|
79
83
|
Object.freeze({ id: 'settings', label: '設定', order: ['ontology'], defaultScreen: 'ontology', icon: 'area:settings' }),
|
|
80
84
|
]);
|
|
81
85
|
|
|
@@ -163,11 +167,14 @@ export function parseLocalWebTarget(target) {
|
|
|
163
167
|
// プロジェクトと関係者 one project (`project` = Graph project id); other screens ignore them.
|
|
164
168
|
const decisionId = screenId === 'value-proofs' ? params.get('decision')?.trim() || null : null;
|
|
165
169
|
const projectId = screenId === 'projects' ? params.get('project')?.trim() || null : null;
|
|
170
|
+
// あなたの記憶 keeps its filters and the opened memory (never the search words).
|
|
171
|
+
const memoryRoute = screenId === 'memory' ? parsePersonalMemoryRoute(params) : null;
|
|
166
172
|
return {
|
|
167
173
|
screenId,
|
|
168
174
|
entityId: screenId === 'graph' ? params.get('entity_id')?.trim() || null : null,
|
|
169
175
|
...(decisionId ? { decisionId } : {}),
|
|
170
176
|
...(projectId ? { projectId } : {}),
|
|
177
|
+
...(memoryRoute ? { memoryRoute } : {}),
|
|
171
178
|
};
|
|
172
179
|
}
|
|
173
180
|
|
|
@@ -228,6 +235,26 @@ function judgmentReferenceLabelReader(context) {
|
|
|
228
235
|
};
|
|
229
236
|
}
|
|
230
237
|
|
|
238
|
+
function personalMemoryPort(context) {
|
|
239
|
+
return createPersonalMemoryHttpPort({ fetcher: context.fetcher, token: context.token });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The opening of each used memory, for 判断の履歴's 本人の考え; the local host has one owner. */
|
|
243
|
+
function personalMemoryResolver(context) {
|
|
244
|
+
const port = personalMemoryPort(context);
|
|
245
|
+
return async (refs) => {
|
|
246
|
+
const list = await port.listMemories({});
|
|
247
|
+
if (list.status !== 'ok') throw new Error(list.reason);
|
|
248
|
+
const wanted = new Set(refs);
|
|
249
|
+
const found = new Map();
|
|
250
|
+
for (const item of list.items) {
|
|
251
|
+
if (!wanted.has(item.id)) continue;
|
|
252
|
+
found.set(item.id, { excerpt: item.text, href: `#${personalMemoryRouteTarget({ memoryId: item.id })}` });
|
|
253
|
+
}
|
|
254
|
+
return found;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
231
258
|
function mountToday(container, context) {
|
|
232
259
|
return createJudgmentHistoryUI({
|
|
233
260
|
root: makePage(container, context),
|
|
@@ -238,6 +265,23 @@ function mountToday(container, context) {
|
|
|
238
265
|
token: context.token,
|
|
239
266
|
basePath: '/api/judgment-history',
|
|
240
267
|
resolveReferenceLabels: judgmentReferenceLabelReader(context),
|
|
268
|
+
resolvePersonalMemory: personalMemoryResolver(context),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function mountPersonalMemory(container, context) {
|
|
273
|
+
return createPersonalMemoryUI({
|
|
274
|
+
root: makePage(container, context),
|
|
275
|
+
rail: context.rail,
|
|
276
|
+
page: context.page,
|
|
277
|
+
document: context.document,
|
|
278
|
+
port: personalMemoryPort(context),
|
|
279
|
+
judgmentHref: (decisionId) => `#value-proofs?decision=${encodeURIComponent(decisionId)}`,
|
|
280
|
+
candidatesCommand: 'brainbase onboard:candidates',
|
|
281
|
+
route: context.initialEntityId ?? undefined,
|
|
282
|
+
onRouteChange: context.navigate
|
|
283
|
+
? (route, options) => context.navigate(personalMemoryRouteTarget(route), options)
|
|
284
|
+
: undefined,
|
|
241
285
|
});
|
|
242
286
|
}
|
|
243
287
|
|
|
@@ -341,6 +385,8 @@ export const LOCAL_WEB_SCREENS = Object.freeze([
|
|
|
341
385
|
onRouteChange: (entityId, options) => context.navigate?.(entityId ? `graph?entity_id=${encodeURIComponent(entityId)}` : 'graph', options),
|
|
342
386
|
})) }),
|
|
343
387
|
Object.freeze({ id: 'people', label: '人と会社', area: 'information', usesGraph: true, rail: true, source: '手元のGraph', mount: mountGraphScreen('people', createPeopleAndCompaniesView, { canCorrect: true }) }),
|
|
388
|
+
// Only the owner sees it (ledger D15); the local host has one owner, so it is always listed here.
|
|
389
|
+
Object.freeze({ id: 'memory', label: 'あなたの記憶', area: 'information', usesGraph: false, rail: true, ownerOnly: true, source: '手元の個人KG', mount: mountPersonalMemory }),
|
|
344
390
|
// The definitions behind 情報と関係: infrequent management work, so under settings (ledger D14).
|
|
345
391
|
Object.freeze({ id: 'ontology', label: '情報の種類とつながり方', area: 'settings', usesGraph: true, rail: false, source: '手元のGraph', mount: mountGraphScreen('ontology', createGraphOntologyView, { canCorrect: true }) }),
|
|
346
392
|
]);
|
|
@@ -428,10 +474,14 @@ export function createLocalWebShell({
|
|
|
428
474
|
meetingMinutesLineage = null,
|
|
429
475
|
areaMemory = createAreaMemory(browserAreaStorage()),
|
|
430
476
|
onNavigate,
|
|
477
|
+
// A host that serves more than one person passes false for anyone but the owner:
|
|
478
|
+
// owner-only screens (あなたの記憶) are then neither listed nor mounted.
|
|
479
|
+
isOwner = true,
|
|
431
480
|
} = {}) {
|
|
432
481
|
if (!root) throw new TypeError('root is required');
|
|
433
482
|
const doc = explicitDocument ?? (typeof document === 'undefined' ? null : document);
|
|
434
483
|
if (!doc || typeof doc.createElement !== 'function') throw new Error('document_unavailable');
|
|
484
|
+
screens = screens.filter((screen) => isOwner === true || screen.ownerOnly !== true);
|
|
435
485
|
const request = typeof fetcher === 'function'
|
|
436
486
|
? fetcher
|
|
437
487
|
: typeof globalThis.fetch === 'function' ? (path, init) => globalThis.fetch(path, init) : null;
|
|
@@ -522,6 +572,7 @@ export function createLocalWebShell({
|
|
|
522
572
|
if (!entityId && screen.id === 'graph' && view?.state?.detail && typeof view.closeEntity === 'function') view.closeEntity();
|
|
523
573
|
if (entityId && screen.id === 'value-proofs' && typeof view?.openDecision === 'function') view.openDecision(entityId);
|
|
524
574
|
if (entityId && screen.id === 'projects' && typeof view?.openProject === 'function') void view.openProject(entityId);
|
|
575
|
+
if (entityId && screen.id === 'memory' && typeof view?.applyRoute === 'function') view.applyRoute(entityId);
|
|
525
576
|
return;
|
|
526
577
|
}
|
|
527
578
|
const slot = slots.get(screen.id);
|
|
@@ -535,6 +586,7 @@ export function createLocalWebShell({
|
|
|
535
586
|
const page = Object.freeze({ crumbs: Object.freeze(['あなたのBrainbase', screen.label]), source: screen.source ?? null });
|
|
536
587
|
const view = screen.mount(slot, Object.freeze({ ...context, rail, page, initialEntityId: entityId })) ?? true;
|
|
537
588
|
mounted.set(screen.id, view);
|
|
589
|
+
if (screen.id === 'memory' && typeof view?.load === 'function') void view.load();
|
|
538
590
|
if (entityId && screen.id === 'value-proofs' && typeof view?.openDecision === 'function') view.openDecision(entityId);
|
|
539
591
|
if (entityId && screen.id === 'projects' && typeof view?.openProject === 'function') void view.openProject(entityId);
|
|
540
592
|
updateRail();
|
|
@@ -550,7 +602,9 @@ export function createLocalWebShell({
|
|
|
550
602
|
const screen = screens.find((candidate) => candidate.id === parsed.screenId) ?? screens[0];
|
|
551
603
|
pendingEntityIds.set(screen.id, screen.id === 'graph' ? parsed.entityId
|
|
552
604
|
: screen.id === 'value-proofs' ? parsed.decisionId ?? null
|
|
553
|
-
: screen.id === 'projects' ? parsed.projectId ?? null
|
|
605
|
+
: screen.id === 'projects' ? parsed.projectId ?? null
|
|
606
|
+
// あなたの記憶 receives its whole route (filters and the opened memory).
|
|
607
|
+
: screen.id === 'memory' ? parsed.memoryRoute ?? null : null);
|
|
554
608
|
active = screen.id;
|
|
555
609
|
for (const [screenId, slot] of slots) slot.hidden = screenId !== screen.id;
|
|
556
610
|
areaNav.show(screen.id);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The local Web host's port for 「あなたの記憶」 (ui/personal-memory.js).
|
|
3
|
+
*
|
|
4
|
+
* Every read carries the launch token: the memory bodies are private, so the
|
|
5
|
+
* host guards these reads as it guards writes. The list is read whole and
|
|
6
|
+
* filtered here, so the words being searched for never go into a request URL.
|
|
7
|
+
* The local host has a single owner, so `isOwner` is always true.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { filterPersonalMemories } from './personal-memory.js';
|
|
11
|
+
|
|
12
|
+
export function createPersonalMemoryHttpPort({
|
|
13
|
+
fetcher,
|
|
14
|
+
token,
|
|
15
|
+
basePath = '/api/personal-memory',
|
|
16
|
+
tokenHeader = 'x-brainbase-review-token',
|
|
17
|
+
} = {}) {
|
|
18
|
+
const request = typeof fetcher === 'function'
|
|
19
|
+
? fetcher
|
|
20
|
+
: typeof globalThis.fetch === 'function' ? (path, init) => globalThis.fetch(path, init) : null;
|
|
21
|
+
const base = String(basePath).replace(/\/+$/u, '');
|
|
22
|
+
|
|
23
|
+
async function read(path) {
|
|
24
|
+
if (!request) return { status: 0, body: null, failure: 'fetch_unavailable' };
|
|
25
|
+
try {
|
|
26
|
+
const response = await request(path, { method: 'GET', headers: token ? { [tokenHeader]: token } : {} });
|
|
27
|
+
let body = null;
|
|
28
|
+
try {
|
|
29
|
+
body = await response.json();
|
|
30
|
+
} catch {
|
|
31
|
+
body = null;
|
|
32
|
+
}
|
|
33
|
+
return { status: response.status, ok: response.ok === true, body };
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return { status: 0, body: null, failure: error instanceof Error ? error.message : 'request_failed' };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function unavailable(result) {
|
|
40
|
+
return {
|
|
41
|
+
status: 'unavailable',
|
|
42
|
+
reason: result.failure ?? result.body?.reason ?? result.body?.error?.code ?? `http_${result.status}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
isOwner: () => true,
|
|
48
|
+
async listMemories(filter = {}) {
|
|
49
|
+
const result = await read(base);
|
|
50
|
+
if (!result.ok || result.body?.status !== 'ok' || !Array.isArray(result.body.items)) return unavailable(result);
|
|
51
|
+
return { status: 'ok', items: filterPersonalMemories(result.body.items, filter), nextCursor: null };
|
|
52
|
+
},
|
|
53
|
+
async readMemory(id) {
|
|
54
|
+
const result = await read(`${base}/${encodeURIComponent(id)}`);
|
|
55
|
+
if (result.status === 404 && result.body?.status === 'not_found') return { status: 'not_found' };
|
|
56
|
+
if (!result.ok || result.body?.status !== 'ok' || !result.body.item) return unavailable(result);
|
|
57
|
+
return { status: 'ok', item: result.body.item };
|
|
58
|
+
},
|
|
59
|
+
async listJudgmentsUsing(id, limit) {
|
|
60
|
+
const result = await read(`${base}/${encodeURIComponent(id)}/judgments?limit=${encodeURIComponent(String(limit))}`);
|
|
61
|
+
if (!result.ok || result.body?.status !== 'ok' || !Array.isArray(result.body.items)) return unavailable(result);
|
|
62
|
+
return { status: 'ok', items: result.body.items, total: result.body.total };
|
|
63
|
+
},
|
|
64
|
+
async countJudgmentsUsing() {
|
|
65
|
+
const result = await read(`${base}?view=judgment-counts`);
|
|
66
|
+
if (!result.ok || result.body?.status !== 'ok' || !result.body.counts) return unavailable(result);
|
|
67
|
+
return { status: 'ok', counts: result.body.counts };
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default createPersonalMemoryHttpPort;
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 「あなたの記憶」. Load after workspace-kit.css.
|
|
3
|
+
* The privacy line, the one-line summary, the filter chips, the ledger's
|
|
4
|
+
* columns (the memory opening wraps to two lines) and the detail's parts.
|
|
5
|
+
* States are told apart by words and a quiet tone, never by red: a superseded
|
|
6
|
+
* or retracted memory is not an error.
|
|
7
|
+
* Uses only the shared tokens in brainbase-tokens.css.
|
|
8
|
+
*/
|
|
9
|
+
.bb-pm-privacy {
|
|
10
|
+
margin: -4px 0 12px;
|
|
11
|
+
color: var(--bb-color-muted);
|
|
12
|
+
font-size: 12px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.bb-pm-summary {
|
|
16
|
+
margin: 0 0 12px;
|
|
17
|
+
color: var(--bb-color-ink);
|
|
18
|
+
font-size: 13px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.bb-pm-loading {
|
|
22
|
+
height: 2px;
|
|
23
|
+
margin: 0 0 10px;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
background: var(--bb-color-accent-soft);
|
|
26
|
+
color: transparent;
|
|
27
|
+
font-size: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.bb-pm-filter-bar {
|
|
31
|
+
margin: 0 0 14px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.bb-pm-filters {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-wrap: wrap;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 8px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.bb-pm-chip {
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
border: 1px solid var(--bb-color-control-border);
|
|
45
|
+
border-radius: 999px;
|
|
46
|
+
background: var(--bb-color-paper);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.bb-pm-chip.is-active {
|
|
50
|
+
border-color: var(--bb-color-accent);
|
|
51
|
+
background: var(--bb-color-accent-soft);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.bb-pm-chip-button,
|
|
55
|
+
.bb-pm-chip-clear,
|
|
56
|
+
.bb-pm-option,
|
|
57
|
+
.bb-pm-clear-all {
|
|
58
|
+
border: 0;
|
|
59
|
+
background: transparent;
|
|
60
|
+
color: var(--bb-color-ink);
|
|
61
|
+
font: inherit;
|
|
62
|
+
font-size: 13px;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.bb-pm-chip-button {
|
|
67
|
+
padding: 5px 12px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.bb-pm-chip-clear {
|
|
71
|
+
padding: 5px 10px 5px 0;
|
|
72
|
+
color: var(--bb-color-muted);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.bb-pm-clear-all {
|
|
76
|
+
padding: 5px 4px;
|
|
77
|
+
color: var(--bb-color-accent-strong);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.bb-pm-clear-all:disabled {
|
|
81
|
+
color: var(--bb-color-quiet);
|
|
82
|
+
cursor: default;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.bb-pm-search {
|
|
86
|
+
min-width: 200px;
|
|
87
|
+
flex: 1 1 200px;
|
|
88
|
+
max-width: 320px;
|
|
89
|
+
padding: 6px 10px;
|
|
90
|
+
border: 1px solid var(--bb-color-control-border);
|
|
91
|
+
border-radius: 6px;
|
|
92
|
+
background: var(--bb-color-paper);
|
|
93
|
+
color: var(--bb-color-ink);
|
|
94
|
+
font: inherit;
|
|
95
|
+
font-size: 13px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.bb-pm-filter-options {
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-wrap: wrap;
|
|
101
|
+
gap: 6px;
|
|
102
|
+
margin-top: 8px;
|
|
103
|
+
padding: 8px;
|
|
104
|
+
border: 1px solid var(--bb-color-border);
|
|
105
|
+
border-radius: 8px;
|
|
106
|
+
background: var(--bb-color-surface);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.bb-pm-option {
|
|
110
|
+
padding: 4px 10px;
|
|
111
|
+
border: 1px solid var(--bb-color-border);
|
|
112
|
+
border-radius: 999px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.bb-pm-option.is-selected {
|
|
116
|
+
border-color: var(--bb-color-accent);
|
|
117
|
+
background: var(--bb-color-accent-soft);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.bb-pm-ledger .bb-ws-ledger-row {
|
|
121
|
+
grid-template-columns: 112px minmax(0, 1fr) minmax(0, 168px) 132px 72px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.bb-pm-ledger .bb-ws-ledger-row > span.bb-pm-kind,
|
|
125
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:first-child {
|
|
126
|
+
color: var(--bb-color-muted);
|
|
127
|
+
font-size: 12px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:nth-child(2) {
|
|
131
|
+
white-space: normal;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.bb-pm-excerpt {
|
|
135
|
+
display: -webkit-box;
|
|
136
|
+
overflow: hidden;
|
|
137
|
+
-webkit-box-orient: vertical;
|
|
138
|
+
-webkit-line-clamp: 2;
|
|
139
|
+
line-height: 1.5;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.bb-pm-ledger .bb-ws-ledger-row.is-past .bb-pm-excerpt > span:last-child {
|
|
143
|
+
color: var(--bb-color-muted);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.bb-pm-ledger .bb-ws-ledger-row > span.is-none,
|
|
147
|
+
.bb-pm-ledger .bb-ws-ledger-row > span.is-unknown,
|
|
148
|
+
.bb-pm-ledger .bb-ws-ledger-row > span.is-loading,
|
|
149
|
+
.bb-pm-updated {
|
|
150
|
+
color: var(--bb-color-muted);
|
|
151
|
+
font-size: 12px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.bb-pm-state,
|
|
155
|
+
.bb-pm-inferred {
|
|
156
|
+
display: inline-block;
|
|
157
|
+
margin-right: 6px;
|
|
158
|
+
padding: 0 6px;
|
|
159
|
+
border: 1px solid var(--bb-color-border-strong);
|
|
160
|
+
border-radius: 4px;
|
|
161
|
+
color: var(--bb-color-muted);
|
|
162
|
+
font-size: 11px;
|
|
163
|
+
line-height: 18px;
|
|
164
|
+
vertical-align: 1px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.bb-pm-state.is-active {
|
|
168
|
+
border-color: var(--bb-color-success);
|
|
169
|
+
color: var(--bb-color-success);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.bb-pm-inferred {
|
|
173
|
+
margin: 0 0 0 6px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.bb-pm-origin {
|
|
177
|
+
font-size: 12px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.bb-pm-empty {
|
|
181
|
+
padding: 28px 16px;
|
|
182
|
+
border: 1px dashed var(--bb-color-border-strong);
|
|
183
|
+
border-radius: 8px;
|
|
184
|
+
color: var(--bb-color-ink);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.bb-pm-empty p {
|
|
188
|
+
margin: 6px 0 0;
|
|
189
|
+
color: var(--bb-color-muted);
|
|
190
|
+
font-size: 13px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.bb-pm-muted {
|
|
194
|
+
margin: 0;
|
|
195
|
+
color: var(--bb-color-muted);
|
|
196
|
+
font-size: 12px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.bb-pm-status > .bb-pm-state {
|
|
200
|
+
margin-bottom: 6px;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.bb-pm-history,
|
|
204
|
+
.bb-pm-judgment-list {
|
|
205
|
+
margin: 6px 0 0;
|
|
206
|
+
padding-left: 18px;
|
|
207
|
+
font-size: 13px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.bb-pm-judgment-list li {
|
|
211
|
+
margin: 0 0 6px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.bb-pm-judgment-list li > .bb-pm-muted {
|
|
215
|
+
margin-left: 8px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.bb-pm-record {
|
|
219
|
+
margin-top: 16px;
|
|
220
|
+
font-size: 12px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.bb-pm-record summary {
|
|
224
|
+
cursor: pointer;
|
|
225
|
+
color: var(--bb-color-muted);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.bb-pm-detail-inline {
|
|
229
|
+
margin-top: 20px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@media (max-width: 760px) {
|
|
233
|
+
.bb-pm-ledger .bb-ws-ledger-row {
|
|
234
|
+
grid-template-columns: minmax(0, 1fr) 124px;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:nth-child(4) {
|
|
238
|
+
white-space: normal;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:nth-child(1),
|
|
242
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:nth-child(3),
|
|
243
|
+
.bb-pm-ledger .bb-ws-ledger-row > span:nth-child(5) {
|
|
244
|
+
display: none;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* The detail's head is the memory itself: body-sized, not a page title. */
|
|
249
|
+
.bb-pm-detail .bb-ws-rail-head h2 {
|
|
250
|
+
font-size: 16px;
|
|
251
|
+
font-weight: 600;
|
|
252
|
+
line-height: 1.6;
|
|
253
|
+
white-space: pre-wrap;
|
|
254
|
+
}
|