@things-factory/worklist 10.1.36 → 10.1.38

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 (133) hide show
  1. package/dist-client/components/activity-instance-preview.js +2 -13
  2. package/dist-client/components/activity-instance-preview.js.map +1 -1
  3. package/dist-client/components/activity-thread-timeline.d.ts +2 -2
  4. package/dist-client/components/can-pick.d.ts +15 -0
  5. package/dist-client/components/can-pick.js +16 -0
  6. package/dist-client/components/can-pick.js.map +1 -0
  7. package/dist-client/index.d.ts +1 -0
  8. package/dist-client/index.js +1 -0
  9. package/dist-client/index.js.map +1 -1
  10. package/dist-client/pages/activity-catalog/activity-catalog-page.js +50 -40
  11. package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
  12. package/dist-client/pages/activity-catalog/activity-detail-actions.d.ts +34 -0
  13. package/dist-client/pages/activity-catalog/activity-detail-actions.js +18 -0
  14. package/dist-client/pages/activity-catalog/activity-detail-actions.js.map +1 -0
  15. package/dist-client/pages/activity-catalog/activity-detail-page.d.ts +68 -0
  16. package/dist-client/pages/activity-catalog/activity-detail-page.js +489 -0
  17. package/dist-client/pages/activity-catalog/activity-detail-page.js.map +1 -0
  18. package/dist-client/pages/activity-catalog/activity-guide.d.ts +16 -0
  19. package/dist-client/pages/activity-catalog/activity-guide.js +5 -0
  20. package/dist-client/pages/activity-catalog/activity-guide.js.map +1 -0
  21. package/dist-client/pages/activity-catalog/activity-panels.d.ts +80 -0
  22. package/dist-client/pages/activity-catalog/activity-panels.js +53 -0
  23. package/dist-client/pages/activity-catalog/activity-panels.js.map +1 -0
  24. package/dist-client/pages/activity-catalog/activity-stage.d.ts +31 -0
  25. package/dist-client/pages/activity-catalog/activity-stage.js +44 -0
  26. package/dist-client/pages/activity-catalog/activity-stage.js.map +1 -0
  27. package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +1 -0
  28. package/dist-client/pages/activity-instance/activity-instance-start-page.js +33 -1
  29. package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -1
  30. package/dist-client/pages/activity-instance/discard-offer.d.ts +11 -0
  31. package/dist-client/pages/activity-instance/discard-offer.js +11 -0
  32. package/dist-client/pages/activity-instance/discard-offer.js.map +1 -0
  33. package/dist-client/pages/activity-thread/activity-thread-view.d.ts +1 -1
  34. package/dist-client/pages/todo/approval-done-list-page.d.ts +5 -1
  35. package/dist-client/pages/todo/approval-done-list-page.js +8 -1
  36. package/dist-client/pages/todo/approval-done-list-page.js.map +1 -1
  37. package/dist-client/pages/todo/approval-pending-list-page.d.ts +5 -1
  38. package/dist-client/pages/todo/approval-pending-list-page.js +8 -1
  39. package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
  40. package/dist-client/pages/todo/done-list-page.d.ts +5 -1
  41. package/dist-client/pages/todo/done-list-page.js +8 -1
  42. package/dist-client/pages/todo/done-list-page.js.map +1 -1
  43. package/dist-client/pages/todo/draft-list-page.d.ts +5 -1
  44. package/dist-client/pages/todo/draft-list-page.js +18 -12
  45. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  46. package/dist-client/pages/todo/list-thumbnail.d.ts +25 -0
  47. package/dist-client/pages/todo/list-thumbnail.js +25 -0
  48. package/dist-client/pages/todo/list-thumbnail.js.map +1 -0
  49. package/dist-client/pages/todo/todo-list-page.d.ts +5 -1
  50. package/dist-client/pages/todo/todo-list-page.js +8 -1
  51. package/dist-client/pages/todo/todo-list-page.js.map +1 -1
  52. package/dist-client/pages/work-door/door-links.d.ts +30 -0
  53. package/dist-client/pages/work-door/door-links.js +30 -0
  54. package/dist-client/pages/work-door/door-links.js.map +1 -0
  55. package/dist-client/pages/work-door/work-doors-page.js +15 -5
  56. package/dist-client/pages/work-door/work-doors-page.js.map +1 -1
  57. package/dist-client/route.d.ts +1 -1
  58. package/dist-client/route.js +3 -0
  59. package/dist-client/route.js.map +1 -1
  60. package/dist-client/tsconfig.tsbuildinfo +1 -1
  61. package/dist-server/controllers/activity-approval/delegate.js +27 -2
  62. package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
  63. package/dist-server/controllers/activity-approval/delegation.d.ts +31 -0
  64. package/dist-server/controllers/activity-approval/delegation.js +31 -0
  65. package/dist-server/controllers/activity-approval/delegation.js.map +1 -0
  66. package/dist-server/controllers/activity-instance/discard-draft.d.ts +22 -0
  67. package/dist-server/controllers/activity-instance/discard-draft.js +54 -0
  68. package/dist-server/controllers/activity-instance/discard-draft.js.map +1 -0
  69. package/dist-server/controllers/activity-read/assert-may-read.d.ts +15 -0
  70. package/dist-server/controllers/activity-read/assert-may-read.js +99 -0
  71. package/dist-server/controllers/activity-read/assert-may-read.js.map +1 -0
  72. package/dist-server/controllers/activity-read/participates.d.ts +41 -0
  73. package/dist-server/controllers/activity-read/participates.js +42 -0
  74. package/dist-server/controllers/activity-read/participates.js.map +1 -0
  75. package/dist-server/controllers/activity-thread/delegate.js +23 -1
  76. package/dist-server/controllers/activity-thread/delegate.js.map +1 -1
  77. package/dist-server/service/activity/activity-mutation.js +1 -0
  78. package/dist-server/service/activity/activity-mutation.js.map +1 -1
  79. package/dist-server/service/activity-approval/activity-approval-query.js +7 -1
  80. package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
  81. package/dist-server/service/activity-approval/activity-approval-subscription.js +2 -11
  82. package/dist-server/service/activity-approval/activity-approval-subscription.js.map +1 -1
  83. package/dist-server/service/activity-instance/activity-instance-mutation.js +12 -20
  84. package/dist-server/service/activity-instance/activity-instance-mutation.js.map +1 -1
  85. package/dist-server/service/activity-instance/activity-instance-query.js +30 -9
  86. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  87. package/dist-server/service/activity-instance/activity-instance-subscription.js +4 -12
  88. package/dist-server/service/activity-instance/activity-instance-subscription.js.map +1 -1
  89. package/dist-server/service/activity-instance/draft-list-states.d.ts +39 -0
  90. package/dist-server/service/activity-instance/draft-list-states.js +51 -0
  91. package/dist-server/service/activity-instance/draft-list-states.js.map +1 -0
  92. package/dist-server/service/activity-instance/index.d.ts +1 -2
  93. package/dist-server/service/activity-instance/index.js +1 -2
  94. package/dist-server/service/activity-instance/index.js.map +1 -1
  95. package/dist-server/service/activity-template/activity-template-mutation.js +6 -0
  96. package/dist-server/service/activity-template/activity-template-mutation.js.map +1 -1
  97. package/dist-server/service/activity-thread/activity-thread-mutation.d.ts +0 -3
  98. package/dist-server/service/activity-thread/activity-thread-mutation.js +0 -19
  99. package/dist-server/service/activity-thread/activity-thread-mutation.js.map +1 -1
  100. package/dist-server/service/activity-thread/activity-thread-query.js +7 -1
  101. package/dist-server/service/activity-thread/activity-thread-query.js.map +1 -1
  102. package/dist-server/service/activity-thread/activity-thread-subscription.js +2 -8
  103. package/dist-server/service/activity-thread/activity-thread-subscription.js.map +1 -1
  104. package/dist-server/service/index.d.ts +2 -2
  105. package/dist-server/service/subscription/subscription-filters.d.ts +36 -0
  106. package/dist-server/service/subscription/subscription-filters.js +41 -0
  107. package/dist-server/service/subscription/subscription-filters.js.map +1 -0
  108. package/dist-server/service/work-door/work-door-declaration.d.ts +15 -0
  109. package/dist-server/service/work-door/work-door-declaration.js +18 -0
  110. package/dist-server/service/work-door/work-door-declaration.js.map +1 -1
  111. package/dist-server/service/work-door/work-door-resolver.d.ts +3 -0
  112. package/dist-server/service/work-door/work-door-resolver.js +21 -1
  113. package/dist-server/service/work-door/work-door-resolver.js.map +1 -1
  114. package/dist-server/tsconfig.tsbuildinfo +1 -1
  115. package/package.json +10 -10
  116. package/tests/delegate-approval.test.ts +112 -0
  117. package/tests/discard-draft.test.ts +145 -0
  118. package/tests/may-read-case.test.ts +166 -0
  119. package/tests/open-doors.test.ts +274 -0
  120. package/tests/published-shape.test.ts +85 -0
  121. package/tests/work-door-not-used-refuse.test.ts +110 -0
  122. package/things-factory.config.js +1 -0
  123. package/translations/en.json +32 -3
  124. package/translations/ja.json +33 -4
  125. package/translations/ko.json +33 -4
  126. package/translations/ms.json +32 -3
  127. package/translations/zh.json +33 -4
  128. package/dist-server/service/activity-instance/activity-instance-history-query.d.ts +0 -12
  129. package/dist-server/service/activity-instance/activity-instance-history-query.js +0 -79
  130. package/dist-server/service/activity-instance/activity-instance-history-query.js.map +0 -1
  131. package/dist-server/service/activity-instance/activity-instance-history-type.d.ts +0 -5
  132. package/dist-server/service/activity-instance/activity-instance-history-type.js +0 -21
  133. package/dist-server/service/activity-instance/activity-instance-history-type.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"draft-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/draft-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '../../components/activity-starter-form.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { OxPopup } from '@operato/popup'\n\nimport { ActivityStartingTypes } from '../../types/types.js'\n\nimport { subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('draft-list-page')\nexport class DraftListPage extends localize(i18next)(PageView) { static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n .header { grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n get context() { return { title: i18next.t('title.draft list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: { handler: () => { this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/draft-list-page',\n actions: []\n }\n }\n\n render() { const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist class=\"page-fill\" .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle) { this.gristConfig = { list: { thumbnail: 'thumbnail',\n fields: ['name', 'description'],\n details: ['createdAt', 'due']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 375\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n { type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: { editable: false,\n options: [\n { display: i18next.t('label.activity-state-draft'), value: 'draft' },\n { display: i18next.t('label.activity-state-posted'), value: 'posted' },\n { display: i18next.t('label.activity-state-unassigned'), value: 'unassigned' },\n { display: i18next.t('label.activity-state-assigned'), value: 'assigned' },\n { display: i18next.t('label.activity-state-started'), value: 'started' },\n { display: i18next.t('label.activity-state-pending'), value: 'pending' },\n { display: i18next.t('label.activity-state-escalated'), value: 'escalated' },\n { display: i18next.t('label.activity-state-ended'), value: 'ended' },\n { display: i18next.t('label.activity-state-aborted'), value: 'aborted' }\n ]\n },\n width: 85\n },\n { type: 'select',\n name: 'startingType',\n label: true,\n header: i18next.t('field.wl-starting-type'),\n record: { editable: false,\n options: ActivityStartingTypes\n },\n width: 90\n },\n { type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false\n },\n sortable: true,\n width: 180\n },\n { type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { if (!record.id) { return\n }\n\n this.openActivityInstanceStart(record)\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) { if (this.active) { this.grist?.fetch()\n }\n }\n\n async fetchHandler({ page, limit, sortings = [], filters = [] }: FetchOption) { const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id\n name\n description\n priority\n state\n input\n output\n refBy\n activity { id\n startingType\n }\n activityType\n assignees { type\n value\n assignee { id\n name\n description\n controlNo\n }\n }\n approvalLine { type\n value\n participation\n approver { id\n name\n description\n controlNo\n }\n }\n threadsMin\n threadsMax\n uiType\n uiSource\n dueAt\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n }\n total\n }\n }\n `,\n variables: { filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n return { total: response.data.responses.total || 0,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n openActivityInstanceStart(activityInstance) { navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`)\n }\n}\n"]}
