@things-factory/worklist 10.1.169 → 10.1.173

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 (26) hide show
  1. package/dist-client/components/decision-content.d.ts +1 -1
  2. package/dist-client/components/decision-content.js +25 -4
  3. package/dist-client/components/decision-content.js.map +1 -1
  4. package/dist-client/pages/activity-instance/activity-instance-view.d.ts +10 -2
  5. package/dist-client/pages/activity-instance/activity-instance-view.js +18 -22
  6. package/dist-client/pages/activity-instance/activity-instance-view.js.map +1 -1
  7. package/dist-client/pages/activity-thread/activity-thread-view-page.js +2 -0
  8. package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
  9. package/dist-client/pages/activity-thread/activity-thread-view.js +18 -2
  10. package/dist-client/pages/activity-thread/activity-thread-view.js.map +1 -1
  11. package/dist-client/pages/todo/draft-list-page.d.ts +11 -3
  12. package/dist-client/pages/todo/draft-list-page.js +23 -7
  13. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  14. package/dist-client/pages/todo/work-box.d.ts +16 -0
  15. package/dist-client/pages/todo/work-box.js +10 -0
  16. package/dist-client/pages/todo/work-box.js.map +1 -1
  17. package/dist-client/route.d.ts +1 -1
  18. package/dist-client/tsconfig.tsbuildinfo +1 -1
  19. package/dist-server/service/activity-summary/index.d.ts +1 -1
  20. package/dist-server/service/activity-thread/index.d.ts +1 -1
  21. package/dist-server/service/index.d.ts +3 -3
  22. package/dist-server/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +5 -5
  24. package/dist-client/pages/todo/done-list-page.d.ts +0 -38
  25. package/dist-client/pages/todo/done-list-page.js +0 -382
  26. package/dist-client/pages/todo/done-list-page.js.map +0 -1
@@ -2,7 +2,6 @@ import '@operato/data-grist';
2
2
  import '@operato/data-grist/ox-filters-form.js';
3
3
  import '../../components/activity-starter-form.js';
4
4
  import '../../components/work-box-groups.js';
5
- import '../activity-instance/activity-instance-view.js';
6
5
  import { DataGrist, FetchOption } from '@operato/data-grist';
7
6
  import { PageView } from '@operato/shell';
8
7
  declare const DraftListPage_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
@@ -50,8 +49,17 @@ export declare class DraftListPage extends DraftListPage_base {
50
49
  total: any;
51
50
  records: any;
52
51
  }>;
53
- /** 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다. */
54
- openActivityInstanceView(activityInstance: any): void;
52
+ /**
53
+ * 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다.
54
+ *
55
+ * 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중
56
+ * 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제
57
+ * 할 일의 완료가 여는 읽기 화면(activity-thread-view)을 같이 쓴다.
58
+ *
59
+ * 내가 올린 건의 스레드는 대개 내 것이다(post) — 그것을 연다. 남에게 맡긴 건이면 그 건의 첫
60
+ * 스레드를 연다. 올린 사람은 그 건의 스레드를 읽을 수 있다(assert-may-read · participates).
61
+ */
62
+ openActivityThreadView(record: any): void;
55
63
  openActivityInstanceStart(activityInstance: any): void;
56
64
  }
57
65
  export {};
@@ -3,7 +3,6 @@ import '@operato/data-grist';
3
3
  import '@operato/data-grist/ox-filters-form.js';
4
4
  import '../../components/activity-starter-form.js';
5
5
  import '../../components/work-box-groups.js';
6
- import '../activity-instance/activity-instance-view.js';
7
6
  import gql from 'graphql-tag';
8
7
  import { css, html } from 'lit';
9
8
  import { customElement, property, query, state } from 'lit/decorators.js';
@@ -12,10 +11,9 @@ import { client } from '@operato/graphql';
12
11
  import { i18next, localize } from '@operato/i18n';
13
12
  import { navigate, PageView } from '@operato/shell';
14
13
  import { listWithThumbnail } from './list-thumbnail.js';
15
- import { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, groupAddress, groupAt } from './work-box.js';
14
+ import { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, groupAddress, groupAt, threadToView } from './work-box.js';
16
15
  import { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
17
16
  import { adjustFilters, isMobileDevice } from '@operato/utils';
18
- import { openPopup } from '@operato/layout';
19
17
  import { ActivityStartingTypes } from '../../types/types.js';
20
18
  import { ActivityInstanceStatus } from '../../types/activity-instance.js';
21
19
  import { subjectCell } from '../../activity-cells.js';
@@ -257,7 +255,7 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
257
255
  this.openActivityInstanceStart(record);
258
256
  }
