@things-factory/figure-ui 10.1.210 → 10.1.212
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/client/graphql/index.ts +1 -1
- package/client/modeller/angle-dial.ts +1 -1
- package/client/modeller/canvas.ts +1 -1
- package/client/modeller/editor.ts +24 -32
- package/client/modeller/figure-history-panel.ts +1 -1
- package/client/modeller/figure-links.ts +61 -37
- package/client/modeller/figure-parts.ts +3 -3
- package/client/modeller/figure-settings.ts +1 -1
- package/client/modeller/figure-size-editor.ts +41 -4
- package/client/modeller/links.ts +63 -24
- package/client/modeller/live.ts +33 -0
- package/client/modeller/scene-budget.ts +3 -3
- package/client/modeller/thumbnail.ts +1 -1
- package/client/pages/figure-list-page.ts +2 -2
- package/client/pages/figure-modeller-page.ts +4 -4
- package/client/types.ts +2 -2
- package/client/viewparts/figure-thumb.ts +1 -1
- package/dist-client/graphql/index.d.ts +1 -1
- package/dist-client/graphql/index.js +1 -1
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/angle-dial.d.ts +1 -1
- package/dist-client/modeller/angle-dial.js.map +1 -1
- package/dist-client/modeller/canvas.js +1 -1
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +5 -0
- package/dist-client/modeller/editor.js +24 -32
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.d.ts +1 -1
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +2 -0
- package/dist-client/modeller/figure-links.js +66 -39
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-parts.d.ts +3 -3
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-settings.js +1 -1
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-size-editor.d.ts +3 -1
- package/dist-client/modeller/figure-size-editor.js +45 -4
- package/dist-client/modeller/figure-size-editor.js.map +1 -1
- package/dist-client/modeller/links.d.ts +15 -6
- package/dist-client/modeller/links.js +63 -25
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/live.d.ts +14 -0
- package/dist-client/modeller/live.js +31 -0
- package/dist-client/modeller/live.js.map +1 -1
- package/dist-client/modeller/scene-budget.d.ts +3 -3
- package/dist-client/modeller/scene-budget.js +3 -3
- package/dist-client/modeller/scene-budget.js.map +1 -1
- package/dist-client/modeller/thumbnail.js +1 -1
- package/dist-client/modeller/thumbnail.js.map +1 -1
- package/dist-client/pages/figure-list-page.d.ts +1 -1
- package/dist-client/pages/figure-list-page.js +2 -2
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +3 -3
- package/dist-client/pages/figure-modeller-page.js +4 -4
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/types.d.ts +2 -2
- package/dist-client/types.js +1 -1
- package/dist-client/types.js.map +1 -1
- package/dist-client/viewparts/figure-thumb.js +1 -1
- package/dist-client/viewparts/figure-thumb.js.map +1 -1
- package/docs/multipart-response-review-2026-10-24.md +1 -1
- package/docs/response-authoring-2026-10-24.md +4 -4
- package/package.json +6 -6
- package/test/ai-proposal.test.ts +1 -1
- package/test/align.test.ts +1 -1
- package/test/browser/editing.check.mjs +38 -0
- package/test/browser/modeller.check.mjs +55 -0
- package/test/command-preview.test.ts +3 -3
- package/test/fields.test.ts +2 -2
- package/test/first-minute.test.ts +5 -5
- package/test/first-save.test.ts +3 -3
- package/test/gizmo.test.ts +3 -3
- package/test/keys.test.ts +2 -2
- package/test/layout.test.ts +1 -1
- package/test/links.test.ts +53 -14
- package/test/live.test.ts +4 -4
- package/test/material.test.ts +1 -1
- package/test/properties.test.ts +1 -1
- package/test/proposal-record.test.ts +1 -1
- package/test/refusals.test.ts +1 -1
- package/test/resize-with-placement.test.ts +1 -1
- package/test/scene-budget.test.ts +4 -4
- package/test/verdict.test.ts +1 -1
- package/translations/en.json +3 -0
- package/translations/es.json +3 -0
- package/translations/ja.json +3 -0
- package/translations/ko.json +109 -106
- package/translations/ms.json +3 -0
- package/translations/zh.json +3 -0
|
@@ -27,7 +27,7 @@ declare const FigureHistoryPanel_base: (new (...args: any[]) => LitElement) & ty
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class FigureHistoryPanel extends FigureHistoryPanel_base {
|
|
29
29
|
static styles: import("lit").CSSResult[];
|
|
30
|
-
/** 지금 열려 있는
|
|
30
|
+
/** 지금 열려 있는 피규어. 없으면(새로 만드는 중) 발행할 것이 없다. */
|
|
31
31
|
figureId?: string;
|
|
32
32
|
figureState?: 'draft' | 'released';
|
|
33
33
|
figureVersion: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-history-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-history-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { openPopup } from '@operato/layout'\nimport './figure-revert-choice.js'\nimport type { RevertChoice } from './figure-revert-choice.js'\nimport '@material/web/icon/icon.js'\n\nimport { gateFindingStyles, renderGateFinding } from './gate-findings.js'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { getPathInfo } from '@operato/utils'\nimport { fetchFigureVersions, fetchReplacedDrafts, inspectFigure, releaseFigure, revertFigureVersion, undoFigureRevert } from '../graphql/index.js'\nimport type { KeptDraft } from '../graphql/index.js'\nimport { afterRevertAnswer, revertOutcomeUnknown, revertRequestFor } from './revert-request.js'\nimport { packageHrefOf } from './modeller-route.js'\nimport type { RevertRequest } from './revert-request.js'\nimport type { FigureGateFinding, FigureInspection, FigureVersion } from '../types.js'\nimport { OxPrompt } from '@operato/popup'\n\n/**\n * 이력 — **발행하는 자리이자, 발행된 판들을 보는 자리.**\n *\n * ## 왜 저장 옆이 아니라 여기인가\n *\n * 저장은 하루에 수십 번이고 발행은 드물다. 두 단추를 나란히 두면 저장하려다 발행을 누른다.\n * 그리고 발행은 **소비처에게 하는 약속**이라, 무엇을 약속하는지(지금 몇 판인가 · 저장 안 한 것이\n * 있나 · 지난 판이 무엇이었나)를 함께 보여 주는 자리에 있어야 한다.\n *\n * ## 저장하지 않은 것이 있으면 발행하지 않는다\n *\n * 발행은 **저장된 것**을 내보낸다. 화면에 고친 것이 남아 있는 채로 발행하면, 저작자가 보고 있는\n * 것과 약속한 것이 다르다. 그래서 막고, 왜 막혔는지 적는다.\n *\n * ## 되돌리기는 초안으로 돌아온다\n *\n * 옛 판의 정본·속성·그림이 돌아오고 이름·설명은 그대로다. 되살렸다고 그 판이 다시 발행되지는\n * 않는다 — 다시 내보내려면 발행을 한 번 더 하고, 그때 번호는 이미 쓴 다음 번호를 받는다.\n *\n * 덮이는 초안은 서버가 같은 트랜잭션에서 보관하고, 「되돌리기 전 초안」에 남는다(ADR-0097 §5.6, 디자이너 2026-09-27).\n * 발행 판과 섞지 않는다. 다시 접속해도 거기서 찾고, 가장 최근 것은 「되돌리기 취소」로 되살린다 — 되돌린 뒤 모델이\n * 바뀌었으면 서버가 거절하고 보관본은 남는다.\n */\n@customElement('figure-history-panel')\nexport class FigureHistoryPanel extends localize(i18next)(LitElement) {\n static styles = [\n gateFindingStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n :host([off]) {\n display: none;\n }\n\n section {\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n h3 {\n margin: 0 0 6px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* 지금 무엇인가 — 발행을 누르기 전에 읽는 한 줄 */\n div[now] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 8px;\n }\n\n span[state] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n span[state][released] {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n }\n\n span[ver] {\n font-family: var(--ui-mono, ui-monospace, monospace);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n input,\n button {\n font: var(--input-field-font, inherit);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n input[note] {\n width: 100%;\n box-sizing: border-box;\n padding: 5px 8px;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n button[release] {\n width: 100%;\n margin-top: 6px;\n padding: 6px 0;\n font-weight: 700;\n color: var(--ui-on-accent, #fff);\n background-color: var(--md-sys-color-primary);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n }\n\n button[release][disabled] {\n opacity: 0.45;\n cursor: default;\n }\n\n /* 왜 못 누르는지 — 눌러 보고 알게 하지 않는다 */\n p[why] {\n margin: 6px 0 0 0;\n font-size: var(--ui-t-micro, 11px);\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n p[failed] {\n margin: 6px 0 0 0;\n font-size: var(--ui-t-micro, 11px);\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n\n ul {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n li {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 4px 8px;\n align-items: baseline;\n padding: 7px 0;\n border-bottom: 1px dashed var(--md-sys-color-outline-variant);\n }\n\n li:last-child {\n border-bottom: 0;\n }\n\n li span[no] {\n font-family: var(--ui-mono, ui-monospace, monospace);\n font-weight: 700;\n }\n\n li span[when] {\n grid-column: 2 / 4;\n font-size: var(--ui-t-micro, 11px);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n li span[comment] {\n grid-column: 1 / 4;\n line-height: 1.5;\n }\n\n li button[revert] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n\n li a[package] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n text-decoration: none;\n }\n\n li button[revert]:hover {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n 게이트 사유. 막는 것은 색으로도 말하고, 알리는 것은 조용히 둔다 — 둘을 같은 톤으로 두면\n 「이 중 어느 것이 발행을 막았나」를 사람이 다시 세어야 한다.\n */\n\n p[quiet] {\n margin: 0;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n `\n ]\n\n /** 지금 열려 있는 도형. 없으면(새로 만드는 중) 발행할 것이 없다. */\n @property({ type: String }) figureId?: string\n @property({ type: String }) figureState?: 'draft' | 'released'\n @property({ type: Number }) figureVersion = 0\n /** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */\n @property({ type: Boolean }) dirty = false\n /** Saves the edits in hand before reverting; `ok` only when the save is known to have happened. */\n @property({ attribute: false }) saveFirst?: () => Promise<{ ok: boolean; reason?: string }>\n /** The source the server is confirmed to hold: a revert goes on only while the server still holds it. */\n @property({ attribute: false }) serverSource?: () => string | undefined\n /**\n * 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면\n * 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」\n * 판정이 남아 발행 단추가 잠긴 채다.\n */\n @property({ type: String }) figureType?: string\n /** The namespace of the full name: with it a released version can be downloaded as a package (ADR-0114). */\n @property({ type: String }) figureNamespace?: string\n\n @state() private versions: FigureVersion[] = []\n /** Drafts reverts kept, newest first -- apart from the released versions. */\n @state() private kept: KeptDraft[] = []\n /**\n * A revert or undo whose answer never came back. Asked again, it goes with the same request id, so the server\n * answers with what it did rather than doing it twice. Any answer -- done or refused -- lets it go.\n */\n private pending?: RevertRequest\n @state() private busy = false\n @state() private failure = ''\n /**\n * 발행 판정. **저장된 정본에 대한 것**이라 저장할 때마다 다시 묻는다(`figureVersion` 이 아니라\n * `dirty` 가 풀리는 순간이 그때다).\n */\n @state() private inspection?: FigureInspection\n\n updated(changes: Map<string, unknown>) {\n if (changes.has('figureId') || changes.has('figureVersion')) {\n void this.reload()\n }\n\n /*\n 저장이 끝난 순간(dirty 가 풀림) 정본이 바뀌었으니 판정을 다시 묻는다. 저작 중(dirty)에는\n 묻지 않는다 — 서버에 있는 것은 저장 전 정본이라, 그 답은 화면에 있는 것과 다른 것을 말한다.\n */\n if (changes.has('figureId') || changes.has('dirty') || changes.has('figureType')) {\n void this.inspect()\n }\n }\n\n private async inspect() {\n if (!this.figureId || this.dirty) {\n this.inspection = undefined\n return\n }\n\n try {\n this.inspection = await inspectFigure(this.figureId)\n } catch (e) {\n /* 판정을 못 받은 것을 「통과」로 두지 않는다 — 모르는 것이다. 단추는 서버가 막는다. */\n this.inspection = undefined\n this.failure = (e as Error).message\n }\n }\n\n private async reload() {\n if (!this.figureId) {\n this.versions = []\n this.kept = []\n return\n }\n\n try {\n ;[this.versions, this.kept] = await Promise.all([fetchFigureVersions(this.figureId), fetchReplacedDrafts(this.figureId)])\n this.failure = ''\n } catch (e) {\n this.failure = (e as Error).message\n }\n }\n\n /** The release section in view, focus on it: where the top bar's \"release\" leads (ADR-0097 §5.6, Q-D2). */\n async showRelease() {\n await this.updateComplete\n const section = this.renderRoot.querySelector<HTMLElement>('section[release]')\n section?.scrollIntoView({ block: 'start', behavior: 'smooth' })\n ;(section?.querySelector<HTMLElement>('input[note]:not([disabled]), button[release]:not([disabled])') ?? section)?.focus({ preventScroll: true })\n }\n\n render() {\n return html`\n <section release tabindex=\"-1\">\n <h3>${i18next.t('figure.label.release')}</h3>\n ${this.figureId ? this.renderRelease() : html`<p quiet>${i18next.t('figure.text.save-the-figure-before-releasing')}</p>`}\n </section>\n\n <section>\n <h3>${i18next.t('figure.label.released-versions')}</h3>\n ${this.versions.length\n ? html`<ul>\n ${this.versions.map(version => this.renderVersion(version))}\n </ul>`\n : html`<p quiet>${i18next.t('figure.text.nothing-released-yet')}</p>`}\n </section>\n\n ${this.kept.length\n ? html`<section kept>\n <h3>${i18next.t('figure.label.kept-drafts')}</h3>\n <ul>\n ${this.kept.map((kept, index) => this.renderKept(kept, index === 0))}\n </ul>\n </section>`\n : nothing}\n `\n }\n\n private renderRelease() {\n const released = this.figureState === 'released'\n\n /*\n 게이트가 막는 것과 알리는 것을 함께 낸다. **막는 것은 단추를 잠근다** — 눌러 보고 서버에게\n 거절당하는 것으로 알게 하지 않는다. 알리는 것은 잠그지 않고 그대로 보여 준다.\n */\n const blocking = (this.inspection?.findings ?? []).filter(finding => finding.blocking)\n const advisory = (this.inspection?.findings ?? []).filter(finding => !finding.blocking)\n\n /*\n ── 「발행되나」에 **한 번만** 답한다 ─────────────────────────────────────\n 전에는 막는 목록의 머리가 「이것들이 발행을 막습니다」, 알리는 목록의 머리가 「발행은 되지만\n 확인해 보십시오」였다. 두 줄이 나란히 서서 화면이 「막힌다」와 「된다」를 함께 말했고, 사람이\n 「그래서 되는 건가」를 되물었다.\n\n 답은 이 한 줄이 하고, 아래 목록들은 **이유**일 뿐이다 — 그래서 목록 머리는 문장이 아니라\n 이름씨다(「고쳐야 하는 것」·「막지는 않는 것」).\n */\n const why = this.dirty\n ? i18next.t('figure.text.release-needs-a-save-first')\n : released\n ? i18next.t('figure.text.already-released-edit-to-release-again')\n : blocking.length\n ? i18next.t('figure.text.cannot-release-now')\n : ''\n\n return html`\n <div now>\n <span state ?released=${released}>${i18next.t(released ? 'figure.label.figure-released' : 'figure.label.draft')}</span>\n <span ver>${i18next.t('figure.text.version-number', { version: this.figureVersion ?? 0 })}</span>\n </div>\n\n <input note placeholder=${i18next.t('figure.text.what-changed-in-this-release')} ?disabled=${!!why || this.busy} />\n\n <button release ?disabled=${!!why || this.busy} @click=${() => this.release()}>\n ${this.busy ? i18next.t('figure.text.releasing') : i18next.t('figure.button.release-figure')}\n </button>\n\n ${why ? html`<p why>${why}</p>` : nothing}\n ${blocking.length\n ? html`<ul gate>\n <li head>${i18next.t('figure.text.must-fix-to-release')}</li>\n ${blocking.map(finding => this.renderFinding(finding, true))}\n </ul>`\n : nothing}\n ${advisory.length\n ? html`<ul gate>\n <li head quiet>${i18next.t('figure.text.does-not-block')}</li>\n ${advisory.map(finding => this.renderFinding(finding, false))}\n </ul>`\n : nothing}\n ${this.failure ? html`<p failed>${this.failure}</p>` : nothing}\n `\n }\n\n /**\n * 사유 한 줄 — **잰 것 · 왜 · 어떻게** 셋을 함께 말한다.\n *\n * 잰 것만 보여 줬더니 「1 조각이 2 조각으로 갈라진다」에서 사람이 멈췄다. 왜 나쁜지도, 무엇을\n * 바꾸면 되는지도 알 수 없었다. 그 셋은 형식(`figure-model` 의 gate)이 만들고 여기서는 자리만\n * 준다 — 화면이 문장을 지으면 서버가 거절할 때와 다른 말을 하게 된다.\n */\n private renderFinding(finding: FigureGateFinding, blocking: boolean) {\n return renderGateFinding(finding, blocking, nothing)\n }\n\n /** Where one released version downloads as a package file, or undefined before the figure has a full name. */\n private packageHref(version: number): string | undefined {\n return packageHrefOf(getPathInfo(location.pathname).contextPath, this.figureNamespace, this.figureType, version)\n }\n\n private renderVersion(version: FigureVersion) {\n return html`\n <li>\n <span no>${i18next.t('figure.text.version-number', { version: version.version })}</span>\n <span when>\n ${version.updatedAt ? new Date(version.updatedAt).toLocaleString() : ''}\n ${version.updater?.name ? ` · ${version.updater.name}` : ''}\n </span>\n <button revert ?disabled=${this.busy} @click=${() => this.revert(version.version)}>\n ${i18next.t('figure.button.revert')}\n </button>\n ${this.packageHref(version.version)\n ? html`<a package download href=${this.packageHref(version.version)!}>${i18next.t('figure.button.download-package')}</a>`\n : nothing}\n ${version.comment ? html`<span comment>${version.comment}</span>` : nothing}\n </li>\n `\n }\n\n /*\n Only the newest can be taken back: an undo holds only while the figure is what that revert wrote, and a later\n revert or undo has written something else since. The older ones stay listed -- found, not offered.\n */\n private renderKept(kept: KeptDraft, newest: boolean) {\n const what =\n kept.kind === 'undo'\n ? i18next.t('figure.text.kept-before-undo')\n : i18next.t('figure.text.kept-before-revert', { version: String(kept.revertedToVersion ?? '') })\n return html`\n <li>\n <span no>${what}</span>\n <span when>\n ${kept.createdAt ? new Date(kept.createdAt).toLocaleString() : ''} ${kept.creator?.name ? ` · ${kept.creator.name}` : ''}\n ${kept.restoredAt ? ` · ${i18next.t('figure.text.kept-restored')}` : ''}\n </span>\n ${newest && !kept.restoredAt\n ? html`<button revert undo ?disabled=${this.busy} @click=${() => this.undo(kept)}>\n ${i18next.t(kept.kind === 'undo' ? 'figure.button.redo-revert' : 'figure.button.undo-revert')}\n </button>`\n : nothing}\n </li>\n `\n }\n\n private async release() {\n const input = this.renderRoot.querySelector('input[note]') as HTMLInputElement\n const comment = input?.value?.trim()\n\n this.busy = true\n this.failure = ''\n\n try {\n const figure = await releaseFigure(this.figureId!, comment || undefined)\n if (input) input.value = ''\n /* 정본을 든 자리가 갱신한다 — 여기서 페이지 상태를 고쳐 쓰지 않는다. */\n this.dispatchEvent(new CustomEvent('figure-released', { detail: { figure }, bubbles: true, composed: true }))\n await this.reload()\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n\n /**\n * Edits not saved yet: saved first, let go, or kept -- asked with the three (designer 2026-09-27, Q-D1). Reverting and\n * taking a revert back both reopen the figure from the server, so edits not saved would go without a word. `true` to\n * go on.\n */\n private async settleUnsaved(purpose: 'revert' | 'undo', version = 0): Promise<boolean> {\n const choice = await openPopup<RevertChoice>(\n html`<figure-revert-choice .version=${version} .purpose=${purpose}></figure-revert-choice>`,\n { backdrop: true, size: 'small', title: i18next.t(purpose === 'undo' ? 'figure.button.undo-revert' : 'figure.button.revert') }\n ).result\n if (!choice) return false\n if (choice === 'save') {\n /* Saved, and known to be: a save that failed or whose outcome is not known goes no further. */\n const saved = await this.saveFirst?.()\n if (!saved?.ok) {\n this.failure = i18next.t('figure.text.revert-held-unsaved', { reason: saved?.reason ?? '' })\n return false\n }\n }\n return true\n }\n\n private async revert(version: number) {\n this.failure = ''\n if (this.dirty) {\n if (!(await this.settleUnsaved('revert', version))) return\n } else {\n /* 지금 초안은 서버가 보관하지만, 화면의 것이 그 판으로 바뀐다 — 이름으로 확인한다. */\n const agreed = await OxPrompt.open({\n type: 'warning',\n title: i18next.t('figure.button.revert'),\n text: i18next.t('figure.text.revert-to-version-confirm', { version }),\n confirmButton: { text: i18next.t('figure.button.revert') },\n cancelButton: { text: i18next.t('figure.button.keep-editing') }\n })\n if (!agreed) {\n return\n }\n }\n\n /* Read after any save above: what the server is now confirmed to hold. */\n const expected = this.serverSource?.()\n if (expected === undefined) {\n this.failure = i18next.t('figure.text.revert-needs-server-source')\n return\n }\n await this.send(`revert:${version}:${expected}`, requestId => revertFigureVersion(this.figureId!, version, requestId, expected))\n }\n\n private async undo(kept: KeptDraft) {\n this.failure = ''\n if (this.dirty && !(await this.settleUnsaved('undo'))) return\n await this.send(`undo:${kept.id}`, requestId => undoFigureRevert(kept.id, requestId))\n }\n\n /** One revert or undo: a new request id, or the one whose answer was lost when the same is asked again. */\n private async send(key: string, request: (requestId: string) => Promise<unknown>) {\n const sent = revertRequestFor(this.pending, key)\n this.pending = sent\n this.busy = true\n this.failure = ''\n\n try {\n const result = await request(sent.requestId)\n this.pending = undefined\n this.dispatchEvent(new CustomEvent('figure-reverted', { detail: result, bubbles: true, composed: true }))\n await this.reload()\n /*\n **되돌리면 정본이 바뀌므로 판정도 바뀐다.** 이것을 안 하면 옛 판의 사유가 새 정본 위에\n 남아 화면이 거짓말한다 — 되돌리기는 `dirty` 도 `figureVersion` 도 건드리지 않으므로\n `updated` 의 감시로는 다시 묻지 않는다.\n */\n await this.inspect()\n } catch (e) {\n const code = (e as { code?: string })?.code\n /* Not known whether it happened: kept, so the next press asks with the same id. Anything the server said: let go. */\n this.pending = afterRevertAnswer(sent, code)\n if (revertOutcomeUnknown(code)) this.failure = i18next.t('figure.text.revert-unconfirmed')\n else {\n /* Refused: the kept list may have changed under us (another session's undo), so it is read again. */\n await this.reload()\n this.failure = (e as Error).message\n }\n } finally {\n this.busy = false\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-history-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-history-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { openPopup } from '@operato/layout'\nimport './figure-revert-choice.js'\nimport type { RevertChoice } from './figure-revert-choice.js'\nimport '@material/web/icon/icon.js'\n\nimport { gateFindingStyles, renderGateFinding } from './gate-findings.js'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { getPathInfo } from '@operato/utils'\nimport { fetchFigureVersions, fetchReplacedDrafts, inspectFigure, releaseFigure, revertFigureVersion, undoFigureRevert } from '../graphql/index.js'\nimport type { KeptDraft } from '../graphql/index.js'\nimport { afterRevertAnswer, revertOutcomeUnknown, revertRequestFor } from './revert-request.js'\nimport { packageHrefOf } from './modeller-route.js'\nimport type { RevertRequest } from './revert-request.js'\nimport type { FigureGateFinding, FigureInspection, FigureVersion } from '../types.js'\nimport { OxPrompt } from '@operato/popup'\n\n/**\n * 이력 — **발행하는 자리이자, 발행된 판들을 보는 자리.**\n *\n * ## 왜 저장 옆이 아니라 여기인가\n *\n * 저장은 하루에 수십 번이고 발행은 드물다. 두 단추를 나란히 두면 저장하려다 발행을 누른다.\n * 그리고 발행은 **소비처에게 하는 약속**이라, 무엇을 약속하는지(지금 몇 판인가 · 저장 안 한 것이\n * 있나 · 지난 판이 무엇이었나)를 함께 보여 주는 자리에 있어야 한다.\n *\n * ## 저장하지 않은 것이 있으면 발행하지 않는다\n *\n * 발행은 **저장된 것**을 내보낸다. 화면에 고친 것이 남아 있는 채로 발행하면, 저작자가 보고 있는\n * 것과 약속한 것이 다르다. 그래서 막고, 왜 막혔는지 적는다.\n *\n * ## 되돌리기는 초안으로 돌아온다\n *\n * 옛 판의 정본·속성·그림이 돌아오고 이름·설명은 그대로다. 되살렸다고 그 판이 다시 발행되지는\n * 않는다 — 다시 내보내려면 발행을 한 번 더 하고, 그때 번호는 이미 쓴 다음 번호를 받는다.\n *\n * 덮이는 초안은 서버가 같은 트랜잭션에서 보관하고, 「되돌리기 전 초안」에 남는다(ADR-0097 §5.6, 디자이너 2026-09-27).\n * 발행 판과 섞지 않는다. 다시 접속해도 거기서 찾고, 가장 최근 것은 「되돌리기 취소」로 되살린다 — 되돌린 뒤 모델이\n * 바뀌었으면 서버가 거절하고 보관본은 남는다.\n */\n@customElement('figure-history-panel')\nexport class FigureHistoryPanel extends localize(i18next)(LitElement) {\n static styles = [\n gateFindingStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n :host([off]) {\n display: none;\n }\n\n section {\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n h3 {\n margin: 0 0 6px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* 지금 무엇인가 — 발행을 누르기 전에 읽는 한 줄 */\n div[now] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 8px;\n }\n\n span[state] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n span[state][released] {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n }\n\n span[ver] {\n font-family: var(--ui-mono, ui-monospace, monospace);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n input,\n button {\n font: var(--input-field-font, inherit);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n input[note] {\n width: 100%;\n box-sizing: border-box;\n padding: 5px 8px;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n button[release] {\n width: 100%;\n margin-top: 6px;\n padding: 6px 0;\n font-weight: 700;\n color: var(--ui-on-accent, #fff);\n background-color: var(--md-sys-color-primary);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n }\n\n button[release][disabled] {\n opacity: 0.45;\n cursor: default;\n }\n\n /* 왜 못 누르는지 — 눌러 보고 알게 하지 않는다 */\n p[why] {\n margin: 6px 0 0 0;\n font-size: var(--ui-t-micro, 11px);\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n p[failed] {\n margin: 6px 0 0 0;\n font-size: var(--ui-t-micro, 11px);\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n\n ul {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n li {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 4px 8px;\n align-items: baseline;\n padding: 7px 0;\n border-bottom: 1px dashed var(--md-sys-color-outline-variant);\n }\n\n li:last-child {\n border-bottom: 0;\n }\n\n li span[no] {\n font-family: var(--ui-mono, ui-monospace, monospace);\n font-weight: 700;\n }\n\n li span[when] {\n grid-column: 2 / 4;\n font-size: var(--ui-t-micro, 11px);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n li span[comment] {\n grid-column: 1 / 4;\n line-height: 1.5;\n }\n\n li button[revert] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n\n li a[package] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n text-decoration: none;\n }\n\n li button[revert]:hover {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n 게이트 사유. 막는 것은 색으로도 말하고, 알리는 것은 조용히 둔다 — 둘을 같은 톤으로 두면\n 「이 중 어느 것이 발행을 막았나」를 사람이 다시 세어야 한다.\n */\n\n p[quiet] {\n margin: 0;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n `\n ]\n\n /** 지금 열려 있는 피규어. 없으면(새로 만드는 중) 발행할 것이 없다. */\n @property({ type: String }) figureId?: string\n @property({ type: String }) figureState?: 'draft' | 'released'\n @property({ type: Number }) figureVersion = 0\n /** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */\n @property({ type: Boolean }) dirty = false\n /** Saves the edits in hand before reverting; `ok` only when the save is known to have happened. */\n @property({ attribute: false }) saveFirst?: () => Promise<{ ok: boolean; reason?: string }>\n /** The source the server is confirmed to hold: a revert goes on only while the server still holds it. */\n @property({ attribute: false }) serverSource?: () => string | undefined\n /**\n * 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면\n * 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」\n * 판정이 남아 발행 단추가 잠긴 채다.\n */\n @property({ type: String }) figureType?: string\n /** The namespace of the full name: with it a released version can be downloaded as a package (ADR-0114). */\n @property({ type: String }) figureNamespace?: string\n\n @state() private versions: FigureVersion[] = []\n /** Drafts reverts kept, newest first -- apart from the released versions. */\n @state() private kept: KeptDraft[] = []\n /**\n * A revert or undo whose answer never came back. Asked again, it goes with the same request id, so the server\n * answers with what it did rather than doing it twice. Any answer -- done or refused -- lets it go.\n */\n private pending?: RevertRequest\n @state() private busy = false\n @state() private failure = ''\n /**\n * 발행 판정. **저장된 정본에 대한 것**이라 저장할 때마다 다시 묻는다(`figureVersion` 이 아니라\n * `dirty` 가 풀리는 순간이 그때다).\n */\n @state() private inspection?: FigureInspection\n\n updated(changes: Map<string, unknown>) {\n if (changes.has('figureId') || changes.has('figureVersion')) {\n void this.reload()\n }\n\n /*\n 저장이 끝난 순간(dirty 가 풀림) 정본이 바뀌었으니 판정을 다시 묻는다. 저작 중(dirty)에는\n 묻지 않는다 — 서버에 있는 것은 저장 전 정본이라, 그 답은 화면에 있는 것과 다른 것을 말한다.\n */\n if (changes.has('figureId') || changes.has('dirty') || changes.has('figureType')) {\n void this.inspect()\n }\n }\n\n private async inspect() {\n if (!this.figureId || this.dirty) {\n this.inspection = undefined\n return\n }\n\n try {\n this.inspection = await inspectFigure(this.figureId)\n } catch (e) {\n /* 판정을 못 받은 것을 「통과」로 두지 않는다 — 모르는 것이다. 단추는 서버가 막는다. */\n this.inspection = undefined\n this.failure = (e as Error).message\n }\n }\n\n private async reload() {\n if (!this.figureId) {\n this.versions = []\n this.kept = []\n return\n }\n\n try {\n ;[this.versions, this.kept] = await Promise.all([fetchFigureVersions(this.figureId), fetchReplacedDrafts(this.figureId)])\n this.failure = ''\n } catch (e) {\n this.failure = (e as Error).message\n }\n }\n\n /** The release section in view, focus on it: where the top bar's \"release\" leads (ADR-0097 §5.6, Q-D2). */\n async showRelease() {\n await this.updateComplete\n const section = this.renderRoot.querySelector<HTMLElement>('section[release]')\n section?.scrollIntoView({ block: 'start', behavior: 'smooth' })\n ;(section?.querySelector<HTMLElement>('input[note]:not([disabled]), button[release]:not([disabled])') ?? section)?.focus({ preventScroll: true })\n }\n\n render() {\n return html`\n <section release tabindex=\"-1\">\n <h3>${i18next.t('figure.label.release')}</h3>\n ${this.figureId ? this.renderRelease() : html`<p quiet>${i18next.t('figure.text.save-the-figure-before-releasing')}</p>`}\n </section>\n\n <section>\n <h3>${i18next.t('figure.label.released-versions')}</h3>\n ${this.versions.length\n ? html`<ul>\n ${this.versions.map(version => this.renderVersion(version))}\n </ul>`\n : html`<p quiet>${i18next.t('figure.text.nothing-released-yet')}</p>`}\n </section>\n\n ${this.kept.length\n ? html`<section kept>\n <h3>${i18next.t('figure.label.kept-drafts')}</h3>\n <ul>\n ${this.kept.map((kept, index) => this.renderKept(kept, index === 0))}\n </ul>\n </section>`\n : nothing}\n `\n }\n\n private renderRelease() {\n const released = this.figureState === 'released'\n\n /*\n 게이트가 막는 것과 알리는 것을 함께 낸다. **막는 것은 단추를 잠근다** — 눌러 보고 서버에게\n 거절당하는 것으로 알게 하지 않는다. 알리는 것은 잠그지 않고 그대로 보여 준다.\n */\n const blocking = (this.inspection?.findings ?? []).filter(finding => finding.blocking)\n const advisory = (this.inspection?.findings ?? []).filter(finding => !finding.blocking)\n\n /*\n ── 「발행되나」에 **한 번만** 답한다 ─────────────────────────────────────\n 전에는 막는 목록의 머리가 「이것들이 발행을 막습니다」, 알리는 목록의 머리가 「발행은 되지만\n 확인해 보십시오」였다. 두 줄이 나란히 서서 화면이 「막힌다」와 「된다」를 함께 말했고, 사람이\n 「그래서 되는 건가」를 되물었다.\n\n 답은 이 한 줄이 하고, 아래 목록들은 **이유**일 뿐이다 — 그래서 목록 머리는 문장이 아니라\n 이름씨다(「고쳐야 하는 것」·「막지는 않는 것」).\n */\n const why = this.dirty\n ? i18next.t('figure.text.release-needs-a-save-first')\n : released\n ? i18next.t('figure.text.already-released-edit-to-release-again')\n : blocking.length\n ? i18next.t('figure.text.cannot-release-now')\n : ''\n\n return html`\n <div now>\n <span state ?released=${released}>${i18next.t(released ? 'figure.label.figure-released' : 'figure.label.draft')}</span>\n <span ver>${i18next.t('figure.text.version-number', { version: this.figureVersion ?? 0 })}</span>\n </div>\n\n <input note placeholder=${i18next.t('figure.text.what-changed-in-this-release')} ?disabled=${!!why || this.busy} />\n\n <button release ?disabled=${!!why || this.busy} @click=${() => this.release()}>\n ${this.busy ? i18next.t('figure.text.releasing') : i18next.t('figure.button.release-figure')}\n </button>\n\n ${why ? html`<p why>${why}</p>` : nothing}\n ${blocking.length\n ? html`<ul gate>\n <li head>${i18next.t('figure.text.must-fix-to-release')}</li>\n ${blocking.map(finding => this.renderFinding(finding, true))}\n </ul>`\n : nothing}\n ${advisory.length\n ? html`<ul gate>\n <li head quiet>${i18next.t('figure.text.does-not-block')}</li>\n ${advisory.map(finding => this.renderFinding(finding, false))}\n </ul>`\n : nothing}\n ${this.failure ? html`<p failed>${this.failure}</p>` : nothing}\n `\n }\n\n /**\n * 사유 한 줄 — **잰 것 · 왜 · 어떻게** 셋을 함께 말한다.\n *\n * 잰 것만 보여 줬더니 「1 조각이 2 조각으로 갈라진다」에서 사람이 멈췄다. 왜 나쁜지도, 무엇을\n * 바꾸면 되는지도 알 수 없었다. 그 셋은 형식(`figure-model` 의 gate)이 만들고 여기서는 자리만\n * 준다 — 화면이 문장을 지으면 서버가 거절할 때와 다른 말을 하게 된다.\n */\n private renderFinding(finding: FigureGateFinding, blocking: boolean) {\n return renderGateFinding(finding, blocking, nothing)\n }\n\n /** Where one released version downloads as a package file, or undefined before the figure has a full name. */\n private packageHref(version: number): string | undefined {\n return packageHrefOf(getPathInfo(location.pathname).contextPath, this.figureNamespace, this.figureType, version)\n }\n\n private renderVersion(version: FigureVersion) {\n return html`\n <li>\n <span no>${i18next.t('figure.text.version-number', { version: version.version })}</span>\n <span when>\n ${version.updatedAt ? new Date(version.updatedAt).toLocaleString() : ''}\n ${version.updater?.name ? ` · ${version.updater.name}` : ''}\n </span>\n <button revert ?disabled=${this.busy} @click=${() => this.revert(version.version)}>\n ${i18next.t('figure.button.revert')}\n </button>\n ${this.packageHref(version.version)\n ? html`<a package download href=${this.packageHref(version.version)!}>${i18next.t('figure.button.download-package')}</a>`\n : nothing}\n ${version.comment ? html`<span comment>${version.comment}</span>` : nothing}\n </li>\n `\n }\n\n /*\n Only the newest can be taken back: an undo holds only while the figure is what that revert wrote, and a later\n revert or undo has written something else since. The older ones stay listed -- found, not offered.\n */\n private renderKept(kept: KeptDraft, newest: boolean) {\n const what =\n kept.kind === 'undo'\n ? i18next.t('figure.text.kept-before-undo')\n : i18next.t('figure.text.kept-before-revert', { version: String(kept.revertedToVersion ?? '') })\n return html`\n <li>\n <span no>${what}</span>\n <span when>\n ${kept.createdAt ? new Date(kept.createdAt).toLocaleString() : ''} ${kept.creator?.name ? ` · ${kept.creator.name}` : ''}\n ${kept.restoredAt ? ` · ${i18next.t('figure.text.kept-restored')}` : ''}\n </span>\n ${newest && !kept.restoredAt\n ? html`<button revert undo ?disabled=${this.busy} @click=${() => this.undo(kept)}>\n ${i18next.t(kept.kind === 'undo' ? 'figure.button.redo-revert' : 'figure.button.undo-revert')}\n </button>`\n : nothing}\n </li>\n `\n }\n\n private async release() {\n const input = this.renderRoot.querySelector('input[note]') as HTMLInputElement\n const comment = input?.value?.trim()\n\n this.busy = true\n this.failure = ''\n\n try {\n const figure = await releaseFigure(this.figureId!, comment || undefined)\n if (input) input.value = ''\n /* 정본을 든 자리가 갱신한다 — 여기서 페이지 상태를 고쳐 쓰지 않는다. */\n this.dispatchEvent(new CustomEvent('figure-released', { detail: { figure }, bubbles: true, composed: true }))\n await this.reload()\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n\n /**\n * Edits not saved yet: saved first, let go, or kept -- asked with the three (designer 2026-09-27, Q-D1). Reverting and\n * taking a revert back both reopen the figure from the server, so edits not saved would go without a word. `true` to\n * go on.\n */\n private async settleUnsaved(purpose: 'revert' | 'undo', version = 0): Promise<boolean> {\n const choice = await openPopup<RevertChoice>(\n html`<figure-revert-choice .version=${version} .purpose=${purpose}></figure-revert-choice>`,\n { backdrop: true, size: 'small', title: i18next.t(purpose === 'undo' ? 'figure.button.undo-revert' : 'figure.button.revert') }\n ).result\n if (!choice) return false\n if (choice === 'save') {\n /* Saved, and known to be: a save that failed or whose outcome is not known goes no further. */\n const saved = await this.saveFirst?.()\n if (!saved?.ok) {\n this.failure = i18next.t('figure.text.revert-held-unsaved', { reason: saved?.reason ?? '' })\n return false\n }\n }\n return true\n }\n\n private async revert(version: number) {\n this.failure = ''\n if (this.dirty) {\n if (!(await this.settleUnsaved('revert', version))) return\n } else {\n /* 지금 초안은 서버가 보관하지만, 화면의 것이 그 판으로 바뀐다 — 이름으로 확인한다. */\n const agreed = await OxPrompt.open({\n type: 'warning',\n title: i18next.t('figure.button.revert'),\n text: i18next.t('figure.text.revert-to-version-confirm', { version }),\n confirmButton: { text: i18next.t('figure.button.revert') },\n cancelButton: { text: i18next.t('figure.button.keep-editing') }\n })\n if (!agreed) {\n return\n }\n }\n\n /* Read after any save above: what the server is now confirmed to hold. */\n const expected = this.serverSource?.()\n if (expected === undefined) {\n this.failure = i18next.t('figure.text.revert-needs-server-source')\n return\n }\n await this.send(`revert:${version}:${expected}`, requestId => revertFigureVersion(this.figureId!, version, requestId, expected))\n }\n\n private async undo(kept: KeptDraft) {\n this.failure = ''\n if (this.dirty && !(await this.settleUnsaved('undo'))) return\n await this.send(`undo:${kept.id}`, requestId => undoFigureRevert(kept.id, requestId))\n }\n\n /** One revert or undo: a new request id, or the one whose answer was lost when the same is asked again. */\n private async send(key: string, request: (requestId: string) => Promise<unknown>) {\n const sent = revertRequestFor(this.pending, key)\n this.pending = sent\n this.busy = true\n this.failure = ''\n\n try {\n const result = await request(sent.requestId)\n this.pending = undefined\n this.dispatchEvent(new CustomEvent('figure-reverted', { detail: result, bubbles: true, composed: true }))\n await this.reload()\n /*\n **되돌리면 정본이 바뀌므로 판정도 바뀐다.** 이것을 안 하면 옛 판의 사유가 새 정본 위에\n 남아 화면이 거짓말한다 — 되돌리기는 `dirty` 도 `figureVersion` 도 건드리지 않으므로\n `updated` 의 감시로는 다시 묻지 않는다.\n */\n await this.inspect()\n } catch (e) {\n const code = (e as { code?: string })?.code\n /* Not known whether it happened: kept, so the next press asks with the same id. Anything the server said: let go. */\n this.pending = afterRevertAnswer(sent, code)\n if (revertOutcomeUnknown(code)) this.failure = i18next.t('figure.text.revert-unconfirmed')\n else {\n /* Refused: the kept list may have changed under us (another session's undo), so it is read again. */\n await this.reload()\n this.failure = (e as Error).message\n }\n } finally {\n this.busy = false\n }\n }\n}\n"]}
|
|
@@ -65,6 +65,8 @@ export declare class FigureLinks extends FigureLinks_base {
|
|
|
65
65
|
private row;
|
|
66
66
|
/** The motion form is open over the part's own motion, to change it where it is. */
|
|
67
67
|
private editingMotion;
|
|
68
|
+
/** Which of the joint's axes the form is over (ADR-0159); one past the last is a new axis. */
|
|
69
|
+
private motionAxis;
|
|
68
70
|
private loadedFor?;
|
|
69
71
|
willUpdate(changed: Map<string, unknown>): void;
|
|
70
72
|
updated(): void;
|
|
@@ -6,8 +6,8 @@ import './figure-slot-layout-panel.js';
|
|
|
6
6
|
import './figure-size-editor.js';
|
|
7
7
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
8
8
|
import { i18next, localize } from '@operato/i18n';
|
|
9
|
-
import { figureFaceOverhangOf } from '@hatiolab/figure-model';
|
|
10
|
-
import { acceptsOf, AXES, canFasten, canFollow, positionIsShare, heldBy, shownWhenOf, visibilityControlsOf, fasteningOf, hasInstanceSize, holdsThings, leadersFor, motionOf, motionFormOf, motionFormRefusalOf, endPlaceKeyOf, motionJoint, placeFacesOf, placeIdFor, placesOn, rowAxesOf, rowBlockOf, fixedJointOf, rowOf, positionsWorkedOut } from './links.js';
|
|
9
|
+
import { figureFaceOverhangOf, figureMotionsOf, motionIdOf } from '@hatiolab/figure-model';
|
|
10
|
+
import { acceptsOf, AXES, canFasten, canFollow, positionIsShare, heldBy, shownWhenOf, visibilityControlsOf, fasteningOf, hasInstanceSize, holdsThings, leadersFor, motionOf, motionFormOf, motionFormRefusalOf, endPlaceKeyOf, motionJoint, controlIdFor, withoutAxis, placeFacesOf, placeIdFor, placesOn, rowAxesOf, rowBlockOf, fixedJointOf, rowOf, positionsWorkedOut } from './links.js';
|
|
11
11
|
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js';
|
|
12
12
|
import { insideAlignmentOf } from './fasten-geometry.js';
|
|
13
13
|
import { fastenFormOf, fastenPlanOf, fastenSentenceOf } from './fasten-form.js';
|
|
@@ -66,6 +66,8 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
66
66
|
this.row = freshRow();
|
|
67
67
|
/** The motion form is open over the part's own motion, to change it where it is. */
|
|
68
68
|
this.editingMotion = false;
|
|
69
|
+
/** Which of the joint's axes the form is over (ADR-0159); one past the last is a new axis. */
|
|
70
|
+
this.motionAxis = 0;
|
|
69
71
|
}
|
|
70
72
|
static { this.styles = [SidePanelStyles, GroupMenuStyles, css `
|
|
71
73
|
:host {
|
|
@@ -153,6 +155,7 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
153
155
|
this.rowOpen = false;
|
|
154
156
|
this.rowCandidate = undefined;
|
|
155
157
|
this.editingMotion = false;
|
|
158
|
+
this.motionAxis = 0;
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
161
|
updated() {
|
|
@@ -562,6 +565,45 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
562
565
|
/* Which part moves, against what, which way, how far -- by name (ADR-0097 §5.5). */
|
|
563
566
|
const against = joint ? ('plane' in joint.body0 ? i18next.t('figure.label.mounting-plane') : joint.body0.part) : '';
|
|
564
567
|
const ends = this.motionEnds;
|
|
568
|
+
/* One row an axis (ADR-0159): how it moves and by what, changed or taken away where it is; more added under them. */
|
|
569
|
+
const count = joint ? figureMotionsOf(joint).length : 1;
|
|
570
|
+
const edit = (k) => {
|
|
571
|
+
if (!joint)
|
|
572
|
+
return;
|
|
573
|
+
this.motionAxis = k;
|
|
574
|
+
this.motion = motionFormOf(joint, k);
|
|
575
|
+
this.editingMotion = true;
|
|
576
|
+
};
|
|
577
|
+
const row = (k) => {
|
|
578
|
+
const it = k === 0 ? now : motionOf(asset, this.partId, k);
|
|
579
|
+
if (!it)
|
|
580
|
+
return nothing;
|
|
581
|
+
return html `<div pair motion-axis=${k}>
|
|
582
|
+
<span>
|
|
583
|
+
${count > 1 ? html `<b>${i18next.t('figure.label.motion-axis-n', { n: k + 1 })}</b> ` : nothing}${i18next.t('figure.label.motion-' + it.kind)} · ${it.vector ? jointAxisWord(it.vector) : String(it.axis).toUpperCase()}
|
|
584
|
+
${it.travel
|
|
585
|
+
? html `<small>${i18next.t('figure.label.motion-travel-is', { part: it.travel.part, axis: it.travel.axis.toUpperCase(), plus: it.travel.plus ?? 0 })}</small>`
|
|
586
|
+
: nothing}
|
|
587
|
+
${it.follows?.sum.length === 1
|
|
588
|
+
? html `<small>${i18next.t('figure.label.motion-follows', { joint: it.follows.sum[0].joint, multiplier: it.follows.sum[0].multiplier, offset: it.follows.offset })}</small>`
|
|
589
|
+
: it.follows
|
|
590
|
+
? html `<small>${i18next.t('figure.label.motion-follow')}: ${it.follows.sum.map(t => `${t.joint} × ${t.multiplier}`).join(' + ')} + ${it.follows.offset}</small>`
|
|
591
|
+
: it.control
|
|
592
|
+
? html `<small>${it.control.id} (${it.control.unit}) ${it.control.min} … ${it.control.max}</small>`
|
|
593
|
+
: nothing}
|
|
594
|
+
</span>
|
|
595
|
+
${count > 1
|
|
596
|
+
? html `<button act remove-axis ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: withoutAxis(joint, k) })}>
|
|
597
|
+
<md-icon>close</md-icon>${i18next.t('figure.button.remove-axis')}
|
|
598
|
+
</button>`
|
|
599
|
+
: html `<button act ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: fixedJointOf(joint) })}>
|
|
600
|
+
<md-icon>close</md-icon>${i18next.t('figure.button.remove-motion')}
|
|
601
|
+
</button>`}
|
|
602
|
+
<button act ?disabled=${this.locked || !joint} @click=${() => edit(k)}>
|
|
603
|
+
<md-icon>edit</md-icon>${i18next.t('figure.button.change-motion')}
|
|
604
|
+
</button>
|
|
605
|
+
</div>`;
|
|
606
|
+
};
|
|
565
607
|
return html `<p motion-summary>
|
|
566
608
|
${i18next.t('figure.text.motion-summary', {
|
|
567
609
|
part: this.partId,
|
|
@@ -573,40 +615,17 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
573
615
|
${ends
|
|
574
616
|
? html `<p hint motion-ends>${i18next.t('figure.text.motion-ends-shown', { min: String(ends.min), max: String(ends.max), unit: ends.unit })}</p>`
|
|
575
617
|
: nothing}
|
|
618
|
+
${Array.from({ length: count }, (_, k) => row(k))}
|
|
576
619
|
<div pair>
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
620
|
+
<button act add-axis ?disabled=${this.locked || !joint} @click=${() => edit(count)}>
|
|
621
|
+
<md-icon>add</md-icon>${i18next.t('figure.button.add-axis')}
|
|
622
|
+
</button>
|
|
623
|
+
${count > 1
|
|
624
|
+
? html `<button act ?disabled=${this.locked || !joint} @click=${() => joint && this.command({ kind: 'set-joint', joint: fixedJointOf(joint) })}>
|
|
625
|
+
<md-icon>close</md-icon>${i18next.t('figure.button.remove-motion')}
|
|
626
|
+
</button>`
|
|
581
627
|
: nothing}
|
|
582
|
-
|
|
583
|
-
? html `<small>${i18next.t('figure.label.motion-follows', { joint: now.follows.sum[0].joint, multiplier: now.follows.sum[0].multiplier, offset: now.follows.offset })}</small>`
|
|
584
|
-
: now.follows
|
|
585
|
-
? html `<small>${i18next.t('figure.label.motion-follow')}: ${now.follows.sum.map(t => `${t.joint} × ${t.multiplier}`).join(' + ')} + ${now.follows.offset}</small>`
|
|
586
|
-
: now.control
|
|
587
|
-
? html `<small>${now.control.id} (${now.control.unit}) ${now.control.min} … ${now.control.max}</small>`
|
|
588
|
-
: nothing}
|
|
589
|
-
</span>
|
|
590
|
-
<button
|
|
591
|
-
act
|
|
592
|
-
?disabled=${this.locked || !joint}
|
|
593
|
-
@click=${() => joint && this.command({ kind: 'set-joint', joint: fixedJointOf(joint) })}
|
|
594
|
-
>
|
|
595
|
-
<md-icon>close</md-icon>${i18next.t('figure.button.remove-motion')}
|
|
596
|
-
</button>
|
|
597
|
-
<button
|
|
598
|
-
act
|
|
599
|
-
?disabled=${this.locked || !joint}
|
|
600
|
-
@click=${() => {
|
|
601
|
-
if (!joint)
|
|
602
|
-
return;
|
|
603
|
-
this.motion = motionFormOf(joint);
|
|
604
|
-
this.editingMotion = true;
|
|
605
|
-
}}
|
|
606
|
-
>
|
|
607
|
-
<md-icon>edit</md-icon>${i18next.t('figure.button.change-motion')}
|
|
608
|
-
</button>
|
|
609
|
-
</div>`;
|
|
628
|
+
</div>`;
|
|
610
629
|
}
|
|
611
630
|
/* A joint needs a parent (URDF): a part fastened to nothing is fastened first. */
|
|
612
631
|
if (!joint)
|
|
@@ -617,10 +636,13 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
617
636
|
const m = this.motion;
|
|
618
637
|
const unit = m.kind === 'slide' ? 'mm' : 'deg';
|
|
619
638
|
/* A follower follows a joint that moves the same way; a choice the kind no longer allows is dropped. */
|
|
620
|
-
const
|
|
639
|
+
const k = this.motionAxis;
|
|
640
|
+
const leaders = leadersFor(asset, this.partId, m.kind, motionIdOf(joint, k));
|
|
641
|
+
const adding = k > 0 && k >= figureMotionsOf(joint).length;
|
|
621
642
|
const follow = leaders.some(j => j.id === m.follow) ? m.follow : '';
|
|
622
643
|
const refusal = motionFormRefusalOf(m, follow);
|
|
623
644
|
return html `
|
|
645
|
+
${k > 0 ? html `<p motion-axis-heading><b>${i18next.t('figure.label.motion-axis-n', { n: k + 1 })}</b></p>` : nothing}
|
|
624
646
|
<div pair>
|
|
625
647
|
<select @change=${(e) => this.setKind(e.target.value)}>
|
|
626
648
|
<option value="slide" ?selected=${m.kind === 'slide'}>${i18next.t('figure.label.motion-slide')}</option>
|
|
@@ -676,7 +698,7 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
676
698
|
: nothing}`
|
|
677
699
|
: nothing}
|
|
678
700
|
<span>${i18next.t('figure.label.control-id')}</span>
|
|
679
|
-
<input .value=${m.id} placeholder=${
|
|
701
|
+
<input .value=${m.id} placeholder=${controlIdFor(this.partId, m.kind, k)} @change=${(e) => (this.motion = { ...m, id: e.target.value.trim() })} />
|
|
680
702
|
${m.kind === 'continuous' || (m.kind === 'slide' && (m.travel || m.travelSum))
|
|
681
703
|
? nothing
|
|
682
704
|
: html `<span>${i18next.t('figure.label.control-range')} (${unit})</span>
|
|
@@ -690,14 +712,15 @@ let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
690
712
|
?disabled=${this.locked || !!refusal}
|
|
691
713
|
title=${refusal === 'range' ? i18next.t('figure.text.range-needs-room') : ''}
|
|
692
714
|
@click=${() => {
|
|
693
|
-
this.command({ kind: 'set-joint', joint: motionJoint(joint, { ...m, follow }, this.partId) });
|
|
715
|
+
this.command({ kind: 'set-joint', joint: motionJoint(joint, { ...m, follow }, this.partId, k) });
|
|
694
716
|
this.editingMotion = false;
|
|
717
|
+
this.motionAxis = 0;
|
|
695
718
|
}}
|
|
696
719
|
>
|
|
697
|
-
<md-icon>animation</md-icon>${i18next.t(this.editingMotion ? 'figure.button.apply-motion-change' : 'figure.button.add-motion')}
|
|
720
|
+
<md-icon>animation</md-icon>${i18next.t(adding ? 'figure.button.add-axis' : this.editingMotion ? 'figure.button.apply-motion-change' : 'figure.button.add-motion')}
|
|
698
721
|
</button>
|
|
699
722
|
${this.editingMotion
|
|
700
|
-
? html `<button act @click=${() => (this.editingMotion = false)}><md-icon>undo</md-icon>${i18next.t('figure.button.cancel-motion-change')}</button>`
|
|
723
|
+
? html `<button act @click=${() => ((this.editingMotion = false), (this.motionAxis = 0))}><md-icon>undo</md-icon>${i18next.t('figure.button.cancel-motion-change')}</button>`
|
|
701
724
|
: nothing}
|
|
702
725
|
`;
|
|
703
726
|
}
|
|
@@ -776,6 +799,10 @@ __decorate([
|
|
|
776
799
|
state(),
|
|
777
800
|
__metadata("design:type", Object)
|
|
778
801
|
], FigureLinks.prototype, "editingMotion", void 0);
|
|
802
|
+
__decorate([
|
|
803
|
+
state(),
|
|
804
|
+
__metadata("design:type", Object)
|
|
805
|
+
], FigureLinks.prototype, "motionAxis", void 0);
|
|
779
806
|
FigureLinks = __decorate([
|
|
780
807
|
customElement('figure-links')
|
|
781
808
|
], FigureLinks);
|