@things-factory/worklist 10.1.184 → 10.1.186

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.
Files changed (46) hide show
  1. package/dist-client/my-work-menus.d.ts +0 -5
  2. package/dist-client/my-work-menus.js +1 -2
  3. package/dist-client/my-work-menus.js.map +1 -1
  4. package/dist-client/pages/activity-catalog/activity-catalog-page.d.ts +18 -74
  5. package/dist-client/pages/activity-catalog/activity-catalog-page.js +292 -527
  6. package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
  7. package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
  8. package/dist-client/pages/work-door/door-links.d.ts +1 -9
  9. package/dist-client/pages/work-door/door-links.js +1 -11
  10. package/dist-client/pages/work-door/door-links.js.map +1 -1
  11. package/dist-client/pages/work-door/door-sentence.d.ts +26 -14
  12. package/dist-client/pages/work-door/door-sentence.js +58 -60
  13. package/dist-client/pages/work-door/door-sentence.js.map +1 -1
  14. package/dist-client/route.d.ts +1 -1
  15. package/dist-client/route.js +0 -3
  16. package/dist-client/route.js.map +1 -1
  17. package/dist-client/tsconfig.tsbuildinfo +1 -1
  18. package/dist-server/service/activity/activity-query.js +2 -31
  19. package/dist-server/service/activity/activity-query.js.map +1 -1
  20. package/dist-server/service/activity/approval-line-seats.d.ts +12 -0
  21. package/dist-server/service/activity/approval-line-seats.js +68 -0
  22. package/dist-server/service/activity/approval-line-seats.js.map +1 -0
  23. package/dist-server/service/activity/index.d.ts +1 -1
  24. package/dist-server/service/activity-instance/activity-instance-query.js +2 -54
  25. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  26. package/dist-server/service/activity-instance/index.d.ts +1 -1
  27. package/dist-server/service/index.d.ts +3 -3
  28. package/dist-server/service/work-door/work-door-resolver.js +7 -2
  29. package/dist-server/service/work-door/work-door-resolver.js.map +1 -1
  30. package/dist-server/service/work-door/work-door-service.d.ts +8 -1
  31. package/dist-server/service/work-door/work-door-service.js +11 -2
  32. package/dist-server/service/work-door/work-door-service.js.map +1 -1
  33. package/dist-server/service/work-door/work-door-type.d.ts +2 -0
  34. package/dist-server/service/work-door/work-door-type.js +8 -0
  35. package/dist-server/service/work-door/work-door-type.js.map +1 -1
  36. package/dist-server/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +3 -3
  38. package/tests/work-door-door-words.test.ts +1 -1
  39. package/things-factory.config.js +1 -6
  40. package/translations/en.json +11 -45
  41. package/translations/es.json +11 -45
  42. package/translations/ja.json +11 -45
  43. package/translations/ko.json +11 -45
  44. package/translations/ms.json +11 -45
  45. package/translations/zh.json +11 -45
  46. package/tests/work-door-sentence.test.ts +0 -199