259
257
  else {
260
- this.openActivityInstanceView(record);
258
+ this.openActivityThreadView(record);
261
259
  }
262
260
  }
263
261
  }
@@ -328,6 +326,12 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
328
326
  creator { id
329
327
  name
330
328
  }
329
+ activityThreads {
330
+ id
331
+ assignee {
332
+ id
333
+ }
334
+ }
331
335
  }
332
336
  total
333
337
  }
@@ -349,9 +353,21 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
349
353
  }) || []
350
354
  };
351
355
  }
352
- /** 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다. */
353
- openActivityInstanceView(activityInstance) {
354
- openPopup(html `<activity-instance-view activity-instance-id=${activityInstance.id} style="background-color: white;"></activity-instance-view>`, { backdrop: true, size: 'large', title: activityInstance.name || i18next.t('title.activity instance view') });
356
+ /**
357
+ * 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다.
358
+ *
359
+ * 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중
360
+ * 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제
361
+ * 할 일의 완료가 여는 읽기 화면(activity-thread-view)을 같이 쓴다.
362
+ *
363
+ * 내가 올린 건의 스레드는 대개 내 것이다(post) — 그것을 연다. 남에게 맡긴 건이면 그 건의 첫
364
+ * 스레드를 연다. 올린 사람은 그 건의 스레드를 읽을 수 있다(assert-may-read · participates).
365
+ */
366
+ openActivityThreadView(record) {
367
+ const threadId = threadToView(record);
368
+ if (threadId) {
369
+ navigate(`activity-thread-view/${threadId}?title=${record.name}`);
370
+ }
355
371
  }
356
372
  openActivityInstanceStart(activityInstance) {
357
373
  navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`);
@@ -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'\nimport '../../components/work-box-groups.js'\nimport '../activity-instance/activity-instance-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } 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 { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, DraftGroup, groupAddress, groupAt } from './work-box.js'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice } from '@operato/utils'\nimport { openPopup } from '@operato/layout'\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 /**\n * 지금 어느 묶음을 보고 있나 — 작성 중 · 진행 중 · 완료 (pages/todo/work-box.ts).\n *\n * 남에게 시킨 일의 함이다. 전에는 작성 중만 보였고, 올린 건은 상태 거르기를 바꿔야 보였다 —\n * 지출결의를 올린 사람이 상신함을 열면 0 건이었다(2026-10-16).\n */\n @state() private group: DraftGroup = 'draft'\n\n /** 기다리는 두 묶음의 건수. 끝난 묶음은 이력이라 세지 않는다. */\n @state() private counts: Partial<Record<DraftGroup, number>> = {}\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 <work-box-groups\n .groups=${(\n [\n ['draft', 'label.group-draft', 'text.group-draft-hint'],\n ['progress', 'label.group-progress', 'text.group-progress-hint'],\n ['completed', 'label.group-completed', 'text.group-sent-completed-hint']\n ] as const\n ).map(([key, label, hint]) => ({ key, label, hint, count: countsOnTab(key) ? this.counts[key] : undefined }))}\n .selected=${this.group}\n @select=${(e: CustomEvent) => this.selectGroup(e.detail)}\n ></work-box-groups>\n\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 /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: DraftGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, DRAFT_GROUPS))\n }\n\n private syncGroup(key?: string) {\n const group = groupAt(key, DRAFT_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /** 안 보고 있는 기다리는 묶음의 건수 — 한 줄만 받아 total 을 읽는다. 못 읽은 수는 0 이 아니다. */\n private async countOther() {\n const other: DraftGroup = this.group === 'progress' ? 'draft' : 'progress'\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n responses: draftList(filters: $filters, pagination: $pagination) {\n total\n }\n }\n `,\n variables: { filters: [this.stateFilterOf(other)], pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') this.counts = { ...this.counts, [other]: total }\n }\n\n private stateFilterOf(group: DraftGroup) {\n return { name: 'state', operator: 'in' as const, value: [...DRAFT_GROUP_STATES[group]] }\n }\n\n async pageInitialized(lifecycle) {\n /* pageUpdated 가 이 함수보다 먼저 지나가므로 주소로 바로 들어온 경우는 여기서 잡힌다. */\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n private applyConfig() {\n 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 if (this.group === 'draft') {\n this.openActivityInstanceStart(record)\n } else {\n this.openActivityInstanceView(record)\n }\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n 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) {\n filters = adjustFilters(filters, [this.stateFilterOf(this.group)])\n\n 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 notifyAfter\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 const total = response.data.responses.total || 0\n /* 보고 있는 묶음의 수는 이 조회가 알려 준다. 나머지는 countOther 가 센다. */\n if (countsOnTab(this.group)) this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n /** 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다. */\n openActivityInstanceView(activityInstance) {\n openPopup(\n html`<activity-instance-view activity-instance-id=${activityInstance.id} style=\"background-color: white;\"></activity-instance-view>`,\n { backdrop: true, size: 'large', title: activityInstance.name || i18next.t('title.activity instance view') }\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'\nimport '../../components/work-box-groups.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } 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 { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, DraftGroup, groupAddress, groupAt, threadToView } from './work-box.js'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, 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 /**\n * 지금 어느 묶음을 보고 있나 — 작성 중 · 진행 중 · 완료 (pages/todo/work-box.ts).\n *\n * 남에게 시킨 일의 함이다. 전에는 작성 중만 보였고, 올린 건은 상태 거르기를 바꿔야 보였다 —\n * 지출결의를 올린 사람이 상신함을 열면 0 건이었다(2026-10-16).\n */\n @state() private group: DraftGroup = 'draft'\n\n /** 기다리는 두 묶음의 건수. 끝난 묶음은 이력이라 세지 않는다. */\n @state() private counts: Partial<Record<DraftGroup, number>> = {}\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 <work-box-groups\n .groups=${(\n [\n ['draft', 'label.group-draft', 'text.group-draft-hint'],\n ['progress', 'label.group-progress', 'text.group-progress-hint'],\n ['completed', 'label.group-completed', 'text.group-sent-completed-hint']\n ] as const\n ).map(([key, label, hint]) => ({ key, label, hint, count: countsOnTab(key) ? this.counts[key] : undefined }))}\n .selected=${this.group}\n @select=${(e: CustomEvent) => this.selectGroup(e.detail)}\n ></work-box-groups>\n\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 /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: DraftGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, DRAFT_GROUPS))\n }\n\n private syncGroup(key?: string) {\n const group = groupAt(key, DRAFT_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /** 안 보고 있는 기다리는 묶음의 건수 — 한 줄만 받아 total 을 읽는다. 못 읽은 수는 0 이 아니다. */\n private async countOther() {\n const other: DraftGroup = this.group === 'progress' ? 'draft' : 'progress'\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n responses: draftList(filters: $filters, pagination: $pagination) {\n total\n }\n }\n `,\n variables: { filters: [this.stateFilterOf(other)], pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') this.counts = { ...this.counts, [other]: total }\n }\n\n private stateFilterOf(group: DraftGroup) {\n return { name: 'state', operator: 'in' as const, value: [...DRAFT_GROUP_STATES[group]] }\n }\n\n async pageInitialized(lifecycle) {\n /* pageUpdated 가 이 함수보다 먼저 지나가므로 주소로 바로 들어온 경우는 여기서 잡힌다. */\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n private applyConfig() {\n 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 if (this.group === 'draft') {\n this.openActivityInstanceStart(record)\n } else {\n this.openActivityThreadView(record)\n }\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n 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) {\n filters = adjustFilters(filters, [this.stateFilterOf(this.group)])\n\n 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 notifyAfter\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 activityThreads {\n id\n assignee {\n id\n }\n }\n }\n total\n }\n }\n `,\n variables: { filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n const total = response.data.responses.total || 0\n /* 보고 있는 묶음의 수는 이 조회가 알려 준다. 나머지는 countOther 가 센다. */\n if (countsOnTab(this.group)) this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n /**\n * 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다.\n *\n * 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중\n * 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제\n * 할 일의 완료가 여는 읽기 화면(activity-thread-view)을 같이 쓴다.\n *\n * 내가 올린 건의 스레드는 대개 내 것이다(post) — 그것을 연다. 남에게 맡긴 건이면 그 건의 첫\n * 스레드를 연다. 올린 사람은 그 건의 스레드를 읽을 수 있다(assert-may-read · participates).\n */\n openActivityThreadView(record) {\n const threadId = threadToView(record)\n\n if (threadId) {\n navigate(`activity-thread-view/${threadId}?title=${record.name}`)\n }\n }\n\n openActivityInstanceStart(activityInstance) { navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`)\n }\n}\n"]}
@@ -34,3 +34,19 @@ export declare function countsOnTab(group: string): boolean;
34
34
  * new state cannot fall out of the box unseen.
