@things-factory/ops-master 10.1.206 → 10.1.208

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.
@@ -55,7 +55,7 @@ export default function bootstrap() {
55
55
  /*
56
56
  * 기준정보 변경 정책은 **설정에 안 올린다**(2026-09-24).
57
57
  *
58
- * 같은 표가 업무 상세에 섰다(worklist `registerActivityPanel`, 위에서 이 꾸러미가 건다). 두 자리에 두면 한
58
+ * 같은 표가 업무 상세에 섰다(worklist `registerActivityPanel`, 위에서 이 패키지가 건다). 두 자리에 두면 한
59
59
  * 사실을 두 화면이 각각 그리고, 한쪽만 고치는 날이 온다. 그 축을 부르는 업무 옆에 두는 쪽이 맞다 —
60
60
  * 「이 업무를 승인제로 둘까」가 그 자리에서 답할 물음이다.
61
61
  *
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAEtH,OAAO,iCAAiC,CAAA;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAA;AAE5E,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAErG,OAAO,EAAE,+BAA+B,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AAClH,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAA;AAEhI;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B;;;;OAIG;IACH,yBAAyB,EAAE,CAAA;IAC3B,2BAA2B,CAAC;QAC1B,iBAAiB,EAAE,8BAA8B;QACjD,gBAAgB,EAAE,mBAAmB;QACrC,kBAAkB,EAAE,+BAA+B;KACpD,CAAC,CAAA;IACF,qBAAqB,CAAC;QACpB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,qBAAqB;QAC/B,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,IAAI,CAAA,yCAAyC,YAAY,gCAAgC;KACxH,CAAC,CAAA;IAEF,qBAAqB,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAA;IACjE,mBAAmB,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAA;IAEpE;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAA;IAC5D,mBAAmB,CAAC,WAAW,EAAE,6BAA6B,CAAC,CAAA;IAE/D;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAEtD;;;;;;;;;OASG;AACL,CAAC","sourcesContent":["import { registerEditor as registerGristEditor, registerRenderer as registerGristRenderer } from '@operato/data-grist'\n\nimport './master-change-policy-panel.js'\n\nimport { html } from 'lit'\n\nimport { registerActivityPanel } from '@things-factory/worklist/dist-client'\n\nimport { provideMasterChangeApproval, provideMasterChangeStatus } from './master-change-providers.js'\n\nimport { OpsMasterGristEditorIsoDuration, OxGristRendererIsoDuration } from './pages/master/grist-iso-duration.js'\nimport { OpsMasterGristEditorReference, OxGristRendererList, OxGristRendererReference } from './pages/master/grist-reference.js'\n\n/**\n * 그리드 편집기 등록.\n *\n * `select` · `json5` · `datetime` 같은 것은 data-grist 가 기본으로 등록한다.\n *\n * ── 왜 `duration` 이 아니라 `iso-duration` 인가 ────────────────────────────\n * `@operato/grist-editor` 에 `duration` 이 있지만 그것은 **초 숫자**를 받는다. 우리 칸에는\n * `PT209S` 가 들어 있어서 붙여 보니 화면이 빈 칸이었다.\n *\n * 그래서 같은 이름으로 우리 것을 덮어 등록해 봤더니 **그것도 안 됐다.** `worklist` 패키지가 같은\n * 이름으로 초 숫자용을 등록하고 있었고, 나중에 부팅한 쪽이 이긴다. 둘 다 자기가 이겼는지 모른다.\n *\n * 이름을 뺏는 대신 뜻이 다른 이름을 쓴다. 초 숫자와 ISO 8601 은 실제로 다른 타입이고, 이름이 그것을\n * 말해야 한다. `worklist` 의 화면은 초를 저장하는 것이 맞고 우리가 건드릴 일이 아니다.\n *\n * **이 등록소는 앱 전체가 한 벌을 나눠 쓴다** — 이름이 겹치면 조용히 진다. 아키텍트에게 올려 두었다.\n */\nexport default function bootstrap() {\n /*\n * The approval flow for master changes is ops-master's (ADR-0086 decision 1, amended 2026-10-10): it\n * answers the editor's submit and status events for its own axes, and puts the policy table beside the\n * activity it governs.\n */\n provideMasterChangeStatus()\n provideMasterChangeApproval({\n testSpecification: 'submitTestSpecificationDraft',\n recipeDefinition: 'submitRecipeDraft',\n materialDefinition: 'submitMaterialDefinitionDraft'\n })\n registerActivityPanel({\n name: 'master-change-policy',\n labelKey: 'master-policy.title',\n render: ({ activityName }) => html`<master-change-policy-panel .activity=${activityName}></master-change-policy-panel>`\n })\n\n registerGristRenderer('iso-duration', OxGristRendererIsoDuration)\n registerGristEditor('iso-duration', OpsMasterGristEditorIsoDuration)\n\n /*\n * 다른 표의 이름 하나를 골라 오는 칸. `resource-object` 와 팝업은 같고 저장하는 것이 다르다 —\n * 저쪽은 객체, 이쪽은 이름. 이름이 그것을 말해야 해서 따로 등록한다.\n */\n registerGristRenderer('reference', OxGristRendererReference)\n registerGristEditor('reference', OpsMasterGristEditorReference)\n\n /*\n * 목록 칸. 기본 글자 렌더러는 배열을 **구분 없이 이어 붙인다** — 두 사람이 선 자리가\n * 「P-ECU-S-0001P-ECU-S-0002」로 보였다. 고칠 것은 그리기뿐이라 편집기는 그대로 둔다.\n */\n registerGristRenderer('ops-list', OxGristRendererList)\n\n /*\n * 기준정보 변경 정책은 **설정에 안 올린다**(2026-09-24).\n *\n * 같은 표가 업무 상세에 섰다(worklist `registerActivityPanel`, 위에서 이 꾸러미가 건다). 두 자리에 두면 한\n * 사실을 두 화면이 각각 그리고, 한쪽만 고치는 날이 온다. 그 축을 부르는 업무 옆에 두는 쪽이 맞다 —\n * 「이 업무를 승인제로 둘까」가 그 자리에서 답할 물음이다.\n *\n * 설정으로 되돌릴 일이 생기면 여기에 다시 ADD_SETTING 을 놓으면 된다 —\n * 그때 setting-base 의존도 다시 든다.\n */\n}\n"]}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAEtH,OAAO,iCAAiC,CAAA;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAA;AAE5E,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAErG,OAAO,EAAE,+BAA+B,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AAClH,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAA;AAEhI;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B;;;;OAIG;IACH,yBAAyB,EAAE,CAAA;IAC3B,2BAA2B,CAAC;QAC1B,iBAAiB,EAAE,8BAA8B;QACjD,gBAAgB,EAAE,mBAAmB;QACrC,kBAAkB,EAAE,+BAA+B;KACpD,CAAC,CAAA;IACF,qBAAqB,CAAC;QACpB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,qBAAqB;QAC/B,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,IAAI,CAAA,yCAAyC,YAAY,gCAAgC;KACxH,CAAC,CAAA;IAEF,qBAAqB,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAA;IACjE,mBAAmB,CAAC,cAAc,EAAE,+BAA+B,CAAC,CAAA;IAEpE;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAA;IAC5D,mBAAmB,CAAC,WAAW,EAAE,6BAA6B,CAAC,CAAA;IAE/D;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAEtD;;;;;;;;;OASG;AACL,CAAC","sourcesContent":["import { registerEditor as registerGristEditor, registerRenderer as registerGristRenderer } from '@operato/data-grist'\n\nimport './master-change-policy-panel.js'\n\nimport { html } from 'lit'\n\nimport { registerActivityPanel } from '@things-factory/worklist/dist-client'\n\nimport { provideMasterChangeApproval, provideMasterChangeStatus } from './master-change-providers.js'\n\nimport { OpsMasterGristEditorIsoDuration, OxGristRendererIsoDuration } from './pages/master/grist-iso-duration.js'\nimport { OpsMasterGristEditorReference, OxGristRendererList, OxGristRendererReference } from './pages/master/grist-reference.js'\n\n/**\n * 그리드 편집기 등록.\n *\n * `select` · `json5` · `datetime` 같은 것은 data-grist 가 기본으로 등록한다.\n *\n * ── 왜 `duration` 이 아니라 `iso-duration` 인가 ────────────────────────────\n * `@operato/grist-editor` 에 `duration` 이 있지만 그것은 **초 숫자**를 받는다. 우리 칸에는\n * `PT209S` 가 들어 있어서 붙여 보니 화면이 빈 칸이었다.\n *\n * 그래서 같은 이름으로 우리 것을 덮어 등록해 봤더니 **그것도 안 됐다.** `worklist` 패키지가 같은\n * 이름으로 초 숫자용을 등록하고 있었고, 나중에 부팅한 쪽이 이긴다. 둘 다 자기가 이겼는지 모른다.\n *\n * 이름을 뺏는 대신 뜻이 다른 이름을 쓴다. 초 숫자와 ISO 8601 은 실제로 다른 타입이고, 이름이 그것을\n * 말해야 한다. `worklist` 의 화면은 초를 저장하는 것이 맞고 우리가 건드릴 일이 아니다.\n *\n * **이 등록소는 앱 전체가 한 벌을 나눠 쓴다** — 이름이 겹치면 조용히 진다. 아키텍트에게 올려 두었다.\n */\nexport default function bootstrap() {\n /*\n * The approval flow for master changes is ops-master's (ADR-0086 decision 1, amended 2026-10-10): it\n * answers the editor's submit and status events for its own axes, and puts the policy table beside the\n * activity it governs.\n */\n provideMasterChangeStatus()\n provideMasterChangeApproval({\n testSpecification: 'submitTestSpecificationDraft',\n recipeDefinition: 'submitRecipeDraft',\n materialDefinition: 'submitMaterialDefinitionDraft'\n })\n registerActivityPanel({\n name: 'master-change-policy',\n labelKey: 'master-policy.title',\n render: ({ activityName }) => html`<master-change-policy-panel .activity=${activityName}></master-change-policy-panel>`\n })\n\n registerGristRenderer('iso-duration', OxGristRendererIsoDuration)\n registerGristEditor('iso-duration', OpsMasterGristEditorIsoDuration)\n\n /*\n * 다른 표의 이름 하나를 골라 오는 칸. `resource-object` 와 팝업은 같고 저장하는 것이 다르다 —\n * 저쪽은 객체, 이쪽은 이름. 이름이 그것을 말해야 해서 따로 등록한다.\n */\n registerGristRenderer('reference', OxGristRendererReference)\n registerGristEditor('reference', OpsMasterGristEditorReference)\n\n /*\n * 목록 칸. 기본 글자 렌더러는 배열을 **구분 없이 이어 붙인다** — 두 사람이 선 자리가\n * 「P-ECU-S-0001P-ECU-S-0002」로 보였다. 고칠 것은 그리기뿐이라 편집기는 그대로 둔다.\n */\n registerGristRenderer('ops-list', OxGristRendererList)\n\n /*\n * 기준정보 변경 정책은 **설정에 안 올린다**(2026-09-24).\n *\n * 같은 표가 업무 상세에 섰다(worklist `registerActivityPanel`, 위에서 이 패키지가 건다). 두 자리에 두면 한\n * 사실을 두 화면이 각각 그리고, 한쪽만 고치는 날이 온다. 그 축을 부르는 업무 옆에 두는 쪽이 맞다 —\n * 「이 업무를 승인제로 둘까」가 그 자리에서 답할 물음이다.\n *\n * 설정으로 되돌릴 일이 생기면 여기에 다시 ADD_SETTING 을 놓으면 된다 —\n * 그때 setting-base 의존도 다시 든다.\n */\n}\n"]}
@@ -15,7 +15,7 @@
15
15
  */