@@ -1 +1 @@
1
- {"version":3,"file":"activity-catalog-page.js","sourceRoot":"","sources":["../../../client/pages/activity-catalog/activity-catalog-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/list-state/ox-page-state.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { guideLines } from './activity-guide.js'\nimport { canonicalStage, isRegistered, STAGE_ORDER, stageRank } from './activity-stage.js'\nimport { DocumentPageStyles, ScrollbarStyles } from '@operato/styles'\n\n/**\n * 업무 카탈로그 — **업무함에 올라오는 일이 무슨 일인지 읽는 자리.**\n *\n * ── 개발 현황 블록은 제품이 나가면 걷는다 (2026-09-23, 사용자 판단) ────────\n * `renderBuild` 가 그리는 것 — 모델 in/out 개수 · 판단 키 수 · 덮는 시험 · 마지막 시험 실행 —\n * 은 이 제품을 **만드는 쪽**이 읽는 값이다. 선언 자체가 그렇게 적고 있다: readiness 는 「여기까지\n * 되어 있다고 우리가 말하는 것」이고 `lastRun` 은 손으로 적는 값이라 낡을 수 있어 잰 날짜를 함께\n * 보인다. 쓰는 사람이 읽을 글이 아니다.\n *\n * **접지 않고 보이게 둔다.** 접으면 낡은 수를 아무도 안 보고, 그러면 적어 둔 값이 거짓이 된다.\n * 대신 걷을 것이라고 여기 적어 둔다 — 적어 두지 않으면 안 지워진다.\n *\n * 걷을 범위는 셋이다:\n *\n * 1. `renderBuild` 와 그것을 부르는 줄\n * 2. 이 파일의 질의에서 `readiness { stage gaps tests notes lastRun { … } }`\n * 3. 그 값에만 쓰이는 스타일(`.build`)\n *\n * `readiness.stage` 는 **남긴다** — 카드 머리의 「사용 가능 · 일부 동작」 띠와 위의 개수 줄이 그것을\n * 읽는다. 그것은 쓰는 사람에게 「이 업무를 지금 믿고 써도 되나」를 말하는 값이라 성격이 다르다.\n *\n * ── 첫 판을 다시 만든 이유 (2026-09-08) ───────────────────────────────────\n * 처음 만든 화면은 사용자가 읽을 것이 없었다. 네 줄 중 세 줄이 「…선언되지 않았습니다」였고, 업무\n * 설명은 영어로 나왔고, 다크 테마에서는 글자가 뭉개졌다. 「덮는 시험」처럼 아무도 쓰지 않는 말을\n * 지어내기까지 했다. 개발자 덤프를 사용자 화면이라고 부른 셈이다.\n *\n * 그래서 층을 진짜로 가른다.\n *\n * - **사용자가 읽는 것**: 이 업무가 무엇이고, 여기서 쓰이고 있나. 그것만 크게.\n * - **개발 정보**: 어디까지 됐나 · 시험. **값이 있을 때만** 접어서 아래에 둔다. 없는 것을 줄줄이\n * 적지 않는다 — 빈 줄을 나열하는 것은 정직한 게 아니라 아무 말도 안 하는 것이다.\n *\n * 여전히 판단하지 않고 선언을 그린다. 어디까지 됐는지는 화면이 실행 중에 알 수 없고, 그 업무를\n * 등록한 모듈이 자기 코드 옆에 적는다(ActivityReadiness).\n */\nconst CatalogFetch = gql`\n query {\n responses: installableActivities {\n items {\n name\n label\n labelTKey\n readinessNotesTKey\n readinessGapTKeys\n description\n guide\n guideTKeys\n category\n activityType\n provider\n release\n approvalSteps\n uiType\n viewType\n viewSource\n model {\n inout\n hidden\n }\n activity {\n id\n decisionKeys {\n role\n }\n }\n readiness {\n stage\n gaps\n tests\n notes\n lastRun {\n passed\n total\n at\n command\n }\n }\n }\n total\n }\n }\n`\n\n/**\n * 카드에 보이는 이름. 정렬도 이 글자로 한다 — 보이는 글자와 정렬 기준이 다르면 목록이 뒤섞여 보인다.\n *\n * 번역 키는 서버가 `name` 에서 계산해 보낸다(labelTKey). 화면은 키 규칙을 모른다. label 이 없으면\n * name 이다 — name 은 콜백을 찾는 키라 번역하지 않는다.\n */\nfunction shownName(one: any): string {\n if (!one?.label) return String(one?.name ?? '')\n return one.labelTKey ? String(i18next.t(one.labelTKey, { defaultValue: one.label })) : String(one.label)\n}\n\n/*\n * 단계를 읽고 차례를 매기는 판단은 `activity-stage.ts` 한 벌이다 — 업무 상세도 같은 답을 내야 해서\n * 여기 사본을 두지 않는다. 그 파일이 왜 그렇게 되돌리고 왜 그 차례인지 적고 있다.\n */\n\n@customElement('activity-catalog-page')\nexport class ActivityCatalogPage extends localize(i18next)(PageView) {\n static styles = [\n /* The frame owns the page shell and the reading column (ADR-0060 decision 8). */\n DocumentPageStyles,\n ScrollbarStyles,\n css`\n /*\n * 색은 전부 테마 토큰으로 쓴다. 첫 판은 흰 카드와 연회색 글자를 값으로 박아서 다크 테마에서\n * 글자가 배경에 묻혔다.\n */\n :host {\n color: var(--md-sys-color-on-background);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* 단계별 수. 설명이 아니라 자료라서 둔다 — 개발 기간에 이 수가 남은 일을 말한다. */\n [counts] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n\n margin: 0 0 12px 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n [counts] b {\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n [failed] {\n display: flex;\n align-items: center;\n gap: 6px;\n\n padding: 8px 10px;\n border-radius: 6px;\n\n background-color: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n }\n\n ul {\n display: grid;\n gap: 10px;\n\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /*\n * 카드는 **바탕보다 밝다** — 페이지에서 떠 있어야 스물여섯 장이 줄로 읽힌다.\n *\n * 처음엔 surface 를 썼는데, 이 테마에서 그 값이 background 와 **같다**(실측: 라이트 둘 다\n * rgb(238 241 243), 다크 둘 다 rgb(13 18 22)). 그래서 카드가 1px 테두리로만 구분됐다.\n *\n * surface-container-low 가 두 테마에서 **같은 방향**으로 갈린다 — 라이트 246 248 249,\n * 다크 20 27 33, 둘 다 바탕보다 밝다. surface-container-high 는 라이트에서 오히려 어두워져\n * 카드가 눌린 것처럼 읽힌다. 뜨는 것과 눌리는 것은 다른 말이라 방향이 뒤집히면 안 된다.\n */\n li {\n padding: 12px 14px;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n border-radius: 6px;\n\n background-color: var(--md-sys-color-surface-container-low, #f6f8f9);\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n .head {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 8px;\n }\n\n /*\n * 이름이 상세로 가는 문이다. 링크처럼 보이게 두되 색은 바꾸지 않는다 — 카드에서 가장 크게\n * 읽혀야 하는 글자라, 파랗게 만들면 이름보다 「링크」가 먼저 읽힌다. 마우스가 오면 말한다.\n */\n .name {\n font-size: var(--ui-t-title, 15px);\n font-weight: 600;\n color: inherit;\n text-decoration: none;\n cursor: pointer;\n }\n\n .name:hover,\n .name:focus-visible {\n text-decoration: underline;\n }\n\n /* 여기서 쓰이나 — 사용자에게 이 카드에서 가장 실질적인 사실이다. */\n .use {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .use[idle] {\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /* 이 업무가 무엇인가. 카드에서 가장 먼저 읽히는 줄이다. */\n .guide {\n margin: 8px 0 0 0;\n line-height: 1.55;\n }\n\n .guide p {\n margin: 0 0 4px 0;\n }\n\n .unwritten {\n margin: 8px 0 0 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 개발 정보. 값이 있을 때만 그린다. 사용자에게는 접힌 한 줄로만 보이고, 열면 우리가 볼 것이\n * 나온다.\n */\n /*\n * 단계 표. **철자를 하나만 쓴다.**\n *\n * 앞 판은 단계마다 boolean 속성을 뒀다. 그러면 하이픈 없는 두 번째 철자가 생기고\n * (notworklist) i18n 키(label.readiness-not-worklist)와 어긋난다. 값 하나를 data-stage 에\n * 실으면 선택자 · 키 꼬리 · 서버 enum 값이 **같은 글자**가 된다.\n *\n * 색과 말로 함께 말한다 — 색만 쓰면 색을 못 가리는 사람에게 아무 말도 하지 않는다.\n */\n .stage {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n .stage[data-stage='working'] {\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .stage[data-stage='partial'],\n .stage[data-stage='declared'] {\n background-color: var(--md-sys-color-tertiary-container, #ffd8e4);\n color: var(--md-sys-color-on-tertiary-container, #31111d);\n }\n\n /* 여기 두지 않기로 한 것. 테두리만 두어 만들 것들과 섞이지 않게 한다. */\n .stage[data-stage='not-worklist'] {\n background-color: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n details {\n margin-top: 10px;\n padding-top: 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n summary {\n cursor: pointer;\n border-radius: 4px;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 키보드로 여기 왔을 때 어디에 있는지 보여야 한다.\n *\n * summary 는 눌리는 것이라 tab 이 멈추는 자리다. 내가 이 절을 만들면서 표시를 안 줘서\n * plant 의 접근성 래칫 시험이 「포커스가 안 보이는 자리 7 → 8」로 잡아냈다. 화면을 하나\n * 더할 때마다 한 칸씩 늘어나는 것을 막는 시험이고, 허용 수를 올려 통과시킬 자리가 아니다.\n */\n summary:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #6750a4);\n outline-offset: 2px;\n }\n\n dl {\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: 4px 12px;\n\n margin: 8px 0 0 0;\n }\n\n dt {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n dd {\n margin: 0;\n }\n\n code {\n font-family: var(--ui-font-mono, monospace);\n font-size: 12px;\n word-break: break-all;\n }\n\n div[empty] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n div[empty] .title {\n font-size: var(--ui-t-title, 15px);\n }\n\n div[empty] .why {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n @media (max-width: 480px) {\n dl {\n grid-template-columns: 1fr;\n gap: 0;\n }\n\n dt {\n margin-top: 6px;\n }\n }\n `\n ]\n\n @state() items: any[] = []\n @state() loaded = false\n @state() failed = false\n /** Why the catalog could not be read - ox-page-state says it, with retry (ADR-0060 decision 8). */\n @state() loadError: unknown = null\n\n get context() {\n return {\n /*\n * 이 화면이 어떤 틀인가 — 동작 줄이 이것을 읽고 자기 오른쪽 끝을 내용에 맞춘다\n * (ADR-0060 결정 9 보탬). 안 적으면 창 폭이고, 그것은 작업면의 모양이다.\n */\n frame: 'document',\ntitle: i18next.t('title.activity catalog'),\n help: 'worklist/activity-catalog-page'\n }\n }\n\n render() {\n /* Loading showed a blank page; a failure had its own box. Both are the shared page state now. */\n return html`<div class=\"page\">\n <ox-page-state .loading=${!this.loaded} .error=${this.loadError} @retry=${() => this.retry()}\n >${this.loaded && !this.loadError ? this.renderCatalog() : ''}</ox-page-state\n >\n </div>`\n }\n\n private retry() {\n this.failed = false\n this.loadError = null\n this.loaded = false\n this.fetch()\n }\n\n private renderCatalog() {\n if (!this.items.length) {\n return html`<div empty>\n <span class=\"title\">${i18next.t('text.no-installable-activity')}</span>\n <span class=\"why\">${i18next.t('text.no-installable-activity-why')}</span>\n </div>`\n }\n\n return html`\n <div counts>\n ${STAGE_ORDER.map(stage => {\n const n = this.items.filter(one => canonicalStage(one.readiness?.stage) == stage).length\n return n ? html`<span>${i18next.t('label.readiness-' + stage)} <b>${n}</b></span>` : ''\n })}\n </div>\n\n <ul>\n ${this.items.map(one => this.renderOne(one))}\n </ul>\n `\n }\n\n private renderOne(one: any) {\n const stage = canonicalStage(one.readiness?.stage)\n\n /*\n * 아직 만들지 않은 것은 **설치될 수가 없다.** 그런 카드에 「아직 사용 안 함」을 붙이면 「예정」과\n * 같은 말을 두 번 하는 것이고, 읽는 사람은 둘이 다른 뜻인 줄 알고 두 번 읽는다.\n */\n const registered = isRegistered(stage)\n const inUse = !!one.activity?.id\n\n return html`<li>\n <div class=\"head\">\n <!--\n 이름은 label 이 있으면 label 이다. name 은 콜백을 찾는 키라서 사람이 읽는 말이 아닐 수\n 있다 — 한국어 스물셋 사이에 「MES Disposition Approval」 하나가 그렇게 떴다.\n -->\n <!--\n 이름이 상세로 가는 문이다. 전에는 이 화면에 나가는 자리가 하나도 없었고(navigate 0 ·\n <a href> 0), 카드가 「결재선 없음」이라고 적어 놓고 어디서 정하는지는 말하지 않았다.\n [확인함 2026-09-23] 결재선 하나를 세워 확인하는 데 화면 셋, 역할에 사람이 없으면 다섯.\n\n 카드 전체가 아니라 **이름만** 문으로 둔다 — 카드 안에 펼치는 절이 있어서, 카드를 누르면\n 펼치려던 사람이 화면을 떠나게 된다.\n -->\n <a class=\"name\" @click=${() => navigate(`activity-detail?name=${encodeURIComponent(one.name)}`)}\n >${shownName(one)}</a\n >\n\n <!--\n 단계를 카드 머리에 둔다.\n 한 판에서 이것을 개발 정보 안으로 옮겼다가 되돌렸다. 업무가 마흔을 넘고 그중 대부분이 아직\n 안 만든 것이면, 접힌 절 안에 든 단계는 하나씩 펼쳐야 아는 값이 된다. 그러면 목록이 다\n 같아 보인다.\n -->\n ${stage ? html`<span class=\"stage\" data-stage=${stage}>${i18next.t('label.readiness-' + stage)}</span>` : ''}\n ${\n registered\n ? html`<span class=\"use\" ?idle=${!inUse}\n >${inUse ? i18next.t('text.activity-in-use-here') : i18next.t('text.activity-not-in-use-here')}</span\n >`\n : ''\n }\n </div>\n\n ${this.renderGuide(one)} ${registered ? this.renderApprovers(one) : ''} ${this.renderBuild(one)}\n </li>`\n }\n\n /**\n * 이 업무가 무엇인가.\n *\n * `guide` 가 그 자리다 — 받는 사람의 말로 쓴 문장이다. 번역은 서버가 줄마다 계산해 보낸 `guideTKeys` 로\n * 찾고, 번역이 없으면 문장이 그대로 나간다. `description` 은\n * 우리끼리 쓰는 영어 한 줄이라 여기에 그대로 내지 않는다. 한국어 화면에서 영어 한 줄은 설명이\n * 아니다.\n *\n * 없으면 **한 줄로** 없다고 말한다. 없는 것을 여러 줄로 늘리지 않는다.\n */\n /**\n * Reads declared sentences in the reader's language, falling back to the sentence as declared\n * when there is no key or no translation for it. Lines and keys pair by position, as guide does.\n */\n private readSentences(lines: string[] | undefined, keys: string[] | undefined): string[] {\n return (lines || []).map((line, n) => (keys?.[n] ? String(i18next.t(keys[n], { defaultValue: line })) : line))\n }\n\n private renderGuide(one: any) {\n /* 줄을 고르는 판단은 상세 화면과 한 벌로 둔다 — 두 벌이면 같은 업무가 두 화면에서 달라진다. */\n const lines = guideLines(one, (key, options) => i18next.t(key, options))\n\n if (!lines.length) {\n return html`<p class=\"unwritten\">${i18next.t('text.activity-guide-unwritten')}</p>`\n }\n\n return html`<div class=\"guide\">${lines.map(line => html`<p>${line}</p>`)}</div>`\n }\n\n /**\n * 이 공장이 이 단계를 쓰나 — **결재선에 결재자가 있나.**\n *\n * 결재선은 양식이 아니라 그 현장이 정하는 것이라, 같은 업무가 어느 공장에서는 결재를 받고 어느\n * 공장에서는 그냥 지나간다. 그 사실이 지금까지 기동 로그 한 줄에만 있었다.\n *\n * **사람 수가 아니라 단계 수다** — 역할로 걸린 한 단계는 여러 사람이 본다. 그리고 비어 있다는 것이\n * 무슨 일을 뜻하는지는 업무마다 달라서(상신이 막히거나, 확인 없이 지나가거나) 여기서 결과를 말하지\n * 않는다. 그건 그 업무의 설명이 할 말이다.\n *\n * 「아직 사용 안 함」인 카드에는 그리지 않는다 — 세워지지 않은 양식에 결재선이 있을 수 없다.\n */\n private renderApprovers(one: any) {\n if (!one.activity?.id) {\n return ''\n }\n\n const steps = one.approvalSteps\n\n return html`<dl>\n <dt>${i18next.t('field.approval-line')}</dt>\n <dd>\n ${\n typeof steps != 'number'\n ? html`<span class=\"unwritten\">${i18next.t('text.approval-line-unknown')}</span>`\n : steps > 0\n ? i18next.t('text.approval-line-steps', { n: steps })\n : html`<span class=\"unwritten\">${i18next.t('text.approval-line-empty')}</span>`\n }\n </dd>\n </dl>`\n }\n\n /**\n * 개발 정보 — **값이 있을 때만.**\n *\n * 첫 판은 값이 없어도 「…선언되지 않았습니다」를 네 줄 그렸다. 사용자에게는 뜻 없는 벽이고 우리에게도\n * 아무 정보가 아니다. 아무것도 없으면 이 절 자체를 그리지 않는다 — 그 업무가 카탈로그에 「개발 정보\n * 없음」으로 남는 것은 화면 위쪽의 목적을 방해하지 않는다.\n */\n private renderBuild(one: any) {\n const readiness = one.readiness || {}\n const stage = canonicalStage(readiness.stage)\n const run = readiness.lastRun\n const hasRun = run && typeof run.total == 'number'\n\n const built = this.renderBuilt(one)\n\n if (!stage && !built && !readiness.tests?.length && !hasRun && !readiness.notes && !readiness.gaps?.length) {\n return ''\n }\n\n return html`<details>\n <summary>\n ${i18next.t('label.activity-build-info')}${stage ? ` · ${i18next.t('label.readiness-' + stage)}` : ''}\n </summary>\n <dl>\n ${\n built\n ? html`<dt>${i18next.t('field.what-is-built')}</dt>\n <dd>${built}</dd>`\n : ''\n }\n ${\n readiness.gaps?.length\n ? html`<dt>${i18next.t('field.readiness-gaps')}</dt>\n <dd>${this.readSentences(readiness.gaps, one.readinessGapTKeys).join(' · ')}</dd>`\n : ''\n }\n ${\n readiness.tests?.length\n ? html`<dt>${i18next.t('field.covering-tests')}</dt>\n <dd>${readiness.tests.map((test: string) => html`<div><code>${test}</code></div>`)}</dd>`\n : ''\n }\n ${\n hasRun\n ? html`<dt>${i18next.t('field.last-test-run')}</dt>\n <dd>${this.renderRun(run)}</dd>`\n : ''\n }\n ${\n readiness.notes\n ? html`<dt>${i18next.t('field.readiness-notes')}</dt>\n <dd>\n ${\n one.readinessNotesTKey\n ? i18next.t(one.readinessNotesTKey, { defaultValue: readiness.notes })\n : readiness.notes\n }\n </dd>`\n : ''\n }\n </dl>\n </details>`\n }\n\n /**\n * 무엇이 실제로 서 있나 — **선언과 정의를 가르는 줄이다.**\n *\n * 이 화면은 단계 이름 하나로 「계획」·「동작함」만 말했다. 그런데 사용자가 카탈로그를 보고 물은 것은\n * 「화면 설정도 없이 이게 정의냐」였고, 화면이 그 칸을 안 보이니 세는 사람이 파일을 열어야 했다.\n * 액티비티가 서려면 주고받는 값과 화면과 콜백이 있어야 하고, 선언만 된 항목에는 그중 아무것도 없다.\n *\n * 설치되지 않은 항목에는 그리지 않는다. 45건에 「없음 · 없음 · 없음」을 세 줄씩 붙이면 그 자체가\n * 벽이고, 무엇이 없는지는 그 항목의 gaps 가 이미 사람 말로 적고 있다.\n */\n private renderBuilt(one: any) {\n if (!one.activity?.id) {\n return ''\n }\n\n const model = (one.model || []).filter((item: any) => !item?.hidden)\n const taking = model.filter((item: any) => item?.inout == 'in' || item?.inout == 'inout').length\n const giving = model.filter((item: any) => item?.inout == 'out' || item?.inout == 'inout').length\n const decisions = (one.activity?.decisionKeys || []).length\n\n /*\n * 결재 화면이 무엇으로 그려지나. 전용 요소는 이름까지 적는다 — 「전용 화면이 있다」만으로는 어느\n * 것인지 못 찾고, 이 절을 읽는 사람은 그 파일을 열려는 사람이다.\n *\n * 선언이 채워지면 기본 화면도 판단을 그린다. 그래서 「기본 화면」 뒤에 판단 항목 수가 붙는다 —\n * 0 이면 그 화면은 아직 칸 목록이다.\n */\n const screen = one.viewSource\n ? html`${i18next.t('text.own-approval-view')} · <code>${one.viewSource}</code>`\n : html`${i18next.t('text.generated-approval-view')}`\n\n return html`\n <div>${i18next.t('text.model-in-out', { taking, giving })}</div>\n <div>${i18next.t('field.approval-view')} — ${screen}</div>\n <div>${i18next.t('text.decision-keys-count', { n: decisions })}</div>\n `\n }\n\n /** 잰 날짜를 수와 함께 낸다 — 손으로 적는 기록이라 낡는데, 날짜가 있으면 낡았다는 것을 안다. */\n private renderRun(run: any) {\n const at = run.at ? new Date(Date.parse(String(run.at))) : undefined\n const when =\n at && Number.isFinite(at.getTime())\n ? at.toLocaleString(i18next.language || undefined, {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: false\n })\n : ''\n\n return html`${typeof run.passed == 'number' ? run.passed : '—'} /\n ${run.total}${when ? html` · ${when}` : ''}${run.command ? html`<div><code>${run.command}</code></div>` : ''}`\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n await this.fetch()\n }\n }\n\n /**\n * 주소로 바로 들어온 경우 — **`pageUpdated` 가 안 온다.**\n *\n * 메뉴에서 눌러 들어오면 화면이 꺼졌다 켜지면서 `pageUpdated` 가 오고 거기서 읽는다. 그런데 주소를\n * 직접 열면 이 요소가 **이미 active 인 채로** 만들어져서 그 전환이 없다. 실측했다: `active` 는\n * 참인데 `loaded` 가 거짓이고, 화면은 아무것도 없이 조용했다 — 오류도 빈 화면 문구도 없다.\n *\n * 목록 화면들은 이 자리가 안 비어 있다. grist 가 첫 렌더에서 스스로 `fetchHandler` 를 부르기\n * 때문이다. 이 화면은 grist 를 안 쓰니 부르는 사람이 없었다.\n *\n * 그래서 켜져 있는데 아직 안 읽었으면 여기서 읽는다. `loaded` 가 그 조건이라 두 번 읽지 않는다.\n */\n updated(changes: any) {\n if (this.active && !this.loaded && !this.failed) {\n this.fetch()\n }\n }\n\n async fetch() {\n const response = await client.query({ query: CatalogFetch, fetchPolicy: 'no-cache' })\n\n /*\n * 이 client 는 errorPolicy: 'all' 이라 질의가 실패해도 거절되지 않는다. 그대로 읽으면 실패가\n * 「등록된 업무가 없다」로 그려진다.\n */\n const items = response.errors?.length ? undefined : response.data?.responses?.items\n\n if (!Array.isArray(items)) {\n this.failed = true\n this.loadError = response.errors?.length ? response.errors : new Error('no data')\n this.loaded = true\n console.error('[activity-catalog]', response.errors || 'no data')\n return\n }\n\n this.failed = false\n this.loadError = null\n this.items = [...items].sort(\n (a, b) =>\n stageRank(a.readiness?.stage) - stageRank(b.readiness?.stage) || shownName(a).localeCompare(shownName(b))\n )\n this.loaded = true\n }\n}\n"]}
1
+ {"version":3,"file":"activity-catalog-page.js","sourceRoot":"","sources":["../../../client/pages/activity-catalog/activity-catalog-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/list-state/ox-page-state.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { DocumentPageStyles } from '@operato/styles'\nimport { isApprovalStep } from '@things-factory/organization/dist-client'\n\nimport { guideLines } from './activity-guide.js'\nimport { detailAddress, opensDetail } from '../work-door/door-links.js'\nimport {\n DoorCounts,\n DoorFacts,\n doorLabel,\n doorsSummary,\n followsNote,\n lineNote,\n whenNoLineTag\n} from '../work-door/door-sentence.js'\nimport { kindWord, reasonWord, standingWord, whenNoLineBecauseWord, whenNoLineWord } from '../work-door/door-words.js'\n\n/**\n * 업무 카탈로그 — **이 사업장의 업무가 무엇을 하고, 누가 결재하나.**\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── 두 화면을 하나로 (2026-10-18, 사용자 판단) ──────────────────────────────\n * 「결재·배정 양식 현황」과 「업무 양식 목록」이 같은 업무를 두 번 늘어놓았다. 앞은 결재선이 섰나를,\n * 뒤는 업무가 무엇인가를 말했고, 뒤에는 만드는 쪽이 읽는 값(모델 수 · 판단 키 · 시험 실행)이 섞여\n * 있었다. 틀은 앞 화면 것을 쓰고, 뒤에서는 업무 설명 한 줄만 가져왔다.\n *\n * ── 왜 이 화면이 있나 ──────────────────────────────────────────────────────\n * 양식은 제품이 세우고 **결재선은 그 사업장이 채운다.** 비어 있는 것은 결함이 아니라 선택인데, 그\n * 선택이 어디에도 안 보였다. 실측(2026-09-11): 미라텍에 양식 11개가 다 서 있고 11개 전부 결재자가\n * 없었다 — 실적 정정도 폐기도 승인 없이 반영되는데 화면에는 결재가 있는 것처럼 보였다.\n *\n * ── 결재선은 그려서 보인다 ─────────────────────────────────────────────────\n * 「…은 결재자 2명을 지납니다」는 몇 명인지만 말하고 누구인지는 안 말했다. 줄마다 결재선을 단계와\n * 이름으로 그린다 — 업무함 띠가 쓰는 organization 의 approval-line-brief 를 그대로 쓴다. 서버는 그\n * 업무가 실제로 거치는 결재선을 보낸다(다른 업무의 결재선을 따르면 그 업무의 것).\n *\n * ── 빈 결재선의 결과는 업무마다 선언돼 있다 ────────────────────────────────\n * `run` 업무는 상신하는 사람이 자기 건을 승인한 것이 되고, `refuse` 업무는 상신 자체가 거절된다\n * (ADR-0077). 결재선 밑 한 줄이 그것을 말한다.\n *\n * ── 할 일이 있는 것부터 ────────────────────────────────────────────────────\n * 정할 것이 남은 것을 위로 올린다. 같은 무리 안에서는 선언 순서를 지킨다.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/*\n * A step is asked for every field it carries, though this screen only draws it - organization's\n * approval-line-step-fields test holds every selection to the editor's set.\n */\nconst CATALOG = gql`\n {\n workDoors {\n todo\n on\n off\n missing\n notUsed\n seatsStanding\n seatsOffered\n doors {\n name\n labelKey\n kind\n standing\n reason\n approvers\n from\n whenNoLine\n whenNoLineBecause\n followsLabelKey\n assigneeRole\n notUsedBecause\n approvalLine {\n type\n value\n participation\n notifyAfter\n approver {\n id\n name\n description\n controlNo\n }\n }\n }\n }\n installableActivities {\n items {\n name\n guide\n guideTKeys\n }\n }\n }\n`\n\ntype Door = DoorFacts & {\n kind: 'approval' | 'assignment'\n standing: 'on' | 'off' | 'missing' | 'not-used'\n from?: string\n approvalLine?: any[] | null\n /** What the activity is for - the first line of its declared guide, in the reader's language. */\n about?: string\n}\n\nconst ORDER: Record<Door['standing'], number> = { missing: 0, off: 1, on: 2, 'not-used': 3 }\n\n@customElement('activity-catalog-page')\nexport class ActivityCatalogPage extends localize(i18next)(PageView) {\n static styles = [\n DocumentPageStyles,\n css`\n /*\n * One activity, one row: what it is on the left, what it does and who approves on the right.\n * The rows share one grid (subgrid), so every right column starts at the same x.\n */\n .doors {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n column-gap: var(--spacing-huge, 24px);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .door {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: subgrid;\n row-gap: var(--spacing-small, 4px);\n padding: var(--spacing-large, 12px) 0;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n\n .door:first-child {\n border-top: none;\n }\n\n @media (max-width: 600px) {\n .doors {\n grid-template-columns: minmax(0, 1fr);\n }\n }\n\n .what {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n }\n\n .name {\n font-weight: 600;\n }\n\n /* Kind in words: an empty approval line and an empty assignment line do opposite things. */\n .kind {\n color: var(--ui-muted);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /* The state says it in words as well as colour: colour alone says nothing to someone who cannot see it. */\n .mark {\n padding: 0 var(--spacing-small, 4px);\n border: 1px solid currentColor;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n font-size: var(--ui-t-micro, 11px);\n font-weight: 600;\n line-height: 1.6;\n white-space: nowrap;\n }\n\n .mark.on {\n color: var(--md-sys-color-primary);\n }\n\n .mark.off {\n color: var(--md-sys-color-tertiary);\n }\n\n .mark.missing {\n color: var(--md-sys-color-error);\n }\n\n /* Not a task, so quieter. Not removed: that it was turned off has to be readable. */\n .mark.not-used {\n color: var(--md-sys-color-outline);\n }\n\n .door.not-used .what,\n .door.not-used .says {\n opacity: 0.7;\n }\n\n .says {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n min-width: 0;\n }\n\n .line {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-small, 4px) var(--spacing-large, 12px);\n }\n\n /*\n * The brief spreads its seats over the width it is given; a two-step line across a wide column\n * reads as three islands. Each seat gets about the width of a name.\n */\n approval-line-brief {\n flex: 0 1 auto;\n width: calc(var(--seats) * 88px);\n max-width: 100%;\n font-size: var(--ui-t-small, 11.5px);\n }\n\n .when,\n .from {\n color: var(--ui-muted);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n .state {\n margin: 0 0 var(--spacing-medium, 8px);\n font-weight: 600;\n }\n\n ol.next {\n margin: 0;\n padding-left: var(--spacing-huge, 24px);\n display: flex;\n flex-direction: column;\n gap: var(--spacing-medium, 8px);\n }\n `\n ]\n\n @state() private doors?: Door[]\n @state() private counts: DoorCounts = { on: 0, off: 0, missing: 0, notUsed: 0, todo: 0 }\n @state() private todo = 0\n @state() private seatsStanding = 0\n @state() private seatsOffered = 0\n @state() private loadError: unknown = null\n\n get context() {\n return {\n title: i18next.t('title.activity catalog'),\n frame: 'document'\n }\n }\n\n async pageInitialized() {\n await this.load()\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (lifecycle.active && !this.doors) {\n await this.load()\n }\n }\n\n private async load() {\n this.loadError = null\n\n let response: any\n try {\n response = await client.query({ query: CATALOG, fetchPolicy: 'no-cache' })\n } catch (error) {\n this.loadError = error\n return\n }\n\n /*\n * 못 읽은 것을 빈 목록으로 그리지 않는다. 「업무가 하나도 없습니다」와 「못 읽었습니다」는 사람이 할\n * 일이 다르다. ox-page-state 가 서버의 문장과 다시 읽기를 그린다(ADR-0060 결정 8).\n */\n if (response.errors?.length) {\n this.loadError = response.errors[0]\n return\n }\n\n const guides = new Map<string, any>(\n (response.data?.installableActivities?.items ?? []).map((one: any) => [one.name, one])\n )\n\n /* 전선의 철자를 여기서 **한 번** 옮긴다(§`door-words`). */\n this.doors = (response.data?.workDoors?.doors ?? []).map((one: any) => ({\n ...one,\n standing: standingWord(one.standing) ?? one.standing,\n kind: kindWord(one.kind) ?? one.kind,\n reason: reasonWord(one.reason) ?? one.reason,\n whenNoLine: whenNoLineWord(one.whenNoLine),\n whenNoLineBecause: whenNoLineBecauseWord(one.whenNoLineBecause),\n about: guideLines(guides.get(one.name), (key, options) => i18next.t(key, options))[0]\n }))\n\n const read = response.data?.workDoors ?? {}\n\n this.todo = read.todo ?? 0\n this.counts = {\n on: read.on ?? 0,\n off: read.off ?? 0,\n missing: read.missing ?? 0,\n notUsed: read.notUsed ?? 0,\n todo: this.todo\n }\n this.seatsStanding = read.seatsStanding ?? 0\n this.seatsOffered = read.seatsOffered ?? 0\n }\n\n /** 결재선은 각 업무에서 지정하고, 역할이 부족할 때만 별도로 안내한다. */\n private renderNext() {\n if (!this.todo || this.seatsStanding >= this.seatsOffered) {\n return ''\n }\n\n return html`\n <section class=\"page-section\">\n <div class=\"page-section-header\"><h3>${i18next.t('title.work-doors-next')}</h3></div>\n <ol class=\"next\">\n <li>\n ${i18next.t('text.work-doors-next-seats', {\n standing: this.seatsStanding,\n offered: this.seatsOffered\n })}\n <a class=\"page-nav-link\" href=\"roles\">${i18next.t('field.roles')}</a>\n </li>\n </ol>\n </section>\n `\n }\n\n render() {\n return html`<div class=\"page\">\n <ox-page-state .loading=${!this.doors && !this.loadError} .error=${this.loadError} @retry=${() => this.load()}\n >${this.doors && !this.loadError ? this.renderDoors() : ''}</ox-page-state\n >\n </div>`\n }\n\n private renderDoors() {\n const sorted = [...this.doors!].sort((a, b) => ORDER[a.standing] - ORDER[b.standing])\n\n return html`\n <section class=\"page-section\">\n <p class=\"state\">${doorsSummary(i18next.t, this.counts)}</p>\n <ul class=\"doors\">\n ${sorted.map(door => this.renderDoor(door))}\n </ul>\n </section>\n\n ${this.renderNext()}\n `\n }\n\n /**\n * Where 「결재선 지정」 goes: this activity's detail, or - when it follows another activity's line - that\n * activity's, since the line is set there. None for a form borrowed from another site.\n */\n private lineEditAddress(door: Door): string {\n if (door.kind !== 'approval' || (door.standing !== 'on' && door.standing !== 'off')) {\n return ''\n }\n\n const owner = door.followsLabelKey ? this.doors!.find(one => one.labelKey === door.followsLabelKey) : door\n\n return owner && opensDetail(owner) && opensDetail(door) ? detailAddress(owner.name) : ''\n }\n\n private renderDoor(door: Door) {\n const label = doorLabel(i18next.t, door)\n const steps = (door.approvalLine || []).filter(isApprovalStep).length\n const drawsLine = door.kind === 'approval' && steps > 0\n const note = lineNote(i18next.t, door, drawsLine)\n const follows = followsNote(i18next.t, door)\n const when = whenNoLineTag(i18next.t, door)\n const edit = this.lineEditAddress(door)\n\n return html`\n <li class=\"door ${door.standing}\">\n <div class=\"what\">\n ${opensDetail(door)\n ? html`<a class=\"name\" href=${detailAddress(door.name)}>${label}</a>`\n : html`<span class=\"name\">${label}</span>`}\n <span class=\"kind\">${i18next.t(`text.door-kind-${door.kind}`)}</span>\n <span class=\"mark ${door.standing}\">${i18next.t(`text.door-standing-${door.standing}`)}</span>\n </div>\n <div class=\"says\">\n ${door.about ? html`<span class=\"about\">${door.about}</span>` : ''}\n ${drawsLine || note || edit\n ? html`<div class=\"line\">\n ${drawsLine\n ? html`<approval-line-brief\n plan\n style=\"--seats: ${(door.approvalLine || []).length + 1}\"\n .model=${door.approvalLine}\n ></approval-line-brief>`\n : ''}\n ${note ? html`<span>${note}</span>` : ''}\n ${edit\n ? html`<a class=\"page-nav-link\" href=${edit}>${i18next.t('button.activity-set-approval-line')}</a>`\n : ''}\n </div>`\n : ''}\n ${follows ? html`<span class=\"when\">${follows}</span>` : ''}\n ${when ? html`<span class=\"when\">${when}</span>` : ''}\n ${\n /*\n * 남의 양식을 쓰는 것은 정상이지만, 안 말하면 「정한 적 없는데」가 된다. 차 있으면 어디서\n * 정했는지, 비어 있으면 여기서는 못 고친다는 것을 말한다.\n */\n door.from\n ? html`<span class=\"from\"\n >${door.standing === 'on'\n ? i18next.t('text.door-filled-from', { name: door.from })\n : i18next.t('text.door-form-from', { name: door.from })}</span\n >`\n : ''\n }\n </div>\n </li>\n `\n }\n}\n"]}
@@ -56,7 +56,7 @@ export declare class ActivityThreadPage extends ActivityThreadPage_base {
56
56
  /** 타임라인 위에 무엇을 그리나 — 규칙은 thread-sections 에 있다. */
57
57
  sections(): ThreadSections;
58
58
  /** 액티비티가 선언한 결재 내용 — 결재 화면과 같은 그리기다. */
59
- decision(): typeof nothing | import("lit-html").TemplateResult;
59
+ decision(): import("lit-html").TemplateResult | typeof nothing;
60
60
  activityContent(): DirectiveResult<import("lit-html/directive.js").DirectiveClass>;
61
61
  /**
62
62
  * 화면 종류가 달라도 **같은 자리에 같은 모양으로 놓인다.**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Where a row of the work-doors screen takes its reader.
2
+ * Where a row of the activity catalog takes its reader.
3
3
  *
4
4
  * The approval line of one activity is set on that activity's detail screen, together with whether
5
5
  * it is used here and the master change policy that routes to it. This screen used to send people to
@@ -19,12 +19,4 @@ type DoorLike = {
19
19
  export declare function detailAddress(name: string): string;
20
20
  /** The row opens its activity's detail unless the form belongs to another site. */
21
21
  export declare function opensDetail(door: DoorLike): boolean;
22
- /**
23
- * The doors to name under "set an approval line": approval forms, standing but empty, owned here.
24
- * An empty assignment form lacks a role, not a line - its row says so and links to the detail.
25
- *
26
- * `missing` is left out - that form did not stand at start-up, and the line under it says to read
27
- * the boot log. Setting a line would not fix it.
28
- */
29
- export declare function doorsToSetHere<T extends DoorLike>(doors: readonly T[]): T[];
30
22
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Where a row of the work-doors screen takes its reader.
2
+ * Where a row of the activity catalog takes its reader.
3
3
  *
4
4
  * The approval line of one activity is set on that activity's detail screen, together with whether
5
5
  * it is used here and the master change policy that routes to it. This screen used to send people to
@@ -17,14 +17,4 @@ export function detailAddress(name) {
17
17
  export function opensDetail(door) {
18
18
  return !!door.name && !door.from;
19
19
  }
20
- /**
21
- * The doors to name under "set an approval line": approval forms, standing but empty, owned here.
22
- * An empty assignment form lacks a role, not a line - its row says so and links to the detail.
23
- *
24
- * `missing` is left out - that form did not stand at start-up, and the line under it says to read
25
- * the boot log. Setting a line would not fix it.
26
- */
27
- export function doorsToSetHere(doors) {
28
- return doors.filter(one => one.kind === 'approval' && one.standing === 'off' && opensDetail(one));
29
- }
30
20
  //# sourceMappingURL=door-links.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"door-links.js","sourceRoot":"","sources":["../../../client/pages/work-door/door-links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,uBAAuB,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;AAC3D,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAClC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAqB,KAAmB;IACpE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;AACnG,CAAC","sourcesContent":["/**\n * Where a row of the work-doors screen takes its reader.\n *\n * The approval line of one activity is set on that activity's detail screen, together with whether\n * it is used here and the master change policy that routes to it. This screen used to send people to\n * the definition grid instead - a screen with no menu entry, identifiers, and a double click to open.\n *\n * `WorkDoorType.name` is the activity's name, so it is the key the detail screen takes.\n *\n * A form borrowed from another site is not linked: the row already says it cannot be changed here,\n * and a link would contradict it.\n */\n\ntype DoorLike = { name: string; standing: string; kind?: string; from?: string }\n\nexport function detailAddress(name: string): string {\n return 'activity-detail?name=' + encodeURIComponent(name)\n}\n\n/** The row opens its activity's detail unless the form belongs to another site. */\nexport function opensDetail(door: DoorLike): boolean {\n return !!door.name && !door.from\n}\n\n/**\n * The doors to name under \"set an approval line\": approval forms, standing but empty, owned here.\n * An empty assignment form lacks a role, not a line - its row says so and links to the detail.\n *\n * `missing` is left out - that form did not stand at start-up, and the line under it says to read\n * the boot log. Setting a line would not fix it.\n */\nexport function doorsToSetHere<T extends DoorLike>(doors: readonly T[]): T[] {\n return doors.filter(one => one.kind === 'approval' && one.standing === 'off' && opensDetail(one))\n}\n"]}
1
+ {"version":3,"file":"door-links.js","sourceRoot":"","sources":["../../../client/pages/work-door/door-links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,uBAAuB,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;AAC3D,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAClC,CAAC","sourcesContent":["/**\n * Where a row of the activity catalog takes its reader.\n *\n * The approval line of one activity is set on that activity's detail screen, together with whether\n * it is used here and the master change policy that routes to it. This screen used to send people to\n * the definition grid instead - a screen with no menu entry, identifiers, and a double click to open.\n *\n * `WorkDoorType.name` is the activity's name, so it is the key the detail screen takes.\n *\n * A form borrowed from another site is not linked: the row already says it cannot be changed here,\n * and a link would contradict it.\n */\n\ntype DoorLike = { name: string; standing: string; kind?: string; from?: string }\n\nexport function detailAddress(name: string): string {\n return 'activity-detail?name=' + encodeURIComponent(name)\n}\n\n/** The row opens its activity's detail unless the form belongs to another site. */\nexport function opensDetail(door: DoorLike): boolean {\n return !!door.name && !door.from\n}\n"]}
@@ -1,21 +1,24 @@
1
1
  /**
2
- * The sentences of the work-doors screen, **composed here from facts and translations.**
2
+ * What a row of the activity catalog says, **composed here from facts and translations.**
3
3
  *
4
4
  * ═══════════════════════════════════════════════════════════════════════════
5
5
  * ── Why the screen writes them ────────────────────────────────────────────
6
6
  * The server used to send each row's sentence and the summary already written, in Korean. An English,
7
7
  * Japanese, Chinese or Malay reader got Korean, and the screen had no way to draw a row differently
8
8
  * without reading the sentence back apart. The server now sends facts (`WorkDoorType`) and every
9
- * sentence is a translation key here.
9
+ * phrase is a translation key here.
10
10
  *
11
- * ── The empty line is the door's declaration, not one sentence ────────────
11
+ * ── The line is drawn, not described ──────────────────────────────────────
12
+ * A filled line used to read 「…은 결재자 2명을 지납니다」. The row now draws the line itself (organization's
13
+ * approval-line-brief, steps and names), so the words here are only for what a drawing cannot say: there
14
+ * is no line, nobody holds the role, the form follows another one, it never installed.
15
+ *
16
+ * ── The empty line is the door's declaration ──────────────────────────────
12
17
  * What an empty approval line does is declared per door (ADR-0077 decision 1). `run` lets the raiser
13
- * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. The
14
- * old sentence said "the raiser approves their own" for every door, and four refusing doors on :4000
15
- * carried it (2026-09-24). A door with no declaration says nothing about the consequence rather than
16
- * guessing one.
18
+ * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. A door
19
+ * with no declaration says nothing about the consequence rather than guessing one.
17
20
  *
18
- * Pure: `t` is passed in, so a test can load the real translation files and read the sentences.
21
+ * Pure: `t` is passed in, so a test can load the real translation files and read the phrases.
19
22
  * ═══════════════════════════════════════════════════════════════════════════
20
23
  */
21
24
  /** The row as this screen holds it, after `door-words` has moved the wire spellings. */
@@ -50,14 +53,23 @@ export declare function doorLabel(t: T, door: {
50
53
  }): string;
51
54
  /** Why an approval door will not run on an empty line, as a short phrase. Empty when not declared. */
52
55
  export declare function whyItRefuses(t: T, door: Pick<DoorFacts, 'whenNoLineBecause'>): string;
53
- /** What this row says about its standing. */
54
- export declare function doorSentence(t: T, door: DoorFacts): string;
55
56
  /**
56
- * What the door does when its line is empty, as a short tag - shown on rows whose sentence does not
57
- * already say it (ADR-0077 decision 3). An empty-line row already says it; a not-used or missing row
58
- * does not go through the line at all.
57
+ * What the line slot says, beside or instead of the drawn line.
58
+ *
59
+ * `drawsLine` is whether the row draws approval steps - the page counts them with organization's rule,
60
+ * which this pure file does not load. A not-used row shows what the plant wrote, as written.
61
+ */
62
+ export declare function lineNote(t: T, door: DoorFacts, drawsLine: boolean): string;
63
+ /** The door whose line this one uses, by name - the line is set there. */
64
+ export declare function followsNote(t: T, door: DoorFacts): string;
65
+ /**
66
+ * What the door does when its line is empty (ADR-0077 decision 3), as one quiet line under the line.
67
+ * Only approval doors that stand go through a line at all.
59
68
  */
60
69
  export declare function whenNoLineTag(t: T, door: DoorFacts): string;
61
- /** The whole plant in one sentence - a list alone makes the reader count rows. */
70
+ /**
71
+ * The whole catalog in one line, counts only: how many, and how many stand each way. The words are the
72
+ * row marks' own, so the line and the rows read alike. A count of zero is left out.
73
+ */
62
74
  export declare function doorsSummary(t: T, counts: DoorCounts): string;
63
75
  export {};
@@ -1,26 +1,29 @@
1
1
  /**
2
- * The sentences of the work-doors screen, **composed here from facts and translations.**
2
+ * What a row of the activity catalog says, **composed here from facts and translations.**
3
3
  *
4
4
  * ═══════════════════════════════════════════════════════════════════════════
5
5
  * ── Why the screen writes them ────────────────────────────────────────────
6
6
  * The server used to send each row's sentence and the summary already written, in Korean. An English,
7
7
  * Japanese, Chinese or Malay reader got Korean, and the screen had no way to draw a row differently
8
8
  * without reading the sentence back apart. The server now sends facts (`WorkDoorType`) and every
9
- * sentence is a translation key here.
9
+ * phrase is a translation key here.
10
10
  *
11
- * ── The empty line is the door's declaration, not one sentence ────────────
11
+ * ── The line is drawn, not described ──────────────────────────────────────
12
+ * A filled line used to read 「…은 결재자 2명을 지납니다」. The row now draws the line itself (organization's
13
+ * approval-line-brief, steps and names), so the words here are only for what a drawing cannot say: there
14
+ * is no line, nobody holds the role, the form follows another one, it never installed.
15
+ *
16
+ * ── The empty line is the door's declaration ──────────────────────────────
12
17
  * What an empty approval line does is declared per door (ADR-0077 decision 1). `run` lets the raiser
13
- * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. The
14
- * old sentence said "the raiser approves their own" for every door, and four refusing doors on :4000
15
- * carried it (2026-09-24). A door with no declaration says nothing about the consequence rather than
16
- * guessing one.
18
+ * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. A door
19
+ * with no declaration says nothing about the consequence rather than guessing one.
17
20
  *
18
- * Pure: `t` is passed in, so a test can load the real translation files and read the sentences.
21
+ * Pure: `t` is passed in, so a test can load the real translation files and read the phrases.
19
22
  * ═══════════════════════════════════════════════════════════════════════════
20
23
  */
21
24
  /*
22
- * Values reach the sentence through lit, which escapes them. i18next escaping on top would print
23
- * `&amp;` for a plant's own "we do not use this" note.
25
+ * Values reach the phrase through lit, which escapes them. i18next escaping on top would print
26
+ * `&amp;` in a role name.
24
27
  */
25
28
  const RAW = { interpolation: { escapeValue: false } };
26
29
  /**
@@ -34,42 +37,42 @@ export function doorLabel(t, door) {
34
37
  export function whyItRefuses(t, door) {
35
38
  return door.whenNoLineBecause ? String(t(`text.door-refuses-because-${door.whenNoLineBecause}`)) : '';
36
39
  }
37
- /** What this row says about its standing. */
38
- export function doorSentence(t, door) {
39
- const label = doorLabel(t, door);
40
- const said = [String(t(sentenceKey(door), { ...RAW, label, ...sentenceParams(t, door) }))];
41
- if (door.followsLabelKey && door.standing !== 'not-used' && door.standing !== 'missing') {
42
- said.push(String(t('text.door-because-follows', { ...RAW, label: doorLabel(t, { labelKey: door.followsLabelKey, name: '' }) })));
40
+ /**
41
+ * What the line slot says, beside or instead of the drawn line.
42
+ *
43
+ * `drawsLine` is whether the row draws approval steps - the page counts them with organization's rule,
44
+ * which this pure file does not load. A not-used row shows what the plant wrote, as written.
45
+ */
46
+ export function lineNote(t, door, drawsLine) {
47
+ if (door.standing === 'not-used') {
48
+ return door.notUsedBecause ?? '';
43
49
  }
44
- return said.join(' ');
45
- }
46
- function sentenceKey(door) {
47
- if (door.reason === 'line-empty') {
48
- return door.whenNoLine ? `text.door-because-line-empty-${door.whenNoLine}` : 'text.door-because-line-empty';
50
+ if (door.standing === 'missing') {
51
+ return String(t('text.activity-catalog-missing'));
52
+ }
53
+ if (door.kind === 'assignment') {
54
+ return door.assigneeRole
55
+ ? String(t('text.activity-catalog-assignee', { ...RAW, role: door.assigneeRole }))
56
+ : String(t('text.activity-catalog-no-assignee'));
57
+ }
58
+ if (door.reason === 'role-empty' || door.reason === 'person-absent') {
59
+ return String(t(`text.activity-catalog-${door.reason}`));
49
60
  }
50
- return `text.door-because-${door.reason}`;
61
+ return drawsLine ? '' : String(t('text.activity-catalog-no-line'));
51
62
  }
52
- function sentenceParams(t, door) {
53
- switch (door.reason) {
54
- case 'not-used':
55
- return { reason: door.notUsedBecause ?? '' };
56
- case 'line-filled':
57
- return { count: door.approvers };
58
- case 'assignee-bound':
59
- return { role: door.assigneeRole ?? '' };
60
- case 'line-empty':
61
- return { why: whyItRefuses(t, door) };
62
- default:
63
- return {};
63
+ /** The door whose line this one uses, by name - the line is set there. */
64
+ export function followsNote(t, door) {
65
+ if (!door.followsLabelKey || door.standing === 'not-used' || door.standing === 'missing') {
66
+ return '';
64
67
  }
68
+ return String(t('text.activity-catalog-follows', { ...RAW, label: doorLabel(t, { labelKey: door.followsLabelKey, name: '' }) }));
65
69
  }
66
70
  /**
67
- * What the door does when its line is empty, as a short tag - shown on rows whose sentence does not
68
- * already say it (ADR-0077 decision 3). An empty-line row already says it; a not-used or missing row
69
- * does not go through the line at all.
71
+ * What the door does when its line is empty (ADR-0077 decision 3), as one quiet line under the line.
72
+ * Only approval doors that stand go through a line at all.
70
73
  */
71
74
  export function whenNoLineTag(t, door) {
72
- if (door.kind !== 'approval' || !door.whenNoLine || door.reason === 'line-empty') {
75
+ if (door.kind !== 'approval' || !door.whenNoLine) {
73
76
  return '';
74
77
  }
75
78
  if (door.standing !== 'on' && door.standing !== 'off') {
@@ -79,31 +82,26 @@ export function whenNoLineTag(t, door) {
79
82
  const tag = String(t(`text.door-when-no-line-${door.whenNoLine}`));
80
83
  return door.whenNoLine === 'refuse' && why ? `${tag} (${why})` : tag;
81
84
  }
82
- /** The whole plant in one sentence - a list alone makes the reader count rows. */
85
+ /**
86
+ * The whole catalog in one line, counts only: how many, and how many stand each way. The words are the
87
+ * row marks' own, so the line and the rows read alike. A count of zero is left out.
88
+ */
83
89
  export function doorsSummary(t, counts) {
84
90
  const total = counts.on + counts.off + counts.missing + counts.notUsed;
85
91
  if (!total) {
86
- return String(t('text.work-doors-summary-none'));
87
- }
88
- /*
89
- * Only `off + missing` is counted, so that zero means done. Counting the doors a plant opted out of
90
- * would leave the number standing in a plant that filled everything, and the screen would nag.
91
- */
92
- if (!counts.todo) {
93
- return counts.notUsed
94
- ? String(t('text.work-doors-summary-done-not-used', { on: counts.on, notUsed: counts.notUsed }))
95
- : String(t('text.work-doors-summary-all-on', { count: total }));
96
- }
97
- const said = [String(t('text.work-doors-summary-todo', { count: counts.todo }))];
98
- if (counts.off) {
99
- said.push(String(t('text.work-doors-summary-off', { count: counts.off })));
100
- }
101
- if (counts.missing) {
102
- said.push(String(t('text.work-doors-summary-missing', { count: counts.missing })));
103
- }
104
- if (counts.notUsed) {
105
- said.push(String(t('text.work-doors-summary-not-used', { count: counts.notUsed })));
92
+ return String(t('text.activity-catalog-summary-none'));
106
93
  }
107
- return said.join(' ');
94
+ const parts = [
95
+ ['on', counts.on],
96
+ ['off', counts.off],
97
+ ['missing', counts.missing],
98
+ ['not-used', counts.notUsed]
99
+ ];
100
+ return [
101
+ String(t('text.activity-catalog-summary-total', { count: total })),
102
+ ...parts
103
+ .filter(([, count]) => count)
104
+ .map(([standing, count]) => String(t('text.activity-catalog-summary-part', { ...RAW, standing: t(`text.door-standing-${standing}`), count })))
105
+ ].join(' · ');
108
106
  }
109
107
  //# sourceMappingURL=door-sentence.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"door-sentence.js","sourceRoot":"","sources":["../../../client/pages/work-door/door-sentence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The sentences of the work-doors screen, **composed here from facts and translations.**\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── Why the screen writes them ────────────────────────────────────────────\n * The server used to send each row's sentence and the summary already written, in Korean. An English,\n * Japanese, Chinese or Malay reader got Korean, and the screen had no way to draw a row differently\n * without reading the sentence back apart. The server now sends facts (`WorkDoorType`) and every\n * sentence is a translation key here.\n *\n * ── The empty line is the door's declaration, not one sentence ────────────\n * What an empty approval line does is declared per door (ADR-0077 decision 1). `run` lets the raiser\n * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. The\n * old sentence said \"the raiser approves their own\" for every door, and four refusing doors on :4000\n * carried it (2026-09-24). A door with no declaration says nothing about the consequence rather than\n * guessing one.\n *\n * Pure: `t` is passed in, so a test can load the real translation files and read the sentences.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/** The row as this screen holds it, after `door-words` has moved the wire spellings. */\nexport type DoorFacts = {\n name: string\n labelKey: string\n kind: string\n standing: string\n reason: string\n approvers: number\n whenNoLine?: string\n whenNoLineBecause?: string\n followsLabelKey?: string\n assigneeRole?: string\n notUsedBecause?: string\n}\n\nexport type DoorCounts = { on: number; off: number; missing: number; notUsed: number; todo: number }\n\ntype T = (key: string, options?: Record<string, unknown>) => string\n\n/*\n * Values reach the sentence through lit, which escapes them. i18next escaping on top would print\n * `&amp;` for a plant's own \"we do not use this\" note.\n */\nconst RAW = { interpolation: { escapeValue: false } }\n\n/**\n * A door's name. A label key without a translation falls back to the form name - a name a person can\n * search for - rather than printing the key.\n */\nexport function doorLabel(t: T, door: { labelKey: string; name: string }): string {\n return String(t(door.labelKey, { defaultValue: door.name }))\n}\n\n/** Why an approval door will not run on an empty line, as a short phrase. Empty when not declared. */\nexport function whyItRefuses(t: T, door: Pick<DoorFacts, 'whenNoLineBecause'>): string {\n return door.whenNoLineBecause ? String(t(`text.door-refuses-because-${door.whenNoLineBecause}`)) : ''\n}\n\n/** What this row says about its standing. */\nexport function doorSentence(t: T, door: DoorFacts): string {\n const label = doorLabel(t, door)\n const said = [String(t(sentenceKey(door), { ...RAW, label, ...sentenceParams(t, door) }))]\n\n if (door.followsLabelKey && door.standing !== 'not-used' && door.standing !== 'missing') {\n said.push(String(t('text.door-because-follows', { ...RAW, label: doorLabel(t, { labelKey: door.followsLabelKey, name: '' }) })))\n }\n\n return said.join(' ')\n}\n\nfunction sentenceKey(door: DoorFacts): string {\n if (door.reason === 'line-empty') {\n return door.whenNoLine ? `text.door-because-line-empty-${door.whenNoLine}` : 'text.door-because-line-empty'\n }\n\n return `text.door-because-${door.reason}`\n}\n\nfunction sentenceParams(t: T, door: DoorFacts): Record<string, unknown> {\n switch (door.reason) {\n case 'not-used':\n return { reason: door.notUsedBecause ?? '' }\n case 'line-filled':\n return { count: door.approvers }\n case 'assignee-bound':\n return { role: door.assigneeRole ?? '' }\n case 'line-empty':\n return { why: whyItRefuses(t, door) }\n default:\n return {}\n }\n}\n\n/**\n * What the door does when its line is empty, as a short tag - shown on rows whose sentence does not\n * already say it (ADR-0077 decision 3). An empty-line row already says it; a not-used or missing row\n * does not go through the line at all.\n */\nexport function whenNoLineTag(t: T, door: DoorFacts): string {\n if (door.kind !== 'approval' || !door.whenNoLine || door.reason === 'line-empty') {\n return ''\n }\n\n if (door.standing !== 'on' && door.standing !== 'off') {\n return ''\n }\n\n const why = whyItRefuses(t, door)\n const tag = String(t(`text.door-when-no-line-${door.whenNoLine}`))\n\n return door.whenNoLine === 'refuse' && why ? `${tag} (${why})` : tag\n}\n\n/** The whole plant in one sentence - a list alone makes the reader count rows. */\nexport function doorsSummary(t: T, counts: DoorCounts): string {\n const total = counts.on + counts.off + counts.missing + counts.notUsed\n\n if (!total) {\n return String(t('text.work-doors-summary-none'))\n }\n\n /*\n * Only `off + missing` is counted, so that zero means done. Counting the doors a plant opted out of\n * would leave the number standing in a plant that filled everything, and the screen would nag.\n */\n if (!counts.todo) {\n return counts.notUsed\n ? String(t('text.work-doors-summary-done-not-used', { on: counts.on, notUsed: counts.notUsed }))\n : String(t('text.work-doors-summary-all-on', { count: total }))\n }\n\n const said = [String(t('text.work-doors-summary-todo', { count: counts.todo }))]\n\n if (counts.off) {\n said.push(String(t('text.work-doors-summary-off', { count: counts.off })))\n }\n\n if (counts.missing) {\n said.push(String(t('text.work-doors-summary-missing', { count: counts.missing })))\n }\n\n if (counts.notUsed) {\n said.push(String(t('text.work-doors-summary-not-used', { count: counts.notUsed })))\n }\n\n return said.join(' ')\n}\n"]}
1
+ {"version":3,"file":"door-sentence.js","sourceRoot":"","sources":["../../../client/pages/work-door/door-sentence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a row of the activity catalog says, **composed here from facts and translations.**\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── Why the screen writes them ────────────────────────────────────────────\n * The server used to send each row's sentence and the summary already written, in Korean. An English,\n * Japanese, Chinese or Malay reader got Korean, and the screen had no way to draw a row differently\n * without reading the sentence back apart. The server now sends facts (`WorkDoorType`) and every\n * phrase is a translation key here.\n *\n * ── The line is drawn, not described ──────────────────────────────────────\n * A filled line used to read 「…은 결재자 2명을 지납니다」. The row now draws the line itself (organization's\n * approval-line-brief, steps and names), so the words here are only for what a drawing cannot say: there\n * is no line, nobody holds the role, the form follows another one, it never installed.\n *\n * ── The empty line is the door's declaration ──────────────────────────────\n * What an empty approval line does is declared per door (ADR-0077 decision 1). `run` lets the raiser\n * approve their own; `refuse` refuses the raise; `as-established` turns on how the row stood. A door\n * with no declaration says nothing about the consequence rather than guessing one.\n *\n * Pure: `t` is passed in, so a test can load the real translation files and read the phrases.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/** The row as this screen holds it, after `door-words` has moved the wire spellings. */\nexport type DoorFacts = {\n name: string\n labelKey: string\n kind: string\n standing: string\n reason: string\n approvers: number\n whenNoLine?: string\n whenNoLineBecause?: string\n followsLabelKey?: string\n assigneeRole?: string\n notUsedBecause?: string\n}\n\nexport type DoorCounts = { on: number; off: number; missing: number; notUsed: number; todo: number }\n\ntype T = (key: string, options?: Record<string, unknown>) => string\n\n/*\n * Values reach the phrase through lit, which escapes them. i18next escaping on top would print\n * `&amp;` in a role name.\n */\nconst RAW = { interpolation: { escapeValue: false } }\n\n/**\n * A door's name. A label key without a translation falls back to the form name - a name a person can\n * search for - rather than printing the key.\n */\nexport function doorLabel(t: T, door: { labelKey: string; name: string }): string {\n return String(t(door.labelKey, { defaultValue: door.name }))\n}\n\n/** Why an approval door will not run on an empty line, as a short phrase. Empty when not declared. */\nexport function whyItRefuses(t: T, door: Pick<DoorFacts, 'whenNoLineBecause'>): string {\n return door.whenNoLineBecause ? String(t(`text.door-refuses-because-${door.whenNoLineBecause}`)) : ''\n}\n\n/**\n * What the line slot says, beside or instead of the drawn line.\n *\n * `drawsLine` is whether the row draws approval steps - the page counts them with organization's rule,\n * which this pure file does not load. A not-used row shows what the plant wrote, as written.\n */\nexport function lineNote(t: T, door: DoorFacts, drawsLine: boolean): string {\n if (door.standing === 'not-used') {\n return door.notUsedBecause ?? ''\n }\n\n if (door.standing === 'missing') {\n return String(t('text.activity-catalog-missing'))\n }\n\n if (door.kind === 'assignment') {\n return door.assigneeRole\n ? String(t('text.activity-catalog-assignee', { ...RAW, role: door.assigneeRole }))\n : String(t('text.activity-catalog-no-assignee'))\n }\n\n if (door.reason === 'role-empty' || door.reason === 'person-absent') {\n return String(t(`text.activity-catalog-${door.reason}`))\n }\n\n return drawsLine ? '' : String(t('text.activity-catalog-no-line'))\n}\n\n/** The door whose line this one uses, by name - the line is set there. */\nexport function followsNote(t: T, door: DoorFacts): string {\n if (!door.followsLabelKey || door.standing === 'not-used' || door.standing === 'missing') {\n return ''\n }\n\n return String(t('text.activity-catalog-follows', { ...RAW, label: doorLabel(t, { labelKey: door.followsLabelKey, name: '' }) }))\n}\n\n/**\n * What the door does when its line is empty (ADR-0077 decision 3), as one quiet line under the line.\n * Only approval doors that stand go through a line at all.\n */\nexport function whenNoLineTag(t: T, door: DoorFacts): string {\n if (door.kind !== 'approval' || !door.whenNoLine) {\n return ''\n }\n\n if (door.standing !== 'on' && door.standing !== 'off') {\n return ''\n }\n\n const why = whyItRefuses(t, door)\n const tag = String(t(`text.door-when-no-line-${door.whenNoLine}`))\n\n return door.whenNoLine === 'refuse' && why ? `${tag} (${why})` : tag\n}\n\n/**\n * The whole catalog in one line, counts only: how many, and how many stand each way. The words are the\n * row marks' own, so the line and the rows read alike. A count of zero is left out.\n */\nexport function doorsSummary(t: T, counts: DoorCounts): string {\n const total = counts.on + counts.off + counts.missing + counts.notUsed\n\n if (!total) {\n return String(t('text.activity-catalog-summary-none'))\n }\n\n const parts: [string, number][] = [\n ['on', counts.on],\n ['off', counts.off],\n ['missing', counts.missing],\n ['not-used', counts.notUsed]\n ]\n\n return [\n String(t('text.activity-catalog-summary-total', { count: total })),\n ...parts\n .filter(([, count]) => count)\n .map(([standing, count]) => String(t('text.activity-catalog-summary-part', { ...RAW, standing: t(`text.door-standing-${standing}`), count })))\n ].join(' · ')\n}\n"]}
@@ -1 +1 @@
1
- export default function route(page: string): "activity" | "todo-list" | "approval-pending-list" | "draft-list" | "approval-done-list" | "done-list-calendar" | "pickable-list" | "starter-list" | "reporter-list" | "activity-instance-list" | "activity-catalog" | "work-doors-page" | "activity-thread" | "activity-thread-view" | "activity-approval" | "activity-detail" | "activity-list" | "activity-instance-start" | "activity-instance-search" | "activity-template-list" | "activity-store" | "activity-thread-list" | "activity-approval-list" | "installable-activity-list" | "activity-stats-list" | undefined;
1
+ export default function route(page: string): "todo-list" | "approval-pending-list" | "draft-list" | "approval-done-list" | "done-list-calendar" | "pickable-list" | "starter-list" | "reporter-list" | "activity-instance-list" | "activity-catalog" | "activity" | "activity-detail" | "activity-list" | "activity-instance-start" | "activity-thread" | "activity-thread-view" | "activity-approval" | "activity-instance-search" | "activity-template-list" | "activity-store" | "activity-thread-list" | "activity-approval-list" | "installable-activity-list" | "activity-stats-list" | undefined;
@@ -9,9 +9,6 @@ export default function route(page) {
9
9
  case 'activity-detail':
10
10
  import('./pages/activity-catalog/activity-detail-page.js');
11
11
  return page;
12
- case 'work-doors-page':
13
- import('./pages/work-door/work-doors-page.js');
14
- return page;
15
12
  case 'todo-list':
16
13
  import('./pages/todo/todo-list-page.js');
17
14
  return page;
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../client/route.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,oBAAoB;YACvB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,KAAK,kBAAkB;YACrB,MAAM,CAAC,mDAAmD,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,kDAAkD,CAAC,CAAA;YAC1D,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,sCAAsC,CAAC,CAAA;YAC9C,OAAO,IAAI,CAAA;QAEb,KAAK,WAAW;YACd,MAAM,CAAC,gCAAgC,CAAC,CAAA;YACxC,OAAO,IAAI,CAAA;QAEb,KAAK,uBAAuB;YAC1B,MAAM,CAAC,4CAA4C,CAAC,CAAA;YACpD,OAAO,IAAI,CAAA;QAEb,KAAK,oBAAoB;YACvB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,KAAK,YAAY;YACf,MAAM,CAAC,iCAAiC,CAAC,CAAA;YACzC,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,oCAAoC,CAAC,CAAA;YAC5C,OAAO,IAAI,CAAA;QAEb,KAAK,cAAc;YACjB,MAAM,CAAC,uCAAuC,CAAC,CAAA;YAC/C,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,mDAAmD,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,wCAAwC,CAAC,CAAA;YAChD,OAAO,IAAI,CAAA;QAEb,KAAK,UAAU;YACb,MAAM,CAAC,mCAAmC,CAAC,CAAA;YAC3C,OAAO,IAAI,CAAA;QAEb,KAAK,yBAAyB;YAC5B,MAAM,CAAC,2DAA2D,CAAC,CAAA;YACnE,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,iDAAiD,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;QAEb,KAAK,sBAAsB;YACzB,MAAM,CAAC,sDAAsD,CAAC,CAAA;YAC9D,OAAO,IAAI,CAAA;QAEb,KAAK,mBAAmB;YACtB,MAAM,CAAC,qDAAqD,CAAC,CAAA;YAC7D,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,0DAA0D,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;QAEb,KAAK,0BAA0B;YAC7B,MAAM,CAAC,4DAA4D,CAAC,CAAA;YACpE,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,0DAA0D,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;QAEb,KAAK,gBAAgB;YACnB,MAAM,CAAC,+CAA+C,CAAC,CAAA;YACvD,OAAO,IAAI,CAAA;QAEb,KAAK,sBAAsB;YACzB,MAAM,CAAC,sDAAsD,CAAC,CAAA;YAC9D,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,uDAAuD,CAAC,CAAA;YAC/D,OAAO,IAAI,CAAA;QAEb,KAAK,2BAA2B;YAC9B,MAAM,CAAC,6DAA6D,CAAC,CAAA;YACrE,OAAO,IAAI,CAAA;QAEb,KAAK,qBAAqB;YACxB,MAAM,CAAC,iDAAiD,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC","sourcesContent":["export default function route(page: string) {\n switch (page) {\n case 'done-list-calendar':\n import('./pages/todo/done-list-calendar-page.js')\n return page\n\n case 'activity-catalog':\n import('./pages/activity-catalog/activity-catalog-page.js')\n return page\n\n case 'activity-detail':\n import('./pages/activity-catalog/activity-detail-page.js')\n return page\n\n case 'work-doors-page':\n import('./pages/work-door/work-doors-page.js')\n return page\n\n case 'todo-list':\n import('./pages/todo/todo-list-page.js')\n return page\n\n case 'approval-pending-list':\n import('./pages/todo/approval-pending-list-page.js')\n return page\n\n case 'approval-done-list':\n import('./pages/todo/approval-done-list-page.js')\n return page\n\n case 'draft-list':\n import('./pages/todo/draft-list-page.js')\n return page\n\n case 'pickable-list':\n import('./pages/todo/pickable-list-page.js')\n return page\n\n case 'starter-list':\n import('./pages/activity/starter-list-page.js')\n return page\n\n case 'reporter-list':\n import('./pages/activity-supervisor/reporter-list-page.js')\n return page\n\n case 'activity-list':\n import('./pages/activity/activity-list-page.js')\n return page\n\n case 'activity':\n import('./pages/activity/activity-page.js')\n return page\n\n case 'activity-instance-start':\n import('./pages/activity-instance/activity-instance-start-page.js')\n return page\n\n case 'activity-thread':\n import('./pages/activity-thread/activity-thread-page.js')\n return page\n\n case 'activity-thread-view':\n import('./pages/activity-thread/activity-thread-view-page.js')\n return page\n\n case 'activity-approval':\n import('./pages/activity-approval/activity-approval-page.js')\n return page\n\n case 'activity-instance-list':\n import('./pages/activity-instance/activity-instance-list-page.js')\n return page\n\n case 'activity-instance-search':\n import('./pages/activity-instance/activity-instance-search-page.js')\n return page\n\n case 'activity-template-list':\n import('./pages/activity-template/activity-template-list-page.js')\n return page\n\n case 'activity-store':\n import('./pages/activity-store/activity-store-page.js')\n return page\n\n case 'activity-thread-list':\n import('./pages/activity-thread/activity-thread-list-page.js')\n return page\n\n case 'activity-approval-list':\n import('./pages/activity-approval/activity-approval-list-page')\n return page\n\n case 'installable-activity-list':\n import('./pages/installable-activity/installable-activity-list-page')\n return page\n\n case 'activity-stats-list':\n import('./pages/activity-stats/activity-stats-list-page')\n return page\n }\n}\n"]}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../client/route.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,oBAAoB;YACvB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,KAAK,kBAAkB;YACrB,MAAM,CAAC,mDAAmD,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,kDAAkD,CAAC,CAAA;YAC1D,OAAO,IAAI,CAAA;QAEb,KAAK,WAAW;YACd,MAAM,CAAC,gCAAgC,CAAC,CAAA;YACxC,OAAO,IAAI,CAAA;QAEb,KAAK,uBAAuB;YAC1B,MAAM,CAAC,4CAA4C,CAAC,CAAA;YACpD,OAAO,IAAI,CAAA;QAEb,KAAK,oBAAoB;YACvB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,KAAK,YAAY;YACf,MAAM,CAAC,iCAAiC,CAAC,CAAA;YACzC,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,oCAAoC,CAAC,CAAA;YAC5C,OAAO,IAAI,CAAA;QAEb,KAAK,cAAc;YACjB,MAAM,CAAC,uCAAuC,CAAC,CAAA;YAC/C,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,mDAAmD,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QAEb,KAAK,eAAe;YAClB,MAAM,CAAC,wCAAwC,CAAC,CAAA;YAChD,OAAO,IAAI,CAAA;QAEb,KAAK,UAAU;YACb,MAAM,CAAC,mCAAmC,CAAC,CAAA;YAC3C,OAAO,IAAI,CAAA;QAEb,KAAK,yBAAyB;YAC5B,MAAM,CAAC,2DAA2D,CAAC,CAAA;YACnE,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,iDAAiD,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;QAEb,KAAK,sBAAsB;YACzB,MAAM,CAAC,sDAAsD,CAAC,CAAA;YAC9D,OAAO,IAAI,CAAA;QAEb,KAAK,mBAAmB;YACtB,MAAM,CAAC,qDAAqD,CAAC,CAAA;YAC7D,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,0DAA0D,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;QAEb,KAAK,0BAA0B;YAC7B,MAAM,CAAC,4DAA4D,CAAC,CAAA;YACpE,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,0DAA0D,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;QAEb,KAAK,gBAAgB;YACnB,MAAM,CAAC,+CAA+C,CAAC,CAAA;YACvD,OAAO,IAAI,CAAA;QAEb,KAAK,sBAAsB;YACzB,MAAM,CAAC,sDAAsD,CAAC,CAAA;YAC9D,OAAO,IAAI,CAAA;QAEb,KAAK,wBAAwB;YAC3B,MAAM,CAAC,uDAAuD,CAAC,CAAA;YAC/D,OAAO,IAAI,CAAA;QAEb,KAAK,2BAA2B;YAC9B,MAAM,CAAC,6DAA6D,CAAC,CAAA;YACrE,OAAO,IAAI,CAAA;QAEb,KAAK,qBAAqB;YACxB,MAAM,CAAC,iDAAiD,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC","sourcesContent":["export default function route(page: string) {\n switch (page) {\n case 'done-list-calendar':\n import('./pages/todo/done-list-calendar-page.js')\n return page\n\n case 'activity-catalog':\n import('./pages/activity-catalog/activity-catalog-page.js')\n return page\n\n case 'activity-detail':\n import('./pages/activity-catalog/activity-detail-page.js')\n return page\n\n case 'todo-list':\n import('./pages/todo/todo-list-page.js')\n return page\n\n case 'approval-pending-list':\n import('./pages/todo/approval-pending-list-page.js')\n return page\n\n case 'approval-done-list':\n import('./pages/todo/approval-done-list-page.js')\n return page\n\n case 'draft-list':\n import('./pages/todo/draft-list-page.js')\n return page\n\n case 'pickable-list':\n import('./pages/todo/pickable-list-page.js')\n return page\n\n case 'starter-list':\n import('./pages/activity/starter-list-page.js')\n return page\n\n case 'reporter-list':\n import('./pages/activity-supervisor/reporter-list-page.js')\n return page\n\n case 'activity-list':\n import('./pages/activity/activity-list-page.js')\n return page\n\n case 'activity':\n import('./pages/activity/activity-page.js')\n return page\n\n case 'activity-instance-start':\n import('./pages/activity-instance/activity-instance-start-page.js')\n return page\n\n case 'activity-thread':\n import('./pages/activity-thread/activity-thread-page.js')\n return page\n\n case 'activity-thread-view':\n import('./pages/activity-thread/activity-thread-view-page.js')\n return page\n\n case 'activity-approval':\n import('./pages/activity-approval/activity-approval-page.js')\n return page\n\n case 'activity-instance-list':\n import('./pages/activity-instance/activity-instance-list-page.js')\n return page\n\n case 'activity-instance-search':\n import('./pages/activity-instance/activity-instance-search-page.js')\n return page\n\n case 'activity-template-list':\n import('./pages/activity-template/activity-template-list-page.js')\n return page\n\n case 'activity-store':\n import('./pages/activity-store/activity-store-page.js')\n return page\n\n case 'activity-thread-list':\n import('./pages/activity-thread/activity-thread-list-page.js')\n return page\n\n case 'activity-approval-list':\n import('./pages/activity-approval/activity-approval-list-page')\n return page\n\n case 'installable-activity-list':\n import('./pages/installable-activity/installable-activity-list-page')\n return page\n\n case 'activity-stats-list':\n import('./pages/activity-stats/activity-stats-list-page')\n return page\n }\n}\n"]}