35
35
  */
36
36
  export declare const DRAFT_GROUP_STATES: Record<DraftGroup, readonly string[]>;
37
+ /**
38
+ * Which thread 상신함 opens for something I put up: my own when there is one - what I post is mine
39
+ * to carry until the approvers take it - otherwise the first, for work I gave someone else. Nothing
40
+ * when it has no thread yet.
41
+ */
42
+ export declare function threadToView(record: {
43
+ creator?: {
44
+ id?: string;
45
+ } | null;
46
+ activityThreads?: {
47
+ id?: string;
48
+ assignee?: {
49
+ id?: string;
50
+ } | null;
51
+ }[] | null;
52
+ }): string | undefined;
@@ -41,4 +41,14 @@ export const DRAFT_GROUP_STATES = {
41
41
  progress: ['issued', 'unassigned', 'assigned', 'started', 'pending'],
42
42
  completed: ['ended', 'aborted']
43
43
  };
44
+ /**
45
+ * Which thread 상신함 opens for something I put up: my own when there is one - what I post is mine
46
+ * to carry until the approvers take it - otherwise the first, for work I gave someone else. Nothing
47
+ * when it has no thread yet.
48
+ */
49
+ export function threadToView(record) {
50
+ const threads = (record?.activityThreads || []).filter(thread => thread?.id);
51
+ const mine = threads.find(thread => !!record?.creator?.id && thread.assignee?.id === record.creator.id);
52
+ return (mine ?? threads[0])?.id;
53
+ }
44
54
  //# sourceMappingURL=work-box.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-box.js","sourceRoot":"","sources":["../../../client/pages/todo/work-box.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AAC9E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAU,CAAA;AAMvE;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAmB,UAAqC,EAAE,MAAoB;IACnG,OAAQ,MAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAE,UAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AACnG,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAmB,IAAY,EAAE,KAAQ,EAAE,MAAoB;IACzF,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAA;AACxD,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK,KAAK,WAAW,CAAA;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA0C;IACvE,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;IACpE,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;CAChC,CAAA","sourcesContent":["/**\n * The three boxes of my work, and the groups each one is split into.\n *\n * 할 일 what I have to do 할 것 · 제출한 것 · 완료\n * 내 결재함 what I have to decide 결재할 것 · 참조로 받은 것 · 완료\n * 상신함 what I gave others to do 작성 중 · 진행 중 · 완료\n *\n * Each box ends in its own history, so a separate 「완료」 screen is not needed: it listed my\n * threads that ended, which mixed work I finished for someone with my own requests that someone\n * else decided. The first group of each box is what waits on me, and it is what the badge counts.\n *\n * Kept free of imports so the test runner can hold it.\n */\n\nexport const TODO_GROUPS = ['todo', 'submitted', 'completed'] as const\nexport const APPROVAL_GROUPS = ['approval', 'reference', 'completed'] as const\nexport const DRAFT_GROUPS = ['draft', 'progress', 'completed'] as const\n\nexport type TodoGroup = (typeof TODO_GROUPS)[number]\nexport type ApprovalGroup = (typeof APPROVAL_GROUPS)[number]\nexport type DraftGroup = (typeof DRAFT_GROUPS)[number]\n\n/**\n * The address names the group: `todo-list/submitted`. What is listed changes, so it is part of the\n * address and can be sent to someone, unlike a filter. No name, or one the box does not have, is\n * the first group.\n */\nexport function groupAt<G extends string>(resourceId: string | undefined | null, groups: readonly G[]): G {\n return (groups as readonly string[]).includes(String(resourceId)) ? (resourceId as G) : groups[0]\n}\n\n/** The address of a group - the first group is the page itself. */\nexport function groupAddress<G extends string>(page: string, group: G, groups: readonly G[]): string {\n return group === groups[0] ? page : `${page}/${group}`\n}\n\n/** A finished group is history, so it has no count on its tab. */\nexport function countsOnTab(group: string): boolean {\n return group !== 'completed'\n}\n\n/**\n * 상신함 groups by the state of what I put up (ActivityInstanceStatus, written out).\n *\n * Every state is in exactly one group - test/work-box.test.ts holds this to the server's enum, so a\n * new state cannot fall out of the box unseen.\n */\nexport const DRAFT_GROUP_STATES: Record<DraftGroup, readonly string[]> = {\n draft: ['draft'],\n progress: ['issued', 'unassigned', 'assigned', 'started', 'pending'],\n completed: ['ended', 'aborted']\n}\n"]}