1
+ {"version":3,"file":"draft-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/draft-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '../../components/activity-starter-form.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { listWithThumbnail } from './list-thumbnail.js'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { OxPopup } from '@operato/popup'\n\nimport { ActivityStartingTypes } from '../../types/types.js'\nimport { ActivityInstanceStatus } from '../../types/activity-instance.js'\n\nimport { subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('draft-list-page')\nexport class DraftListPage extends localize(i18next)(PageView) { static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n .header { grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n get context() { return { title: i18next.t('title.draft list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: { handler: () => { this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/draft-list-page',\n actions: []\n }\n }\n\n render() { const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist class=\"page-fill\" .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle) { this.gristConfig = { list: { thumbnail: 'thumbnail',\n fields: ['name', 'description'],\n details: ['createdAt', 'due']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 375\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n { type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: { editable: false,\n /*\n * 이 목록은 **인스턴스**를 보인다. 고를 수 있는 상태도 인스턴스의 것이어야 한다 — 전에는\n * 스레드 상태 posted · escalated 가 섞여 있었고 issued 가 빠져 있었다. 서버는 인스턴스에\n * 없는 이름을 거절하므로 그 둘을 고르면 오류가 났다.\n */\n options: Object.values(ActivityInstanceStatus).map(value => ({\n display: i18next.t(`label.activity-state-${value}`),\n value\n }))\n },\n width: 85\n },\n { type: 'select',\n name: 'startingType',\n label: true,\n header: i18next.t('field.wl-starting-type'),\n record: { editable: false,\n options: ActivityStartingTypes\n },\n width: 90\n },\n { type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false\n },\n sortable: true,\n width: 180\n },\n { type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { if (!record.id) { return\n }\n\n this.openActivityInstanceStart(record)\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) { if (this.active) { this.grist?.fetch()\n }\n }\n\n /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */\n async fetchHandler(options: FetchOption) {\n const fetched = await this.fetchRows(options)\n\n this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || [])\n\n return fetched\n }\n\n async fetchRows({ page, limit, sortings = [], filters = [] }: FetchOption) { const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id\n name\n description\n priority\n state\n input\n output\n refBy\n activity { id\n startingType\n }\n activityType\n assignees { type\n value\n assignee { id\n name\n description\n controlNo\n }\n }\n approvalLine { type\n value\n participation\n approver { id\n name\n description\n controlNo\n }\n }\n threadsMin\n threadsMax\n uiType\n uiSource\n dueAt\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n }\n total\n }\n }\n `,\n variables: { filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n return { total: response.data.responses.total || 0,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n openActivityInstanceStart(activityInstance) { navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`)\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Whether a worklist card shows a thumbnail slot - decided by what the list actually read.
3
+ *
4
+ * The thumbnail is the activity definition's picture. Some products give their activities one
5
+ * (dataset, accounting); plant, warehouse and twin give none. The card keeps a slot even when a
6
+ * record has no picture, so that cards in one list line up (data-grist record-card). On a list where
7
+ * no record has a picture, that is an empty 140px block leading every card - in the approver's inbox
8
+ * it pushed what is being approved below the fold on a phone.
9
+ *
10
+ * So the slot is kept when any record on the page has a picture, and dropped when none has.
11
+ */
12
+ type Config = {
13
+ list?: {
14
+ thumbnail?: string;
15
+ } & Record<string, unknown>;
16
+ } & Record<string, unknown>;
17
+ export declare const THUMBNAIL_COLUMN = "thumbnail";
18
+ export declare function anyThumbnail(records: readonly {
19
+ thumbnail?: unknown;
20
+ }[] | undefined): boolean;
21
+ /** The same config object when nothing changes, so the grist is not handed a new config for nothing. */
22
+ export declare function listWithThumbnail<T extends Config | undefined>(config: T, records: readonly {
23
+ thumbnail?: unknown;
24
+ }[]): T;
25
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Whether a worklist card shows a thumbnail slot - decided by what the list actually read.
3
+ *
4
+ * The thumbnail is the activity definition's picture. Some products give their activities one
5
+ * (dataset, accounting); plant, warehouse and twin give none. The card keeps a slot even when a
6
+ * record has no picture, so that cards in one list line up (data-grist record-card). On a list where
7
+ * no record has a picture, that is an empty 140px block leading every card - in the approver's inbox
8
+ * it pushed what is being approved below the fold on a phone.
9
+ *
10
+ * So the slot is kept when any record on the page has a picture, and dropped when none has.
11
+ */
12
+ export const THUMBNAIL_COLUMN = 'thumbnail';
13
+ export function anyThumbnail(records) {
14
+ return (records || []).some(one => typeof one?.thumbnail === 'string' && one.thumbnail !== '');
15
+ }
16
+ /** The same config object when nothing changes, so the grist is not handed a new config for nothing. */
17
+ export function listWithThumbnail(config, records) {
18
+ if (!config?.list)
19
+ return config;
20
+ const wanted = anyThumbnail(records) ? THUMBNAIL_COLUMN : undefined;
21
+ if (config.list.thumbnail === wanted)
22
+ return config;
23
+ return { ...config, list: { ...config.list, thumbnail: wanted } };
24
+ }
25
+ //# sourceMappingURL=list-thumbnail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-thumbnail.js","sourceRoot":"","sources":["../../../client/pages/todo/list-thumbnail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAA;AAE3C,MAAM,UAAU,YAAY,CAAC,OAAuD;IAClF,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,EAAE,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAA;AAChG,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,iBAAiB,CAA+B,MAAS,EAAE,OAA2C;IACpH,IAAI,CAAC,MAAM,EAAE,IAAI;QAAE,OAAO,MAAM,CAAA;IAEhC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAA;IAEnE,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,MAAM;QAAE,OAAO,MAAM,CAAA;IAEnD,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAO,CAAA;AACxE,CAAC","sourcesContent":["/**\n * Whether a worklist card shows a thumbnail slot - decided by what the list actually read.\n *\n * The thumbnail is the activity definition's picture. Some products give their activities one\n * (dataset, accounting); plant, warehouse and twin give none. The card keeps a slot even when a\n * record has no picture, so that cards in one list line up (data-grist record-card). On a list where\n * no record has a picture, that is an empty 140px block leading every card - in the approver's inbox\n * it pushed what is being approved below the fold on a phone.\n *\n * So the slot is kept when any record on the page has a picture, and dropped when none has.\n */\n\ntype Config = { list?: { thumbnail?: string } & Record<string, unknown> } & Record<string, unknown>\n\nexport const THUMBNAIL_COLUMN = 'thumbnail'\n\nexport function anyThumbnail(records: readonly { thumbnail?: unknown }[] | undefined): boolean {\n return (records || []).some(one => typeof one?.thumbnail === 'string' && one.thumbnail !== '')\n}\n\n/** The same config object when nothing changes, so the grist is not handed a new config for nothing. */\nexport function listWithThumbnail<T extends Config | undefined>(config: T, records: readonly { thumbnail?: unknown }[]): T {\n if (!config?.list) return config\n\n const wanted = anyThumbnail(records) ? THUMBNAIL_COLUMN : undefined\n\n if (config.list.thumbnail === wanted) return config\n\n return { ...config, list: { ...config.list, thumbnail: wanted } } as T\n}\n"]}
@@ -30,7 +30,11 @@ export declare class TodoListPage extends TodoListPage_base {
30
30
  render(): import("lit-html").TemplateResult<1>;
31
31
  pageInitialized(lifecycle: any): Promise<void>;
32
32
  pageUpdated(changes: any, lifecycle: any, changedBefore: any): Promise<void>;
33
- fetchHandler({ page, limit, sortings, filters }: FetchOption): Promise<{
33
+ fetchHandler(options: FetchOption): Promise<{
34
+ total: any;
35
+ records: any;
36
+ }>;
37
+ fetchRows({ page, limit, sortings, filters }: FetchOption): Promise<{
34
38
  total: any;
35
39
  records: any;
36
40
  }>;
@@ -10,6 +10,7 @@ import { client } from '@operato/graphql';
10
10
  import { dueSoonChip, dueSoonFilters, importantChip, importantFilters } from '../../chip-filters.js';
11
11
  import { i18next, localize } from '@operato/i18n';
12
12
  import { navigate, PageView } from '@operato/shell';
13
+ import { listWithThumbnail } from './list-thumbnail.js';
13
14
  import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
14
15
  import { adjustFilters, isMobileDevice } from '@operato/utils';
15
16
  import { p13n } from '@operato/p13n';
@@ -278,7 +279,13 @@ let TodoListPage = class TodoListPage extends p13n(localize(i18next)(PageView))
278
279
  this.grist?.fetch();
279
280
  }
280
281
  }
281
- async fetchHandler({ page, limit, sortings = [], filters = [] }) {
282
+ /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */
283
+ async fetchHandler(options) {
284
+ const fetched = await this.fetchRows(options);
285
+ this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || []);
286
+ return fetched;
287
+ }
288
+ async fetchRows({ page, limit, sortings = [], filters = [] }) {
282
289
  if (this.filters?.includes('important')) {
283
290
  filters = adjustFilters(filters, importantFilters());
284
291
  }
@@ -1 +1 @@
1
- {"version":3,"file":"todo-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/todo-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/input/ox-input-select-buttons.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { asyncReplace } from 'lit/directives/async-replace.js'\nimport { DataGrist, FetchOption, getRenderer } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { dueSoonChip, dueSoonFilters, importantChip, importantFilters } from '../../chip-filters.js'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice, sleep } from '@operato/utils'\n\nimport { p13n } from '@operato/p13n'\n\nimport { dueCell, priorityCell, subjectCell } from '../../activity-cells.js'\n\nimport { ActivityThreadStatus } from '../../types/activity-thread.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('todo-list-page')\nexport class TodoListPage extends p13n(localize(i18next)(PageView)) {\n static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n /*\n * 제목은 헤드룸에 두지 않는다.\n *\n * MDI 를 켜면 제목이 이미 두 곳에 있다 — 헤더 바와 탭. 여기에 또 두면 한 화면에 같은 글자가\n * 셋이 된다. 그래서 표준 배치의 title 줄을 쓰지 않고 한 줄로 둔다.\n */\n .header {\n grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n @state() gristConfig?: any\n @state() filters?: string[]\n\n get context() {\n return {\n title: i18next.t('title.todo list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/todo-list-page',\n actions: []\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist class=\"page-fill\"\n .mode=${mode}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n .personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')!}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n <ox-input-select-buttons\n .value=${this.filters}\n .options=${[\n importantChip(),\n dueSoonChip(),\n { display: i18next.t('label.filter-proceeding'), value: 'proceeding' },\n { display: i18next.t('label.filter-pending-approval'), value: 'pending-approval' }\n ]}\n @change=${(e: CustomEvent) => {\n this.filters = (e.currentTarget as any)?.value\n this.grist.fetch()\n }}\n ></ox-input-select-buttons>\n <!-- <ox-filters-form class=\"filter\" autofocus without-search></ox-filters-form> -->\n </div>\n\n </div>\n\n <ox-grist-personalizer slot=\"setting\"></ox-grist-personalizer>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle) {\n this.gristConfig = {\n list: { thumbnail: 'thumbnail', fields: ['name', 'description'], details: ['createdAt', 'due'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence', fixed: true },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n fixed: true,\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 250\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n {\n type: 'resource-object',\n name: 'creator',\n header: i18next.t('field.wl-drafter'),\n record: { editable: false },\n sortable: true,\n width: 85\n },\n {\n type: 'datetime',\n name: 'dueAt',\n header: i18next.t('field.wl-due'),\n record: {\n editable: false,\n renderer: dueCell(() => this.active)\n },\n sortable: true,\n width: 180\n },\n {\n type: 'number',\n name: 'priority',\n header: i18next.t('field.wl-priority'),\n record: {\n editable: false,\n align: 'center',\n renderer: priorityCell()\n },\n sortable: true,\n width: 70\n },\n {\n type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: {\n editable: false,\n align: 'center',\n options: [\n { display: i18next.t('label.activity-state-unassigned'), value: 'unassigned' },\n { display: i18next.t('label.activity-state-assigned'), value: 'assigned' },\n { display: i18next.t('label.activity-state-started'), value: 'started' },\n { display: i18next.t('label.activity-state-delegated'), value: 'delegated' },\n { display: i18next.t('label.activity-state-submitted'), value: 'submitted' },\n { display: i18next.t('label.activity-state-escalated'), value: 'escalated' },\n { display: i18next.t('label.activity-state-rejected'), value: 'rejected' },\n { display: i18next.t('label.activity-state-ended'), value: 'ended' },\n { display: i18next.t('label.activity-state-aborted'), value: 'aborted' }\n ]\n },\n width: 85\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.wl-submitted-at'),\n record: { editable: false },\n sortable: true,\n filter: false,\n width: 180\n },\n {\n type: 'string',\n name: 'uiSource',\n header: i18next.t('field.wl-view-source'),\n record: {\n editable: false,\n renderer: function (value, column, record, rowIndex, field) {\n const { uiType, uiSource } = record.activity || {}\n var type = uiType !== 'board' ? 'string' : 'board'\n return getRenderer(type)(uiSource, column, record, rowIndex, field)\n }\n },\n width: 140,\n hidden: true\n },\n {\n type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: {\n appendable: false,\n editable: false,\n handlers: {\n click: (columns, data, column, record, rowIndex) => {\n this.openActivityThread(record)\n }\n }\n },\n sorters: [{ name: 'dueAt', desc: false }],\n pagination: { limit: 50, pages: [20, 50, 100, 500] }\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (this.active) {\n this.grist?.fetch()\n }\n }\n\n async fetchHandler({ page, limit, sortings = [], filters = [] }: FetchOption) {\n if (this.filters?.includes('important')) {\n filters = adjustFilters(filters, importantFilters())\n }\n\n if (this.filters?.includes('due')) {\n filters = adjustFilters(filters, dueSoonFilters())\n }\n\n if (this.filters?.includes('proceeding')) {\n filters = adjustFilters(filters, [{ name: 'state', operator: 'eq', value: ActivityThreadStatus.Started }])\n }\n\n if (this.filters?.includes('pending-approval')) {\n filters = adjustFilters(filters, [\n {\n name: 'state',\n operator: 'in',\n value: [ActivityThreadStatus.Rejected, ActivityThreadStatus.Submitted, ActivityThreadStatus.Escalated]\n }\n ])\n }\n\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: todoList(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n activityInstance {\n activityId: id\n name\n description\n priority\n input\n refBy\n activityType\n uiType\n uiSource\n thumbnail\n updatedAt\n createdAt\n creator {\n id\n name\n }\n }\n state\n output\n dueAt\n assignedAt\n }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings }\n })\n\n return {\n total: response.data.responses.total || 0,\n records: (response.data.responses.items || []).map(item => {\n return {\n id: item.id,\n state: item.state,\n output: item.output,\n dueAt: item.dueAt,\n assignedAt: item.assignedAt,\n ...item.activityInstance\n }\n })\n }\n }\n\n openActivityThread(activityThread) {\n navigate(`activity-thread/${activityThread.id}?title=${activityThread.name}`)\n }\n\n}\n"]}
1
+ {"version":3,"file":"todo-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/todo-list-page.ts"],"names":[],"mappings":";AAAA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,wCAAwC,CAAA;AAC/C,OAAO,2CAA2C,CAAA;AAElD,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE,OAAO,EAAE,SAAS,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACpG,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC/G,OAAO,EAAE,aAAa,EAAE,cAAc,EAAS,MAAM,gBAAgB,CAAA;AAErE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEpC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAA;AAErE,MAAM,GAAG,GAAG,EAAE,CAAA;AACd,MAAM,IAAI,GAAG,EAAE,GAAG,GAAG,CAAA;AACrB,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAA;AAGd,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC;IAA5D;;QA4CuB,SAAI,GAA6B,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IAwTjG,CAAC;aAnWQ,WAAM,GAAG;QACd,qEAAqE;QACrE,qBAAqB;QACrB,eAAe;QACf,iBAAiB;QACjB,kBAAkB;QAClB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkCF;KACF,AAzCY,CAyCZ;IASD,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC;YACnC;;;;;;;;;;;eAWG;YACH;;;;;;;;eAQG;YACH,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,MAAc,EAAE,EAAE;oBAC1B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAChC,CAAC;gBACD,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;aACpC;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,GAAG,EAAE;oBACZ,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAA;gBAC7B,CAAC;aACF;YACD,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,EAAE;SACZ,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAE9D,OAAO,IAAI,CAAA;;gBAEC,IAAI;kBACF,IAAI,CAAC,WAAW;wBACV,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;kCAClB,IAAI,CAAC,yBAAyB,CAAC,UAAU,CAAE;;;;;;;uBAOtD,IAAI,CAAC,OAAO;yBACV;YACT,aAAa,EAAE;YACf,WAAW,EAAE;YACb,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;YACtE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE;SACnF;wBACS,CAAC,CAAc,EAAE,EAAE;YAC3B,IAAI,CAAC,OAAO,GAAI,CAAC,CAAC,aAAqB,EAAE,KAAK,CAAA;YAC9C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;;;;;;;;;KASV,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,SAAS;QAC7B,IAAI,CAAC,WAAW,GAAG;YACjB,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE;YAChG,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE;gBACvD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;oBACrC,KAAK,EAAE,IAAI;oBACX,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,WAAW,EAAE;qBACxB;oBACD,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE;;;;;;;;;;uBAUG;oBACH,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,aAAa;oBACnB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;oBACtC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,QAAQ;oBAChB,MAAM,EAAE,IAAI;iBACb;gBACD;oBACE,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;oBACrC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,EAAE;iBACV;gBACD;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;oBACjC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;qBACrC;oBACD,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;oBACtC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,KAAK,EAAE,QAAQ;wBACf,QAAQ,EAAE,YAAY,EAAE;qBACzB;oBACD,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,EAAE;iBACV;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;oBACnC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,KAAK,EAAE,QAAQ;wBACf,OAAO,EAAE;4BACP,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;4BAC9E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE;4BAC1E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE;4BACxE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE;4BAC5E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE;4BAC5E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE;4BAC5E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE;4BAC1E,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE;4BACpE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE;yBACzE;qBACF;oBACD,KAAK,EAAE,EAAE;iBACV;gBACD;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;oBAC1C,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,KAAK;oBACb,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC;oBACzC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,UAAU,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK;4BACxD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAA;4BAClD,IAAI,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;4BAClD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;wBACrE,CAAC;qBACF;oBACD,KAAK,EAAE,GAAG;oBACV,MAAM,EAAE,IAAI;iBACb;gBACD;oBACE,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC;oBACpC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,IAAI;iBACb;aACF;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,KAAK;gBACf,QAAQ,EAAE;oBACR,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;wBACjD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;oBACjC,CAAC;iBACF;aACF;YACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YACzC,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE;SACrD,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa;QACjD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,YAAY,CAAC,OAAoB;QACrC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAE7C,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAA;QAE9E,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAe;QACvE,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAA;QACtD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,CAAA;QACpD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,oBAAoB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC5G,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC/C,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE;gBAC/B;oBACE,IAAI,EAAE,OAAO;oBACb,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,CAAC,oBAAoB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,SAAS,EAAE,oBAAoB,CAAC,SAAS,CAAC;iBACvG;aACF,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BT;YACD,SAAS,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE;SAC9D,CAAC,CAAA;QAEF,OAAO;YACL,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;YACzC,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBACxD,OAAO;oBACL,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,GAAG,IAAI,CAAC,gBAAgB;iBACzB,CAAA;YACH,CAAC,CAAC;SACH,CAAA;IACH,CAAC;IAED,kBAAkB,CAAC,cAAc;QAC/B,QAAQ,CAAC,mBAAmB,cAAc,CAAC,EAAE,UAAU,cAAc,CAAC,IAAI,EAAE,CAAC,CAAA;IAC/E,CAAC;;AAtT2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0CAAoE;AAE5E;IAAlB,KAAK,CAAC,UAAU,CAAC;8BAAS,SAAS;2CAAA;AAE3B;IAAR,KAAK,EAAE;;iDAAkB;AACjB;IAAR,KAAK,EAAE;;6CAAmB;AAjDhB,YAAY;IADxB,aAAa,CAAC,gBAAgB,CAAC;GACnB,YAAY,CAoWxB","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/input/ox-input-select-buttons.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { asyncReplace } from 'lit/directives/async-replace.js'\nimport { DataGrist, FetchOption, getRenderer } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { dueSoonChip, dueSoonFilters, importantChip, importantFilters } from '../../chip-filters.js'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { listWithThumbnail } from './list-thumbnail.js'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice, sleep } from '@operato/utils'\n\nimport { p13n } from '@operato/p13n'\n\nimport { dueCell, priorityCell, subjectCell } from '../../activity-cells.js'\n\nimport { ActivityThreadStatus } from '../../types/activity-thread.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('todo-list-page')\nexport class TodoListPage extends p13n(localize(i18next)(PageView)) {\n static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n /*\n * 제목은 헤드룸에 두지 않는다.\n *\n * MDI 를 켜면 제목이 이미 두 곳에 있다 — 헤더 바와 탭. 여기에 또 두면 한 화면에 같은 글자가\n * 셋이 된다. 그래서 표준 배치의 title 줄을 쓰지 않고 한 줄로 둔다.\n */\n .header {\n grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n @state() gristConfig?: any\n @state() filters?: string[]\n\n get context() {\n return {\n title: i18next.t('title.todo list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/todo-list-page',\n actions: []\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist class=\"page-fill\"\n .mode=${mode}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n .personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')!}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n <ox-input-select-buttons\n .value=${this.filters}\n .options=${[\n importantChip(),\n dueSoonChip(),\n { display: i18next.t('label.filter-proceeding'), value: 'proceeding' },\n { display: i18next.t('label.filter-pending-approval'), value: 'pending-approval' }\n ]}\n @change=${(e: CustomEvent) => {\n this.filters = (e.currentTarget as any)?.value\n this.grist.fetch()\n }}\n ></ox-input-select-buttons>\n <!-- <ox-filters-form class=\"filter\" autofocus without-search></ox-filters-form> -->\n </div>\n\n </div>\n\n <ox-grist-personalizer slot=\"setting\"></ox-grist-personalizer>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle) {\n this.gristConfig = {\n list: { thumbnail: 'thumbnail', fields: ['name', 'description'], details: ['createdAt', 'due'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence', fixed: true },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n fixed: true,\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 250\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n {\n type: 'resource-object',\n name: 'creator',\n header: i18next.t('field.wl-drafter'),\n record: { editable: false },\n sortable: true,\n width: 85\n },\n {\n type: 'datetime',\n name: 'dueAt',\n header: i18next.t('field.wl-due'),\n record: {\n editable: false,\n renderer: dueCell(() => this.active)\n },\n sortable: true,\n width: 180\n },\n {\n type: 'number',\n name: 'priority',\n header: i18next.t('field.wl-priority'),\n record: {\n editable: false,\n align: 'center',\n renderer: priorityCell()\n },\n sortable: true,\n width: 70\n },\n {\n type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: {\n editable: false,\n align: 'center',\n options: [\n { display: i18next.t('label.activity-state-unassigned'), value: 'unassigned' },\n { display: i18next.t('label.activity-state-assigned'), value: 'assigned' },\n { display: i18next.t('label.activity-state-started'), value: 'started' },\n { display: i18next.t('label.activity-state-delegated'), value: 'delegated' },\n { display: i18next.t('label.activity-state-submitted'), value: 'submitted' },\n { display: i18next.t('label.activity-state-escalated'), value: 'escalated' },\n { display: i18next.t('label.activity-state-rejected'), value: 'rejected' },\n { display: i18next.t('label.activity-state-ended'), value: 'ended' },\n { display: i18next.t('label.activity-state-aborted'), value: 'aborted' }\n ]\n },\n width: 85\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.wl-submitted-at'),\n record: { editable: false },\n sortable: true,\n filter: false,\n width: 180\n },\n {\n type: 'string',\n name: 'uiSource',\n header: i18next.t('field.wl-view-source'),\n record: {\n editable: false,\n renderer: function (value, column, record, rowIndex, field) {\n const { uiType, uiSource } = record.activity || {}\n var type = uiType !== 'board' ? 'string' : 'board'\n return getRenderer(type)(uiSource, column, record, rowIndex, field)\n }\n },\n width: 140,\n hidden: true\n },\n {\n type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: {\n appendable: false,\n editable: false,\n handlers: {\n click: (columns, data, column, record, rowIndex) => {\n this.openActivityThread(record)\n }\n }\n },\n sorters: [{ name: 'dueAt', desc: false }],\n pagination: { limit: 50, pages: [20, 50, 100, 500] }\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (this.active) {\n this.grist?.fetch()\n }\n }\n\n /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */\n async fetchHandler(options: FetchOption) {\n const fetched = await this.fetchRows(options)\n\n this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || [])\n\n return fetched\n }\n\n async fetchRows({ page, limit, sortings = [], filters = [] }: FetchOption) {\n if (this.filters?.includes('important')) {\n filters = adjustFilters(filters, importantFilters())\n }\n\n if (this.filters?.includes('due')) {\n filters = adjustFilters(filters, dueSoonFilters())\n }\n\n if (this.filters?.includes('proceeding')) {\n filters = adjustFilters(filters, [{ name: 'state', operator: 'eq', value: ActivityThreadStatus.Started }])\n }\n\n if (this.filters?.includes('pending-approval')) {\n filters = adjustFilters(filters, [\n {\n name: 'state',\n operator: 'in',\n value: [ActivityThreadStatus.Rejected, ActivityThreadStatus.Submitted, ActivityThreadStatus.Escalated]\n }\n ])\n }\n\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: todoList(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n activityInstance {\n activityId: id\n name\n description\n priority\n input\n refBy\n activityType\n uiType\n uiSource\n thumbnail\n updatedAt\n createdAt\n creator {\n id\n name\n }\n }\n state\n output\n dueAt\n assignedAt\n }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings }\n })\n\n return {\n total: response.data.responses.total || 0,\n records: (response.data.responses.items || []).map(item => {\n return {\n id: item.id,\n state: item.state,\n output: item.output,\n dueAt: item.dueAt,\n assignedAt: item.assignedAt,\n ...item.activityInstance\n }\n })\n }\n }\n\n openActivityThread(activityThread) {\n navigate(`activity-thread/${activityThread.id}?title=${activityThread.name}`)\n }\n\n}\n"]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Where a row of the work-doors screen takes its reader.
3
+ *
4
+ * The approval line of one activity is set on that activity's detail screen, together with whether
5
+ * it is used here and the master change policy that routes to it. This screen used to send people to
6
+ * the definition grid instead - a screen with no menu entry, identifiers, and a double click to open.
7
+ *
8
+ * `WorkDoorType.name` is the activity's name, so it is the key the detail screen takes.
9
+ *
10
+ * A form borrowed from another site is not linked: the row already says it cannot be changed here,
11
+ * and a link would contradict it.
12
+ */
13
+ type DoorLike = {
14
+ name: string;
15
+ standing: string;
16
+ kind?: string;
17
+ from?: string;
18
+ };
19
+ export declare function detailAddress(name: string): string;
20
+ /** The row opens its activity's detail unless the form belongs to another site. */
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
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Where a row of the work-doors screen takes its reader.
3
+ *
4
+ * The approval line of one activity is set on that activity's detail screen, together with whether
5
+ * it is used here and the master change policy that routes to it. This screen used to send people to
6
+ * the definition grid instead - a screen with no menu entry, identifiers, and a double click to open.
7
+ *
8
+ * `WorkDoorType.name` is the activity's name, so it is the key the detail screen takes.
9
+ *
10
+ * A form borrowed from another site is not linked: the row already says it cannot be changed here,
11
+ * and a link would contradict it.
12
+ */
13
+ export function detailAddress(name) {
14
+ return 'activity-detail?name=' + encodeURIComponent(name);
15
+ }
16
+ /** The row opens its activity's detail unless the form belongs to another site. */
17
+ export function opensDetail(door) {
18
+ return !!door.name && !door.from;
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
+ //# sourceMappingURL=door-links.js.map
@@ -0,0 +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"]}
@@ -7,6 +7,7 @@ import { client } from '@operato/graphql';
7
7
  import { i18next, localize } from '@operato/i18n';
8
8
  import { PageView } from '@operato/shell';
9
9
  import { ProseStyles, SurfaceStyles } from '@things-factory/styles';
10
+ import { detailAddress, doorsToSetHere, opensDetail } from './door-links.js';
10
11
  import { kindWord, standingWord } from './door-words.js';
11
12
  /**
12
13
  * 결재 문 현황 — **이 공장에서 어느 승인 단계가 실제로 서 있나.**
@@ -260,6 +261,11 @@ let WorkDoorsPage = class WorkDoorsPage extends localize(i18next)(PageView) {
260
261
  return '';
261
262
  }
262
263
  const seatsShort = this.seatsStanding < this.seatsOffered;
264
+ const toSet = doorsToSetHere(this.doors || []);
265
+ /* 남은 것이 전부 남의 양식이거나 배정 양식이면 여기서 가리킬 곳이 없다 — 빈 칸을 세우지 않는다. */
266
+ if (!seatsShort && !toSet.length) {
267
+ return '';
268
+ }
263
269
  return html `
264
270
  <section class="sheet ui-card">
265
271
  <span class="ui-label">${i18next.t('title.work-doors-next')}</span>
@@ -275,10 +281,12 @@ let WorkDoorsPage = class WorkDoorsPage extends localize(i18next)(PageView) {
275
281
  그 키는 어디에도 없어서 화면에 키 글자가 그대로 떴을 것이다. -->
276
282
  </li>`
277
283
  : ''}