16
16
  /** 질의 이름 → 그 표를 보여 주는 화면의 태그. */
17
17
  export declare const REFERENCE_PAGE: Readonly<Record<string, string>>;
18
- /** 이 꾸러미 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */
18
+ /** 이 패키지 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */
19
19
  export declare const ELSEWHERE: ReadonlySet<string>;
20
20
  /**
21
21
  * 지금 주소에서 **도메인까지의 앞부분**을 뗀다.
@@ -30,7 +30,7 @@ export const REFERENCE_PAGE = {
30
30
  equipmentList: 'ops-master-equipment',
31
31
  physicalAssets: 'ops-master-physical-asset',
32
32
  /*
33
- * ── 이 하나만 다른 꾸러미의 화면이다 ────────────────────────────────────
33
+ * ── 이 하나만 다른 패키지의 화면이다 ────────────────────────────────────
34
34
  *
35
35
  * 근무조는 `@things-factory/work-shift` 가 갖는다. 자리가 「여기서 도는 근무조」를 고를 수 있게
36
36
  * 되면서 이 표에 들어왔다.
@@ -41,7 +41,7 @@ export const REFERENCE_PAGE = {
41
41
  */
42
42
  workShifts: 'work-shift'
43
43
  };
44
- /** 이 꾸러미 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */
44
+ /** 이 패키지 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */
45
45
  export const ELSEWHERE = new Set(['work-shift']);