1
+ {"version":3,"file":"work-box.js","sourceRoot":"","sources":["../../../client/pages/todo/work-box.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,CAAU,CAAA;AAC9E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAU,CAAA;AAMvE;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAmB,UAAqC,EAAE,MAAoB;IACnG,OAAQ,MAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAE,UAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AACnG,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAmB,IAAY,EAAE,KAAQ,EAAE,MAAoB;IACzF,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAA;AACxD,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK,KAAK,WAAW,CAAA;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA0C;IACvE,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;IACpE,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;CAChC,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAG5B;IACC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC5E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAEvG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AACjC,CAAC","sourcesContent":["/**\n * The three boxes of my work, and the groups each one is split into.\n *\n * 할 일 what I have to do 할 것 · 제출한 것 · 완료\n * 내 결재함 what I have to decide 결재할 것 · 참조로 받은 것 · 완료\n * 상신함 what I gave others to do 작성 중 · 진행 중 · 완료\n *\n * Each box ends in its own history, so a separate 「완료」 screen is not needed: it listed my\n * threads that ended, which mixed work I finished for someone with my own requests that someone\n * else decided. The first group of each box is what waits on me, and it is what the badge counts.\n *\n * Kept free of imports so the test runner can hold it.\n */\n\nexport const TODO_GROUPS = ['todo', 'submitted', 'completed'] as const\nexport const APPROVAL_GROUPS = ['approval', 'reference', 'completed'] as const\nexport const DRAFT_GROUPS = ['draft', 'progress', 'completed'] as const\n\nexport type TodoGroup = (typeof TODO_GROUPS)[number]\nexport type ApprovalGroup = (typeof APPROVAL_GROUPS)[number]\nexport type DraftGroup = (typeof DRAFT_GROUPS)[number]\n\n/**\n * The address names the group: `todo-list/submitted`. What is listed changes, so it is part of the\n * address and can be sent to someone, unlike a filter. No name, or one the box does not have, is\n * the first group.\n */\nexport function groupAt<G extends string>(resourceId: string | undefined | null, groups: readonly G[]): G {\n return (groups as readonly string[]).includes(String(resourceId)) ? (resourceId as G) : groups[0]\n}\n\n/** The address of a group - the first group is the page itself. */\nexport function groupAddress<G extends string>(page: string, group: G, groups: readonly G[]): string {\n return group === groups[0] ? page : `${page}/${group}`\n}\n\n/** A finished group is history, so it has no count on its tab. */\nexport function countsOnTab(group: string): boolean {\n return group !== 'completed'\n}\n\n/**\n * 상신함 groups by the state of what I put up (ActivityInstanceStatus, written out).\n *\n * Every state is in exactly one group - test/work-box.test.ts holds this to the server's enum, so a\n * new state cannot fall out of the box unseen.\n */\nexport const DRAFT_GROUP_STATES: Record<DraftGroup, readonly string[]> = {\n draft: ['draft'],\n progress: ['issued', 'unassigned', 'assigned', 'started', 'pending'],\n completed: ['ended', 'aborted']\n}\n\n/**\n * Which thread 상신함 opens for something I put up: my own when there is one - what I post is mine\n * to carry until the approvers take it - otherwise the first, for work I gave someone else. Nothing\n * when it has no thread yet.\n */\nexport function threadToView(record: {\n creator?: { id?: string } | null\n activityThreads?: { id?: string; assignee?: { id?: string } | null }[] | null\n}): string | undefined {\n const threads = (record?.activityThreads || []).filter(thread => thread?.id)\n const mine = threads.find(thread => !!record?.creator?.id && thread.assignee?.id === record.creator.id)\n\n return (mine ?? threads[0])?.id\n}\n"]}
@@ -1 +1 @@
1
- export default function route(page: string): "draft-list" | "activity" | "todo-list" | "approval-pending-list" | "done-list-calendar" | "activity-catalog" | "activity-detail" | "work-doors-page" | "approval-done-list" | "pickable-list" | "starter-list" | "reporter-list" | "activity-list" | "activity-instance-start" | "activity-thread" | "activity-thread-view" | "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;
1
+ export default function route(page: string): "activity" | "todo-list" | "approval-pending-list" | "draft-list" | "approval-done-list" | "done-list-calendar" | "pickable-list" | "starter-list" | "reporter-list" | "activity-instance-list" | "activity-catalog" | "work-doors-page" | "activity-thread" | "activity-thread-view" | "activity-approval" | "activity-detail" | "activity-list" | "activity-instance-start" | "activity-instance-search" | "activity-template-list" | "activity-store" | "activity-thread-list" | "activity-approval-list" | "installable-activity-list" | "activity-stats-list" | undefined;