278
- <li>
279
- ${i18next.t('text.work-doors-next-line', { count: this.todo })}
280
- <a href="meta-activity-define">${i18next.t('menu.activity-define')}</a>
281
- </li>
284
+ ${toSet.length
285
+ ? html `<li>
286
+ ${i18next.t('text.work-doors-next-line', { count: toSet.length })}
287
+ ${toSet.map((door, index) => html `${index ? ' · ' : ''}<a href=${detailAddress(door.name)}>${i18next.t(door.label)}</a>`)}
288
+ </li>`
289
+ : ''}
282
290
  </ol>
283
291
  </section>
284
292
  `;
@@ -314,7 +322,9 @@ let WorkDoorsPage = class WorkDoorsPage extends localize(i18next)(PageView) {
314
322
  renderDoor(door) {
315
323
  return html `
316
324
  <div class="door ${door.standing}">
317
- <span class="name">${i18next.t(door.label)}</span>
325
+ ${opensDetail(door)
326
+ ? html `<a class="name" href=${detailAddress(door.name)}>${i18next.t(door.label)}</a>`
327
+ : html `<span class="name">${i18next.t(door.label)}</span>`}
318
328
  <span class="kind">${i18next.t(`text.door-kind-${door.kind}`)}</span>
319
329
  <span class="mark ${door.standing}">${i18next.t(`text.door-standing-${door.standing}`)}</span>