46
46
  /**
47
47
  * 지금 주소에서 **도메인까지의 앞부분**을 뗀다.
@@ -1 +1 @@
1
- {"version":3,"file":"reference-targets.js","sourceRoot":"","sources":["../../../client/pages/master/reference-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,iCAAiC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAqC;IAC9D,oBAAoB,EAAE,iCAAiC;IACvD,cAAc,EAAE,wBAAwB;IACxC,mBAAmB,EAAE,gCAAgC;IACrD,eAAe,EAAE,2BAA2B;IAC5C,gBAAgB,EAAE,6BAA6B;IAC/C,iBAAiB,EAAE,8BAA8B;IACjD,oBAAoB,EAAE,iCAAiC;IACvD,gBAAgB,EAAE,4BAA4B;IAC9C,gBAAgB,EAAE,4BAA4B;IAC9C,oBAAoB,EAAE,iCAAiC;IACvD,kBAAkB,EAAE,+BAA+B;IACnD,OAAO,EAAE,mBAAmB;IAC5B,aAAa,EAAE,sBAAsB;IACrC,cAAc,EAAE,2BAA2B;IAC3C;;;;;;;;;OASG;IACH,UAAU,EAAE,YAAY;CACzB,CAAA;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,SAAS,GAAwB,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;AAErE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;IAE3C,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,SAA6B,EAC7B,KAAyB,EACzB,QAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;IAEnC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAA;AACvD,CAAC","sourcesContent":["/**\n * 참조가 가리키는 표는 **어느 화면인가.**\n *\n * ── 왜 필요한가 ────────────────────────────────────────────────────────────\n * 참조 칸이 「ECU-SUB-01」이라고 적어도 거기로 갈 길이 없었다. 그 자리가 무엇인지 보려면 자리\n * 화면을 따로 열고 이름으로 찾아야 했다. 마스터는 그래프인데 화면은 표 열넷으로 흩어져 있어서,\n * 한 축에서 다른 축으로 건너가는 일이 사람의 기억에 맡겨져 있었다.\n *\n * ── 왜 한 곳에 모으나 ──────────────────────────────────────────────────────\n * 화면마다 「내 참조는 저 화면으로 간다」를 적으면 일곱 군데가 되고, 화면이 늘 때마다 여덟 · 아홉이\n * 된다. 한 군데를 빠뜨리면 그 칸만 안 걸리는데, 안 걸리는 것은 오류가 아니라 **아무 일도 안 일어나는\n * 것**이라 눈에 안 띈다.\n *\n * 여기 한 표로 두고, 화면이 참조하는 질의가 이 표에 다 있는지 테스트가 확인한다.\n */\n\n/** 질의 이름 → 그 표를 보여 주는 화면의 태그. */\nexport const REFERENCE_PAGE: Readonly<Record<string, string>> = {\n operationalLocations: 'ops-master-operational-location',\n stopReasonList: 'ops-master-stop-reason',\n materialDefinitions: 'ops-master-material-definition',\n materialClasses: 'ops-master-material-class',\n routeDefinitions: 'ops-master-route-definition',\n recipeDefinitions: 'ops-master-recipe-definition',\n operationDefinitions: 'ops-master-operation-definition',\n personnelClasses: 'ops-master-personnel-class',\n equipmentClasses: 'ops-master-equipment-class',\n physicalAssetClasses: 'ops-master-physical-asset-class',\n testSpecifications: 'ops-master-test-specification',\n persons: 'ops-master-person',\n equipmentList: 'ops-master-equipment',\n physicalAssets: 'ops-master-physical-asset',\n /*\n * ── 이 하나만 다른 꾸러미의 화면이다 ────────────────────────────────────\n *\n * 근무조는 `@things-factory/work-shift` 가 갖는다. 자리가 「여기서 도는 근무조」를 고를 수 있게\n * 되면서 이 표에 들어왔다.\n *\n * 접두사 규칙(`ops-master-`)에서 벗어나는 유일한 값이다. `domainBaseOf` 는 주소에서 그 접두사\n * 앞까지를 자르므로 여기서 나온 링크도 같은 도메인 밑으로 간다 — 자르는 기준은 **지금 열려 있는\n * 화면**의 태그이지 이 값이 아니다.\n */\n workShifts: 'work-shift'\n}\n\n/** 이 꾸러미 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */\nexport const ELSEWHERE: ReadonlySet<string> = new Set(['work-shift'])\n\n/**\n * 지금 주소에서 **도메인까지의 앞부분**을 뗀다.\n *\n * 주소는 `/domain/<서브도메인>/<화면>` 이고, 파고든 화면이면 `/<이름>` 이 더 붙는다. 상대 경로로\n * 옮기면 파고든 상태에서 한 칸 어긋난다 — `/domain/x/자리화면/GUNSAN` 에서 상대로 가면\n * `/domain/x/자리화면/공정화면` 이 된다.\n *\n * 그래서 **`ops-master-` 로 시작하는 조각**을 찾아 그 앞까지를 자른다. 이 패키지의 화면 태그는 전부\n * 그 접두사를 갖는다(`things-factory.config.js` 의 라우트 열넷).\n *\n * 처음에는 그리드 칸에서 페이지 요소를 거슬러 올라가 태그를 얻으려 했는데 안 됐다 — 칸이 셰도우\n * 안에 있어 `closest` 가 경계를 못 넘고, 거슬러 올라가면 페이지가 아니라 `ox-grid-body` 가 나온다.\n * [확인함] 2026-09-04\n *\n * 못 찾으면 `undefined` 를 낸다 — 짐작으로 자르면 엉뚱한 곳으로 보낸다.\n */\nexport function domainBaseOf(pathname: string): string | undefined {\n const at = pathname.search(/\\/ops-master-/)\n\n return at < 0 ? undefined : pathname.slice(0, at)\n}\n\n/**\n * 그 이름을 보러 갈 주소. 갈 곳을 모르면 `undefined` — 부르는 쪽이 **문을 안 그린다.**\n *\n * 막다른 링크는 없는 링크보다 나쁘다. 선택했는데 아무 일도 안 나면 사람은 그것을 고장으로 읽는다.\n */\nexport function referenceHref(\n queryName: string | undefined,\n value: string | undefined,\n pathname: string\n): string | undefined {\n if (!queryName || !value) {\n return undefined\n }\n\n const page = REFERENCE_PAGE[queryName]\n const base = domainBaseOf(pathname)\n\n if (!page || base === undefined) {\n return undefined\n }\n\n return `${base}/${page}/${encodeURIComponent(value)}`\n}\n"]}
1
+ {"version":3,"file":"reference-targets.js","sourceRoot":"","sources":["../../../client/pages/master/reference-targets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,iCAAiC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAqC;IAC9D,oBAAoB,EAAE,iCAAiC;IACvD,cAAc,EAAE,wBAAwB;IACxC,mBAAmB,EAAE,gCAAgC;IACrD,eAAe,EAAE,2BAA2B;IAC5C,gBAAgB,EAAE,6BAA6B;IAC/C,iBAAiB,EAAE,8BAA8B;IACjD,oBAAoB,EAAE,iCAAiC;IACvD,gBAAgB,EAAE,4BAA4B;IAC9C,gBAAgB,EAAE,4BAA4B;IAC9C,oBAAoB,EAAE,iCAAiC;IACvD,kBAAkB,EAAE,+BAA+B;IACnD,OAAO,EAAE,mBAAmB;IAC5B,aAAa,EAAE,sBAAsB;IACrC,cAAc,EAAE,2BAA2B;IAC3C;;;;;;;;;OASG;IACH,UAAU,EAAE,YAAY;CACzB,CAAA;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,SAAS,GAAwB,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;AAErE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;IAE3C,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,SAA6B,EAC7B,KAAyB,EACzB,QAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;IAEnC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAA;AACvD,CAAC","sourcesContent":["/**\n * 참조가 가리키는 표는 **어느 화면인가.**\n *\n * ── 왜 필요한가 ────────────────────────────────────────────────────────────\n * 참조 칸이 「ECU-SUB-01」이라고 적어도 거기로 갈 길이 없었다. 그 자리가 무엇인지 보려면 자리\n * 화면을 따로 열고 이름으로 찾아야 했다. 마스터는 그래프인데 화면은 표 열넷으로 흩어져 있어서,\n * 한 축에서 다른 축으로 건너가는 일이 사람의 기억에 맡겨져 있었다.\n *\n * ── 왜 한 곳에 모으나 ──────────────────────────────────────────────────────\n * 화면마다 「내 참조는 저 화면으로 간다」를 적으면 일곱 군데가 되고, 화면이 늘 때마다 여덟 · 아홉이\n * 된다. 한 군데를 빠뜨리면 그 칸만 안 걸리는데, 안 걸리는 것은 오류가 아니라 **아무 일도 안 일어나는\n * 것**이라 눈에 안 띈다.\n *\n * 여기 한 표로 두고, 화면이 참조하는 질의가 이 표에 다 있는지 테스트가 확인한다.\n */\n\n/** 질의 이름 → 그 표를 보여 주는 화면의 태그. */\nexport const REFERENCE_PAGE: Readonly<Record<string, string>> = {\n operationalLocations: 'ops-master-operational-location',\n stopReasonList: 'ops-master-stop-reason',\n materialDefinitions: 'ops-master-material-definition',\n materialClasses: 'ops-master-material-class',\n routeDefinitions: 'ops-master-route-definition',\n recipeDefinitions: 'ops-master-recipe-definition',\n operationDefinitions: 'ops-master-operation-definition',\n personnelClasses: 'ops-master-personnel-class',\n equipmentClasses: 'ops-master-equipment-class',\n physicalAssetClasses: 'ops-master-physical-asset-class',\n testSpecifications: 'ops-master-test-specification',\n persons: 'ops-master-person',\n equipmentList: 'ops-master-equipment',\n physicalAssets: 'ops-master-physical-asset',\n /*\n * ── 이 하나만 다른 패키지의 화면이다 ────────────────────────────────────\n *\n * 근무조는 `@things-factory/work-shift` 가 갖는다. 자리가 「여기서 도는 근무조」를 고를 수 있게\n * 되면서 이 표에 들어왔다.\n *\n * 접두사 규칙(`ops-master-`)에서 벗어나는 유일한 값이다. `domainBaseOf` 는 주소에서 그 접두사\n * 앞까지를 자르므로 여기서 나온 링크도 같은 도메인 밑으로 간다 — 자르는 기준은 **지금 열려 있는\n * 화면**의 태그이지 이 값이 아니다.\n */\n workShifts: 'work-shift'\n}\n\n/** 이 패키지 밖에 사는 화면 — 파일이 여기 없으니 태그 검사가 따로 판단한다. */\nexport const ELSEWHERE: ReadonlySet<string> = new Set(['work-shift'])\n\n/**\n * 지금 주소에서 **도메인까지의 앞부분**을 뗀다.\n *\n * 주소는 `/domain/<서브도메인>/<화면>` 이고, 파고든 화면이면 `/<이름>` 이 더 붙는다. 상대 경로로\n * 옮기면 파고든 상태에서 한 칸 어긋난다 — `/domain/x/자리화면/GUNSAN` 에서 상대로 가면\n * `/domain/x/자리화면/공정화면` 이 된다.\n *\n * 그래서 **`ops-master-` 로 시작하는 조각**을 찾아 그 앞까지를 자른다. 이 패키지의 화면 태그는 전부\n * 그 접두사를 갖는다(`things-factory.config.js` 의 라우트 열넷).\n *\n * 처음에는 그리드 칸에서 페이지 요소를 거슬러 올라가 태그를 얻으려 했는데 안 됐다 — 칸이 셰도우\n * 안에 있어 `closest` 가 경계를 못 넘고, 거슬러 올라가면 페이지가 아니라 `ox-grid-body` 가 나온다.\n * [확인함] 2026-09-04\n *\n * 못 찾으면 `undefined` 를 낸다 — 짐작으로 자르면 엉뚱한 곳으로 보낸다.\n */\nexport function domainBaseOf(pathname: string): string | undefined {\n const at = pathname.search(/\\/ops-master-/)\n\n return at < 0 ? undefined : pathname.slice(0, at)\n}\n\n/**\n * 그 이름을 보러 갈 주소. 갈 곳을 모르면 `undefined` — 부르는 쪽이 **문을 안 그린다.**\n *\n * 막다른 링크는 없는 링크보다 나쁘다. 선택했는데 아무 일도 안 나면 사람은 그것을 고장으로 읽는다.\n */\nexport function referenceHref(\n queryName: string | undefined,\n value: string | undefined,\n pathname: string\n): string | undefined {\n if (!queryName || !value) {\n return undefined\n }\n\n const page = REFERENCE_PAGE[queryName]\n const base = domainBaseOf(pathname)\n\n if (!page || base === undefined) {\n return undefined\n }\n\n return `${base}/${page}/${encodeURIComponent(value)}`\n}\n"]}