320
330
  <span class="why">${door.because}</span>
@@ -1 +1 @@
1
- {"version":3,"file":"work-doors-page.js","sourceRoot":"","sources":["../../../client/pages/work-door/work-doors-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.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 { ProseStyles, SurfaceStyles } from '@things-factory/styles'\n\nimport { kindWord, standingWord } from './door-words.js'\n\n/**\n * 결재 문 현황 — **이 공장에서 어느 승인 단계가 실제로 서 있나.**\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── 왜 이 화면이 있나 ──────────────────────────────────────────────────────\n * 양식은 제품이 세우고 **결재선은 그 공장이 채운다.** 채운 것이 「우리는 이 단계를 쓴다」는 선언이라,\n * 비어 있는 것은 결함이 아니라 선택이다. 그런데 **그 선택이 어디에도 안 보였다.** 업무 카탈로그는\n * 「제품이 이 문을 만들었나」를 보여 주고, 이 물음에는 답하지 않는다.\n *\n * 실측(2026-09-11): 미라텍에 양식 11개가 다 서 있고 **11개 전부 결재자가 없었다.** 그 공장에서는\n * 실적 정정도 폐기도 승인 없이 반영되는데, 화면에는 문이 있는 것처럼 보였다.\n *\n * ── 비어 있는 것을 「승인 없음」으로 그리지 않는다 ─────────────────────────\n * 워크리스트는 결재선이 비면 **상신을 곧 완료로 만든다.** 그래서 실제 모습은 「아무도 승인하지\n * 않는다」가 아니라 **「올린 사람이 자기 건을 승인한다」**다. 그 차이를 문장이 말한다 — 문장은\n * 서버가 만든다(§`work-door.ts`). 화면이 상태를 보고 문장을 다시 지으면 두 벌이 된다.\n *\n * ── 할 일이 있는 것부터 ────────────────────────────────────────────────────\n * 선언 순서로 늘어놓으면 서 있는 것과 빈 것이 섞이고, 읽는 사람이 열한 줄을 훑어야 한다. **정할\n * 것이 남은 것을 위로** 올린다 — 이 화면을 여는 이유가 그것이다.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\nconst DOORS = gql`\n {\n workDoors {\n summary\n todo\n seatsStanding\n seatsOffered\n doors {\n name\n label\n kind\n standing\n approvers\n from\n because\n }\n }\n }\n`\n\ntype Door = {\n name: string\n label: string\n kind: 'approval' | 'assignment'\n standing: 'on' | 'off' | 'missing' | 'not-used'\n approvers: number\n from?: string\n because: string\n}\n\n/**\n * 조치할 것 · 서 있는 것 · 안 쓰기로 한 것 순. 같은 무리 안에서는 선언 순서를 지킨다.\n *\n * 안 쓰기로 한 것을 맨 아래 두는 이유는 **그것이 할 일이 아니어서**다. 위에 섞으면 이 화면을 여는\n * 이유(무엇을 채워야 하나)가 안 보인다.\n */\nconst ORDER: Record<Door['standing'], number> = { missing: 0, off: 1, on: 2, 'not-used': 3 }\n\n@customElement('work-doors-page')\nexport class WorkDoorsPage extends localize(i18next)(PageView) {\n static styles = [\n ProseStyles,\n SurfaceStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px;\n overflow: auto;\n }\n\n /*\n * These classes were used here but defined only inside disposition-policy-page's shadow root,\n * so this screen drew them unstyled. Shadow roots do not share rules; each page states its own.\n */\n .sheet {\n max-width: var(--ui-measure, min(1080px, 100%));\n }\n\n .lead {\n margin: 0;\n color: var(--ui-muted, #57676f);\n font-size: var(--ui-t-small, 11.5px);\n max-width: 60ch;\n }\n\n .state {\n margin: 0 0 4px;\n color: var(--ui-ink, #17242c);\n font-weight: 600;\n }\n\n .none {\n margin: 0;\n color: var(--ui-muted, #57676f);\n }\n\n .blocked {\n border-left: 3px solid var(--ui-crit, #c93f30);\n padding: 10px 12px;\n background: var(--ui-line-soft, #eef1f3);\n border-radius: var(--ui-r-small, 6px);\n }\n\n .blocked .why {\n margin-top: 4px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n white-space: pre-wrap;\n }\n\n .rule-actions {\n margin-top: var(--spacing-small, 4px);\n }\n\n .door {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 10px 0;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.12));\n }\n\n .door:last-child {\n border-bottom: none;\n }\n\n .name {\n flex: 0 0 auto;\n font-weight: 600;\n }\n\n /* 상태는 글자로도 말한다 — 색만으로 가르면 색을 못 보는 사람에게 아무 말도 안 한다. */\n .mark {\n flex: 0 0 auto;\n font-size: 0.85em;\n padding: 1px 8px;\n border-radius: 10px;\n border: 1px solid currentColor;\n }\n\n .mark.on {\n color: var(--md-sys-color-primary, #3f6b3f);\n }\n\n .mark.off {\n color: var(--md-sys-color-tertiary, #7a5b12);\n }\n\n .mark.missing {\n color: var(--md-sys-color-error, #a33);\n }\n\n /* 할 일이 아니므로 눈에 덜 띈다. 지우지는 않는다 — 껐다는 사실 자체가 읽혀야 한다. */\n .mark.not-used {\n color: var(--md-sys-color-outline, #777);\n }\n\n .door.not-used {\n opacity: 0.7;\n }\n\n /* 종류는 낱말로 말한다 — 결재와 배정은 비었을 때 결과가 반대다. */\n .kind {\n flex: 0 0 auto;\n font-size: 0.8em;\n opacity: 0.65;\n }\n\n .why {\n flex: 1 1 auto;\n opacity: 0.85;\n }\n\n .from {\n flex: 0 0 auto;\n font-size: 0.85em;\n opacity: 0.7;\n }\n\n ol.next {\n margin: 0;\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n ol.next li {\n line-height: 1.5;\n }\n\n ol.next a {\n margin-left: 4px;\n color: var(--md-sys-color-primary, #3f6cd4);\n }\n `\n ]\n\n @state() private doors?: Door[]\n @state() private summary = ''\n @state() private todo = 0\n @state() private seatsStanding = 0\n @state() private seatsOffered = 0\n @state() private readFailure = ''\n\n get context() {\n return { title: i18next.t('menu.work-doors') }\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.readFailure = ''\n\n const response = await client.query({ query: DOORS, fetchPolicy: 'no-cache' })\n\n /*\n * 못 읽은 것을 빈 목록으로 그리지 않는다. 「결재 문이 하나도 없습니다」와 「못 읽었습니다」는\n * 사람이 할 일이 다르다 — 앞은 설치를 보러 갈 일이고 뒤는 다시 눌러 볼 일이다.\n */\n if (response.errors?.length) {\n this.readFailure = response.errors[0].message\n return\n }\n\n /*\n * 전선의 철자를 여기서 **한 번** 옮긴다(§`door-words`). 안 옮기면 i18n 키도 CSS 클래스도\n * 어긋나는데 **오류가 하나도 안 난다** — 키 글자가 화면에 뜨고 상태 색이 투명해질 뿐이다.\n */\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 }))\n this.summary = response.data?.workDoors?.summary ?? ''\n this.todo = response.data?.workDoors?.todo ?? 0\n this.seatsStanding = response.data?.workDoors?.seatsStanding ?? 0\n this.seatsOffered = response.data?.workDoors?.seatsOffered ?? 0\n }\n\n /**\n * 다음에 할 일 — **순서대로.**\n *\n * ── 문제만 말하는 화면이었다 ──────────────────────────────────────────\n * 열두 줄이 「비었습니다」라고 적혀 있고, 어디로 가야 채우는지는 어디에도 없었다. 이 저장소에서\n * 가장 자주 나는 결함을 내 화면이 하고 있었다 — **자리는 있고 길이 없다.**\n *\n * ── 순서를 지키는 이유 ────────────────────────────────────────────────\n * 결재선은 역할을 가리킨다. 역할이 하나도 없는 공장에서 양식 화면으로 가면 **결재선 칸이 빈\n * 목록**이고, 사람은 헛걸음한 채 무엇이 잘못됐는지 모르고 돌아온다. 그래서 자리가 안 섰으면\n * 자리부터 말한다.\n *\n * 여기서 고치게 하지 않는다. 역할도 업무 양식도 **남의 화면이 임자**이고, 같은 일을 하는 자리를\n * 둘 만들면 한쪽이 낡는다. 이 화면이 하는 일은 **가리키는 것**이다.\n */\n private renderNext() {\n if (!this.todo) {\n return ''\n }\n\n const seatsShort = this.seatsStanding < this.seatsOffered\n\n return html`\n <section class=\"sheet ui-card\">\n <span class=\"ui-label\">${i18next.t('title.work-doors-next')}</span>\n <ol class=\"next\">\n ${seatsShort\n ? html`<li>\n ${i18next.t('text.work-doors-next-seats', {\n standing: this.seatsStanding,\n offered: this.seatsOffered\n })}\n <a href=\"roles\">${i18next.t('field.roles')}</a>\n <!-- field.roles 는 auth-ui 설치본의 키다. 내가 menu.roles 를 썼다가 고쳤다 —\n 그 키는 어디에도 없어서 화면에 키 글자가 그대로 떴을 것이다. -->\n </li>`\n : ''}\n <li>\n ${i18next.t('text.work-doors-next-line', { count: this.todo })}\n <a href=\"meta-activity-define\">${i18next.t('menu.activity-define')}</a>\n </li>\n </ol>\n </section>\n `\n }\n\n render() {\n if (this.readFailure) {\n return html`<div class=\"sheet blocked\">\n ${i18next.t('text.work-doors-read-failed')}\n <div class=\"why\">${this.readFailure}</div>\n <div class=\"rule-actions\">\n <md-text-button @click=${() => this.load()}>${i18next.t('button.try-again')}</md-text-button>\n </div>\n </div>`\n }\n\n if (!this.doors) {\n return html`<div class=\"none\">${i18next.t('text.loading')}</div>`\n }\n\n const sorted = [...this.doors].sort((a, b) => ORDER[a.standing] - ORDER[b.standing])\n\n return html`\n <div class=\"sheet\">\n <p class=\"lead\">${i18next.t('text.work-doors-lead')}</p>\n </div>\n\n <section class=\"sheet ui-card\">\n <span class=\"ui-label\">${i18next.t('title.work-doors')}</span>\n <p class=\"state\">${this.summary}</p>\n ${sorted.map(door => this.renderDoor(door))}\n </section>\n\n ${this.renderNext()}\n `\n }\n\n private renderDoor(door: Door) {\n return html`\n <div class=\"door ${door.standing}\">\n <span class=\"name\">${i18next.t(door.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 <span class=\"why\">${door.because}</span>\n ${\n /*\n * 자기 것이 아닌 양식을 쓰는 것은 정상이지만, 안 말하면 「정한 적 없는데」가 된다.\n *\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 `\n }\n}\n"]}
1
+ {"version":3,"file":"work-doors-page.js","sourceRoot":"","sources":["../../../client/pages/work-door/work-doors-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.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 { ProseStyles, SurfaceStyles } from '@things-factory/styles'\n\nimport { detailAddress, doorsToSetHere, opensDetail } from './door-links.js'\nimport { kindWord, standingWord } from './door-words.js'\n\n/**\n * 결재 문 현황 — **이 공장에서 어느 승인 단계가 실제로 서 있나.**\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── 왜 이 화면이 있나 ──────────────────────────────────────────────────────\n * 양식은 제품이 세우고 **결재선은 그 공장이 채운다.** 채운 것이 「우리는 이 단계를 쓴다」는 선언이라,\n * 비어 있는 것은 결함이 아니라 선택이다. 그런데 **그 선택이 어디에도 안 보였다.** 업무 카탈로그는\n * 「제품이 이 문을 만들었나」를 보여 주고, 이 물음에는 답하지 않는다.\n *\n * 실측(2026-09-11): 미라텍에 양식 11개가 다 서 있고 **11개 전부 결재자가 없었다.** 그 공장에서는\n * 실적 정정도 폐기도 승인 없이 반영되는데, 화면에는 문이 있는 것처럼 보였다.\n *\n * ── 비어 있는 것을 「승인 없음」으로 그리지 않는다 ─────────────────────────\n * 워크리스트는 결재선이 비면 **상신을 곧 완료로 만든다.** 그래서 실제 모습은 「아무도 승인하지\n * 않는다」가 아니라 **「올린 사람이 자기 건을 승인한다」**다. 그 차이를 문장이 말한다 — 문장은\n * 서버가 만든다(§`work-door.ts`). 화면이 상태를 보고 문장을 다시 지으면 두 벌이 된다.\n *\n * ── 할 일이 있는 것부터 ────────────────────────────────────────────────────\n * 선언 순서로 늘어놓으면 서 있는 것과 빈 것이 섞이고, 읽는 사람이 열한 줄을 훑어야 한다. **정할\n * 것이 남은 것을 위로** 올린다 — 이 화면을 여는 이유가 그것이다.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\nconst DOORS = gql`\n {\n workDoors {\n summary\n todo\n seatsStanding\n seatsOffered\n doors {\n name\n label\n kind\n standing\n approvers\n from\n because\n }\n }\n }\n`\n\ntype Door = {\n name: string\n label: string\n kind: 'approval' | 'assignment'\n standing: 'on' | 'off' | 'missing' | 'not-used'\n approvers: number\n from?: string\n because: string\n}\n\n/**\n * 조치할 것 · 서 있는 것 · 안 쓰기로 한 것 순. 같은 무리 안에서는 선언 순서를 지킨다.\n *\n * 안 쓰기로 한 것을 맨 아래 두는 이유는 **그것이 할 일이 아니어서**다. 위에 섞으면 이 화면을 여는\n * 이유(무엇을 채워야 하나)가 안 보인다.\n */\nconst ORDER: Record<Door['standing'], number> = { missing: 0, off: 1, on: 2, 'not-used': 3 }\n\n@customElement('work-doors-page')\nexport class WorkDoorsPage extends localize(i18next)(PageView) {\n static styles = [\n ProseStyles,\n SurfaceStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 16px;\n padding: 12px;\n overflow: auto;\n }\n\n /*\n * These classes were used here but defined only inside disposition-policy-page's shadow root,\n * so this screen drew them unstyled. Shadow roots do not share rules; each page states its own.\n */\n .sheet {\n max-width: var(--ui-measure, min(1080px, 100%));\n }\n\n .lead {\n margin: 0;\n color: var(--ui-muted, #57676f);\n font-size: var(--ui-t-small, 11.5px);\n max-width: 60ch;\n }\n\n .state {\n margin: 0 0 4px;\n color: var(--ui-ink, #17242c);\n font-weight: 600;\n }\n\n .none {\n margin: 0;\n color: var(--ui-muted, #57676f);\n }\n\n .blocked {\n border-left: 3px solid var(--ui-crit, #c93f30);\n padding: 10px 12px;\n background: var(--ui-line-soft, #eef1f3);\n border-radius: var(--ui-r-small, 6px);\n }\n\n .blocked .why {\n margin-top: 4px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n white-space: pre-wrap;\n }\n\n .rule-actions {\n margin-top: var(--spacing-small, 4px);\n }\n\n .door {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 10px 0;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.12));\n }\n\n .door:last-child {\n border-bottom: none;\n }\n\n .name {\n flex: 0 0 auto;\n font-weight: 600;\n }\n\n /* 상태는 글자로도 말한다 — 색만으로 가르면 색을 못 보는 사람에게 아무 말도 안 한다. */\n .mark {\n flex: 0 0 auto;\n font-size: 0.85em;\n padding: 1px 8px;\n border-radius: 10px;\n border: 1px solid currentColor;\n }\n\n .mark.on {\n color: var(--md-sys-color-primary, #3f6b3f);\n }\n\n .mark.off {\n color: var(--md-sys-color-tertiary, #7a5b12);\n }\n\n .mark.missing {\n color: var(--md-sys-color-error, #a33);\n }\n\n /* 할 일이 아니므로 눈에 덜 띈다. 지우지는 않는다 — 껐다는 사실 자체가 읽혀야 한다. */\n .mark.not-used {\n color: var(--md-sys-color-outline, #777);\n }\n\n .door.not-used {\n opacity: 0.7;\n }\n\n /* 종류는 낱말로 말한다 — 결재와 배정은 비었을 때 결과가 반대다. */\n .kind {\n flex: 0 0 auto;\n font-size: 0.8em;\n opacity: 0.65;\n }\n\n .why {\n flex: 1 1 auto;\n opacity: 0.85;\n }\n\n .from {\n flex: 0 0 auto;\n font-size: 0.85em;\n opacity: 0.7;\n }\n\n ol.next {\n margin: 0;\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n ol.next li {\n line-height: 1.5;\n }\n\n ol.next a {\n margin-left: 4px;\n color: var(--md-sys-color-primary, #3f6cd4);\n }\n `\n ]\n\n @state() private doors?: Door[]\n @state() private summary = ''\n @state() private todo = 0\n @state() private seatsStanding = 0\n @state() private seatsOffered = 0\n @state() private readFailure = ''\n\n get context() {\n return { title: i18next.t('menu.work-doors') }\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.readFailure = ''\n\n const response = await client.query({ query: DOORS, fetchPolicy: 'no-cache' })\n\n /*\n * 못 읽은 것을 빈 목록으로 그리지 않는다. 「결재 문이 하나도 없습니다」와 「못 읽었습니다」는\n * 사람이 할 일이 다르다 — 앞은 설치를 보러 갈 일이고 뒤는 다시 눌러 볼 일이다.\n */\n if (response.errors?.length) {\n this.readFailure = response.errors[0].message\n return\n }\n\n /*\n * 전선의 철자를 여기서 **한 번** 옮긴다(§`door-words`). 안 옮기면 i18n 키도 CSS 클래스도\n * 어긋나는데 **오류가 하나도 안 난다** — 키 글자가 화면에 뜨고 상태 색이 투명해질 뿐이다.\n */\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 }))\n this.summary = response.data?.workDoors?.summary ?? ''\n this.todo = response.data?.workDoors?.todo ?? 0\n this.seatsStanding = response.data?.workDoors?.seatsStanding ?? 0\n this.seatsOffered = response.data?.workDoors?.seatsOffered ?? 0\n }\n\n /**\n * 다음에 할 일 — **순서대로.**\n *\n * ── 문제만 말하는 화면이었다 ──────────────────────────────────────────\n * 열두 줄이 「비었습니다」라고 적혀 있고, 어디로 가야 채우는지는 어디에도 없었다. 이 저장소에서\n * 가장 자주 나는 결함을 내 화면이 하고 있었다 — **자리는 있고 길이 없다.**\n *\n * ── 순서를 지키는 이유 ────────────────────────────────────────────────\n * 결재선은 역할을 가리킨다. 역할이 하나도 없는 공장에서 양식 화면으로 가면 **결재선 칸이 빈\n * 목록**이고, 사람은 헛걸음한 채 무엇이 잘못됐는지 모르고 돌아온다. 그래서 자리가 안 섰으면\n * 자리부터 말한다.\n *\n * 여기서 고치게 하지 않는다. 역할도 업무 양식도 **남의 화면이 임자**이고, 같은 일을 하는 자리를\n * 둘 만들면 한쪽이 낡는다. 이 화면이 하는 일은 **가리키는 것**이다.\n */\n private renderNext() {\n if (!this.todo) {\n return ''\n }\n\n const seatsShort = this.seatsStanding < this.seatsOffered\n const toSet = doorsToSetHere(this.doors || [])\n\n /* 남은 것이 전부 남의 양식이거나 배정 양식이면 여기서 가리킬 곳이 없다 — 빈 칸을 세우지 않는다. */\n if (!seatsShort && !toSet.length) {\n return ''\n }\n\n return html`\n <section class=\"sheet ui-card\">\n <span class=\"ui-label\">${i18next.t('title.work-doors-next')}</span>\n <ol class=\"next\">\n ${seatsShort\n ? html`<li>\n ${i18next.t('text.work-doors-next-seats', {\n standing: this.seatsStanding,\n offered: this.seatsOffered\n })}\n <a href=\"roles\">${i18next.t('field.roles')}</a>\n <!-- field.roles 는 auth-ui 설치본의 키다. 내가 menu.roles 를 썼다가 고쳤다 —\n 그 키는 어디에도 없어서 화면에 키 글자가 그대로 떴을 것이다. -->\n </li>`\n : ''}\n ${toSet.length\n ? html`<li>\n ${i18next.t('text.work-doors-next-line', { count: toSet.length })}\n ${toSet.map(\n (door, index) =>\n html`${index ? ' · ' : ''}<a href=${detailAddress(door.name)}>${i18next.t(door.label)}</a>`\n )}\n </li>`\n : ''}\n </ol>\n </section>\n `\n }\n\n render() {\n if (this.readFailure) {\n return html`<div class=\"sheet blocked\">\n ${i18next.t('text.work-doors-read-failed')}\n <div class=\"why\">${this.readFailure}</div>\n <div class=\"rule-actions\">\n <md-text-button @click=${() => this.load()}>${i18next.t('button.try-again')}</md-text-button>\n </div>\n </div>`\n }\n\n if (!this.doors) {\n return html`<div class=\"none\">${i18next.t('text.loading')}</div>`\n }\n\n const sorted = [...this.doors].sort((a, b) => ORDER[a.standing] - ORDER[b.standing])\n\n return html`\n <div class=\"sheet\">\n <p class=\"lead\">${i18next.t('text.work-doors-lead')}</p>\n </div>\n\n <section class=\"sheet ui-card\">\n <span class=\"ui-label\">${i18next.t('title.work-doors')}</span>\n <p class=\"state\">${this.summary}</p>\n ${sorted.map(door => this.renderDoor(door))}\n </section>\n\n ${this.renderNext()}\n `\n }\n\n private renderDoor(door: Door) {\n return html`\n <div class=\"door ${door.standing}\">\n ${opensDetail(door)\n ? html`<a class=\"name\" href=${detailAddress(door.name)}>${i18next.t(door.label)}</a>`\n : html`<span class=\"name\">${i18next.t(door.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 <span class=\"why\">${door.because}</span>\n ${\n /*\n * 자기 것이 아닌 양식을 쓰는 것은 정상이지만, 안 말하면 「정한 적 없는데」가 된다.\n *\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 `\n }\n}\n"]}
@@ -1 +1 @@
1
- export default function route(page: string): "activity" | "activity-thread" | "activity-thread-view" | "activity-approval" | "work-doors-page" | "draft-list" | "todo-list" | "done-list" | "approval-pending-list" | "done-list-calendar" | "activity-catalog" | "approval-done-list" | "pickable-list" | "starter-list" | "reporter-list" | "activity-list" | "activity-instance-start" | "activity-instance-list" | "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): "activity" | "activity-catalog" | "draft-list" | "todo-list" | "activity-thread-view" | "done-list" | "approval-pending-list" | "done-list-calendar" | "activity-detail" | "work-doors-page" | "approval-done-list" | "pickable-list" | "starter-list" | "reporter-list" | "activity-list" | "activity-instance-start" | "activity-thread" | "activity-approval" | "activity-instance-list" | "activity-instance-search" | "activity-template-list" | "activity-store" | "activity-thread-list" | "activity-approval-list" | "installable-activity-list" | "activity-stats-list" | undefined;
@@ -6,6 +6,9 @@ export default function route(page) {
6
6
  case 'activity-catalog':
7
7
  import('./pages/activity-catalog/activity-catalog-page.js');
8
8
  return page;
9
+ case 'activity-detail':
10
+ import('./pages/activity-catalog/activity-detail-page.js');
11
+ return page;
9
12
  case 'work-doors-page':
10
13
  import('./pages/work-door/work-doors-page.js');
11
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,sCAAsC,CAAC,CAAA;YAC9C,OAAO,IAAI,CAAA;QAEb,KAAK,WAAW;YACd,MAAM,CAAC,gCAAgC,CAAC,CAAA;YACxC,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 '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 'done-list':\n import('./pages/todo/done-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,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,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 'done-list':\n import('./pages/todo/done-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"]}