@things-factory/worklist 10.1.243 → 10.1.245
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/activity-state-counts.d.ts +6 -0
- package/dist-client/activity-state-counts.js +23 -0
- package/dist-client/activity-state-counts.js.map +1 -0
- package/dist-client/chip-counts.d.ts +7 -0
- package/dist-client/chip-counts.js +11 -0
- package/dist-client/chip-counts.js.map +1 -0
- package/dist-client/chip-filters.d.ts +7 -0
- package/dist-client/chip-filters.js +42 -0
- package/dist-client/chip-filters.js.map +1 -1
- package/dist-client/pages/activity/activity-list-page.d.ts +2 -0
- package/dist-client/pages/activity/activity-list-page.js +11 -1
- package/dist-client/pages/activity/activity-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-done-list-page.d.ts +4 -0
- package/dist-client/pages/todo/approval-done-list-page.js +21 -10
- package/dist-client/pages/todo/approval-done-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-pending-list-page.d.ts +4 -0
- package/dist-client/pages/todo/approval-pending-list-page.js +21 -13
- package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-calendar-page.d.ts +5 -1
- package/dist-client/pages/todo/done-list-calendar-page.js +33 -52
- package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
- package/dist-client/pages/todo/pickable-list-page.d.ts +4 -0
- package/dist-client/pages/todo/pickable-list-page.js +21 -10
- package/dist-client/pages/todo/pickable-list-page.js.map +1 -1
- package/dist-client/pages/todo/todo-list-page.d.ts +4 -0
- package/dist-client/pages/todo/todo-list-page.js +20 -21
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/work-calendar-sources.d.ts +7 -2
- package/dist-client/work-calendar-sources.js +15 -6
- package/dist-client/work-calendar-sources.js.map +1 -1
- package/dist-server/service/activity/activity-query.d.ts +2 -1
- package/dist-server/service/activity/activity-query.js +22 -1
- package/dist-server/service/activity/activity-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -12
- package/tests/open-doors.test.ts +3 -2
|
@@ -37,6 +37,8 @@ export declare class ApprovalPendingListPage extends ApprovalPendingListPage_bas
|
|
|
37
37
|
mode: 'GRID' | 'LIST' | 'CARD';
|
|
38
38
|
grist: DataGrist;
|
|
39
39
|
filters?: string[];
|
|
40
|
+
/** How many each chip would show under the list's other conditions, counted by the list's own door. */
|
|
41
|
+
chipCounts: Map<string, number>;
|
|
40
42
|
get context(): {
|
|
41
43
|
title: string;
|
|
42
44
|
search: {
|
|
@@ -62,6 +64,8 @@ export declare class ApprovalPendingListPage extends ApprovalPendingListPage_bas
|
|
|
62
64
|
pageInitialized(lifecycle: any): Promise<void>;
|
|
63
65
|
private applyConfig;
|
|
64
66
|
pageUpdated(changes: any, lifecycle: any, changedBefore: any): Promise<void>;
|
|
67
|
+
private counted;
|
|
68
|
+
private countChips;
|
|
65
69
|
fetchHandler(options: FetchOption): Promise<{
|
|
66
70
|
total: any;
|
|
67
71
|
records: any;
|
|
@@ -8,13 +8,13 @@ import { css, html } from 'lit';
|
|
|
8
8
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
9
9
|
import { DataGrist, getRenderer } from '@operato/data-grist';
|
|
10
10
|
import { client } from '@operato/graphql';
|
|
11
|
-
import {
|
|
11
|
+
import { countChips, dueSoonChip, importantChip, withChips } from '../../chip-filters.js';
|
|
12
12
|
import { i18next, localize } from '@operato/i18n';
|
|
13
13
|
import { navigate, PageView } from '@operato/shell';
|
|
14
14
|
import { listWithThumbnail } from './list-thumbnail.js';
|
|
15
15
|
import { APPROVAL_GROUPS, countsOnTab, groupAddress, groupAt } from './work-box.js';
|
|
16
16
|
import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
|
|
17
|
-
import {
|
|
17
|
+
import { isMobileDevice } from '@operato/utils';
|
|
18
18
|
import { p13n } from '@operato/p13n';
|
|
19
19
|
import { approvalMarks, dueCell, priorityCell, subjectCell } from '../../activity-cells.js';
|
|
20
20
|
const MIN = 60;
|
|
@@ -45,6 +45,8 @@ let ApprovalPendingListPage = class ApprovalPendingListPage extends p13n(localiz
|
|
|
45
45
|
/** 세 묶음의 건수. 탭에 함께 적는다 — 안 눌러도 얼마나 있는지 보여야 한다. */
|
|
46
46
|
this.counts = {};
|
|
47
47
|
this.mode = isMobileDevice() ? 'CARD' : 'GRID';
|
|
48
|
+
/** How many each chip would show under the list's other conditions, counted by the list's own door. */
|
|
49
|
+
this.chipCounts = new Map();
|
|
48
50
|
}
|
|
49
51
|
static { this.styles = [
|
|
50
52
|
/* The frame owns the page shell; the grist is the content it sizes (ADR-0060 decision 8). */
|
|
@@ -174,13 +176,13 @@ let ApprovalPendingListPage = class ApprovalPendingListPage extends p13n(localiz
|
|
|
174
176
|
<ox-filters-form class="filter" without-search></ox-filters-form>
|
|
175
177
|
<ox-input-select-buttons
|
|
176
178
|
.value=${this.filters}
|
|
177
|
-
.options=${[
|
|
179
|
+
.options=${this.counted([
|
|
178
180
|
importantChip(),
|
|
179
181
|
dueSoonChip(),
|
|
180
182
|
{ display: i18next.t('label.filter-resubmitted'),
|
|
181
183
|
value: 'resubmitted'
|
|
182
184
|
}
|
|
183
|
-
]}
|
|
185
|
+
])}
|
|
184
186
|
@change=${(e) => {
|
|
185
187
|
this.filters = e.currentTarget?.value;
|
|
186
188
|
this.grist.fetch();
|
|
@@ -557,21 +559,23 @@ let ApprovalPendingListPage = class ApprovalPendingListPage extends p13n(localiz
|
|
|
557
559
|
}
|
|
558
560
|
}
|
|
559
561
|
/* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */
|
|
562
|
+
counted(chips) {
|
|
563
|
+
return chips.map(chip => ({ ...chip, count: this.chipCounts.get(chip.value) ?? 0 }));
|
|
564
|
+
}
|
|
565
|
+
/* The chips' numbers - asked beside the list, on the list's filters before any chip is added. */
|
|
566
|
+
countChips(filters) {
|
|
567
|
+
countChips(this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList', ['important', 'due', 'resubmitted'], filters)
|
|
568
|
+
.then(counts => (this.chipCounts = counts))
|
|
569
|
+
.catch(e => console.error(e));
|
|
570
|
+
}
|
|
560
571
|
async fetchHandler(options) {
|
|
561
572
|
const fetched = await this.fetchRows(options);
|
|
562
573
|
this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || []);
|
|
563
574
|
return fetched;
|
|
564
575
|
}
|
|
565
576
|
async fetchRows({ page, limit, sortings = [], filters = [] }) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
}
|
|
569
|
-
if (this.filters?.includes('due')) {
|
|
570
|
-
filters = adjustFilters(filters, dueSoonFilters());
|
|
571
|
-
}
|
|
572
|
-
if (this.filters?.includes('resubmitted')) {
|
|
573
|
-
filters = adjustFilters(filters, [{ name: 'round', operator: 'gte', value: 2 }]);
|
|
574
|
-
}
|
|
577
|
+
this.countChips(filters);
|
|
578
|
+
filters = withChips(filters, this.filters);
|
|
575
579
|
const response = await client.query({ query: gql `
|
|
576
580
|
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: ${this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList'}(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id
|
|
577
581
|
round
|
|
@@ -668,6 +672,10 @@ __decorate([
|
|
|
668
672
|
state(),
|
|
669
673
|
__metadata("design:type", Array)
|
|
670
674
|
], ApprovalPendingListPage.prototype, "filters", void 0);
|
|
675
|
+
__decorate([
|
|
676
|
+
state(),
|
|
677
|
+
__metadata("design:type", Object)
|
|
678
|
+
], ApprovalPendingListPage.prototype, "chipCounts", void 0);
|
|
671
679
|
ApprovalPendingListPage = __decorate([
|
|
672
680
|
customElement('approval-pending-list-page')
|
|
673
681
|
], ApprovalPendingListPage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-pending-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/approval-pending-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'\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 { 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 { APPROVAL_GROUPS, ApprovalGroup, countsOnTab, groupAddress, groupAt } from './work-box.js'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice, sleep } from '@operato/utils'\n\nimport { p13n } from '@operato/p13n'\n\nimport { approvalMarks, dueCell, priorityCell, subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('approval-pending-list-page')\nexport class ApprovalPendingListPage extends p13n(localize(i18next)(PageView)) { static styles = [\n /* The frame owns the page shell; the grist is the content it sizes (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n /*\n * 세로로 쌓는다 — 묶음 고르는 줄이 표 **위**에 서야 한다.\n *\n * 방향을 빼면 가로로 배치되어, 그 줄이 표 왼쪽에 세로 띠로 서고 버튼 글자가 세로 가운데에\n * 떠서 표 밑처럼 보인다. 표도 그 띠만큼 밀려 오른쪽 칸이 잘린다. 전에는 자식이 ox-grist\n * 하나뿐이라 방향이 드러나지 않았다.\n */\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n .header { grid-template-areas: 'filters actions';\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 * ox-filters-form 은 폭 0으로 남아 자리를 지키고, 그 뒤에 gap 12px 이 붙어 칩들을 밀어냈다.\n *\n * 실측: 표 셀 212 · 필터 영역 212 · 칩 224. 왼쪽 기준선이 다시 둘이 됐다.\n *\n * 컴포넌트가 스스로 [empty] 를 달아 주므로 그것으로 접는다. 필터가 생기면 그 표식이 사라져\n * 다시 나온다.\n */\n .header .filters ox-filters-form[empty] {\n display: none;\n }\n\n /*\n * 세 묶음 — 표 위. 지금 보는 쪽은 밑줄과 굵기로 말하고, 옆에 건수를 적는다.\n *\n * 건수를 안 눌러도 보이게 두는 것이 요점이다. 참조에 몇 건이 있는지 모르면 열어 볼 이유가 없다.\n *\n * ── 필터 칩보다 무거워야 한다 ─────────────────────────────────────────────\n * 처음에 13px 맨글자로 두었더니, 바로 아래 「중요·만기·재상신」 칩이 테두리를 가져서 더 세게\n * 보였다. **보는 대상을 바꾸는 것이 대상을 좁히는 것보다 약해 보였다.** 그래서 글자를 14px 로\n * 올리고(칩은 13px) 세로 여백을 넓혀 제목 다음 자리를 준다.\n *\n * 좌우 여백은 품질 화면 탭에서 베끼지 않는다 — 그 화면은 --spacing-large 라 이 화면의 왼쪽\n * 기준선 212px(표 셀과 같은 값)을 깨뜨린다. 무게만 같게 하고 기준선은 화면이 정한다.\n */\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n\n /**\n * 지금 어느 묶음을 보고 있나.\n *\n * ── 왜 한 화면에 세 묶음인가 ─────────────────────────────────────────────\n * 참조를 별도 화면으로 만들면 **아무도 열지 않는다.** 참조는 안 봐도 아무 일이 안 일어나므로,\n * 아침에 업무 앱을 열면 「승인 대기」를 보지 「참조」를 따로 열지 않는다. 참조를 만든 이유가 의견을\n * 듣는 것인데 안 여는 화면에 넣으면 의견이 안 온다.\n *\n * 그래서 한 화면에 두고, 완료 이력도 같은 자리에서 다시 찾을 수 있게 한다.\n *\n * ── 그렇다고 한 목록에 섞지 않는다 ────────────────────────────────────────\n * 세 묶음의 물음이 다르다 — 「내가 결정할 것」, 「내가 알아야 할 것」, 「끝난 참조 이력」. 섞으면\n * 참조가 「내가 승인해야 하나」로 읽히고, 배지에 12가 뜨는데 결정할 것은 3건이 된다.\n *\n * ── 주소가 주인이다 ──────────────────────────────────────────────────────\n * `.../approval-pending-list/reference` 로 붙여 보낼 수 있다. 대상이 바뀌는 것이므로 필터와 달리\n * 주소에 담는다.\n */\n @state() private group: ApprovalGroup = 'approval'\n\n /** 세 묶음의 건수. 탭에 함께 적는다 — 안 눌러도 얼마나 있는지 보여야 한다. */\n @state() private counts: Partial<Record<ApprovalGroup, number>> = {}\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n @state() filters?: string[]\n\n get context() { return { title: i18next.t('title.approval pending 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/approval-pending-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 ['approval', 'label.group-approval', 'text.group-approval-hint'],\n ['reference', 'label.group-reference', 'text.group-reference-hint'],\n ['completed', 'label.group-completed', 'text.group-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\n 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-resubmitted'),\n value: 'resubmitted'\n }\n ]}\n @change=${(e: CustomEvent) => { 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 /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: ApprovalGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, APPROVAL_GROUPS))\n }\n\n private async syncGroup(key?: string) {\n const group = groupAt(key, APPROVAL_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /**\n * 안 보고 있는 묶음의 건수를 따로 센다 — 한 줄만 받아 `total` 을 읽는다.\n *\n * 보고 있는 쪽의 수는 목록 조회가 이미 알려 준다(fetchHandler). 그래서 여기서는 나머지 둘만 묻는다.\n */\n private async countOther() {\n const queries = {\n approval: 'approvalPendingList',\n reference: 'approvalReferenceList'\n } as const\n const others = (Object.keys(queries) as Array<keyof typeof queries>).filter(group => group !== this.group)\n const results = await Promise.all(\n others.map(async group => ({\n group,\n response: await client.query({\n query: gql`\n query ($pagination: Pagination) {\n responses: ${queries[group]}(pagination: $pagination) {\n total\n }\n }\n `,\n variables: { pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n }))\n )\n\n /*\n * A count we could not fetch is not zero.\n *\n * This read `?? 0`, and the client runs with errorPolicy: 'all' — a failed query comes back as\n * a resolved response carrying `errors`, not a rejection. So any failure drew the other tab as\n * 「0」, which says \"nothing is waiting on you\". The render already draws nothing when the count\n * is undefined, so leaving it unknown is both honest and already handled.\n */\n const counts = { ...this.counts }\n for (const { group, response } of results) {\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') counts[group] = total\n }\n this.counts = counts\n }\n\n async pageInitialized(lifecycle) {\n /*\n * 주소가 묶음을 정한다. 주소로 바로 들어온 경우가 여기서 잡힌다 — pageUpdated 가 이 함수보다 먼저\n * 지나가므로 그것만 믿으면 `/reference` 링크가 결재 묶음을 보여준다.\n */\n await 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 /*\n * 빈 화면이 참조를 가르친다.\n *\n * 참조를 처음 누른 사람은 여기서 그 개념을 만난다. 기본 문장 「해당하는 것이 없습니다」는\n * 참조가 무엇인지 말해 주지 않는다 — 내가 결정해야 하는 것인지, 안 봐도 되는 것인지 모른 채\n * 화면을 닫는다.\n *\n * 그래서 없을 때 그 묶음이 무엇인지 적는다.\n */\n emptyNote:\n this.group === 'reference'\n ? {\n icon: 'visibility',\n title: i18next.t('text.no-reference-title'),\n description: i18next.t('text.no-reference-description')\n }\n : this.group === 'completed'\n ? {\n icon: 'task_alt',\n title: i18next.t('text.no-completed-approval-title'),\n description: i18next.t('text.no-completed-approval-description')\n }\n : {\n icon: 'task_alt',\n title: i18next.t('text.no-approval-title'),\n description: i18next.t('text.no-approval-description')\n },\n /*\n * ── 승인자가 먼저 묻는 순서대로 둔다 (2026-09-01) ─────────────────────\n *\n * 전에는 앞자리를 「열기」 버튼과 **모든 줄이 같은 값인 상태 칸**이 차지했고, 승인자가 가장 먼저\n * 묻는 「누가 올렸나」는 1200px 밖에 있었다. 실측으로 이름부터 담당까지 폭 합이 1287px 이었고\n * 보이는 폭은 1150px 이었다.\n *\n * 순서를 물음의 순서로 바꾼다 — 무엇을 · 누가 · 언제까지 · 얼마나 급한가.\n *\n * ── 「열기」 버튼을 없앤다 ─────────────────────────────────────────────\n * 줄을 누르면 이미 열린다(아래 rows.handlers.click). 같은 일을 하는 버튼이 줄마다 72px 을\n * 차지하고 있었다.\n *\n * 다만 그 버튼의 아이콘이 신호를 하나 들고 있었다 — `comment` 가 있으면 `label`, 없으면\n * `new_label`. **승인자가 보다가 메모를 남기고 미뤄 둔 것**이라는 뜻이다. 버리지 않고 이름 옆에\n * 말로 적는다. 태그 아이콘 두 개로는 아무도 그 뜻으로 읽지 않는다.\n *\n * 열람 여부는 담는 값이 없다 — `ActivityApproval` 에 `readAt` 이 없어서, 열어만 보고 나가면\n * 흔적이 남지 않는다. 지금 표시하는 것은 「메모를 남겨 뒀나」이지 「열어 봤나」가 아니다.\n */\n columns: [\n { type: 'gutter', gutterName: 'sequence', fixed: true },\n {\n type: 'string',\n name: 'name',\n fixed: true,\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n /*\n * 이름과 설명을 한 칸에 둔다. 둘은 함께 읽는 것인데 275px 짜리 칸으로 갈라 두면 눈이\n * 오가고, 그 사이를 우선순위·차수가 가로막고 있었다.\n */\n renderer: subjectCell(approvalMarks)\n },\n filter: 'search',\n sortable: true,\n width: 320\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: 110\n },\n {\n type: 'resource-object',\n name: 'assignee',\n header: i18next.t('field.wl-owner'),\n record: { editable: false },\n width: 110\n },\n {\n /*\n * 기한 한 칸 — 남은 시간이 위, 절대 시각이 아래다.\n *\n * 전에는 「만기 시간」(180px)과 「남은 시간」(180px)이 따로 있었다. 사람이 묻는 것은 「얼마나\n * 남았나」 하나이고, 절대 시각은 그것을 확인할 때만 본다. 두 칸으로 360px 을 쓸 일이 아니다.\n */\n type: 'string',\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: 170\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 width: 80\n },\n {\n type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: {\n editable: false,\n options: [\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-ended'), value: 'ended' }\n ]\n },\n width: 90\n },\n {\n type: 'number',\n name: 'round',\n header: i18next.t('field.wl-round'),\n record: { editable: false, align: 'right' },\n width: 60\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: 160\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false },\n sortable: true,\n filter: false,\n width: 160\n },\n {\n type: 'string',\n name: 'viewSource',\n header: i18next.t('field.wl-view-source'),\n record: {\n editable: false,\n renderer: function (value, column, record, rowIndex, field) {\n const { viewType, viewSource } = record.activity || {}\n var type = viewType !== 'board' ? 'string' : 'board'\n return getRenderer(type)(viewSource, 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 handlers: {\n click: (columns, data, column, record, rowIndex) => {\n this.openActivityApproval(record)\n }\n }\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { this.openActivityApproval(record)\n }\n }\n },\n /*\n * 급한 것부터 — 「할 일」 목록과 같은 순서다.\n *\n * 최근 변경 내림차순이었다. 받은 편지함으로는 말이 되지만 이 목록의 물음은 「무엇을 먼저\n * 판단해야 하나」다. 그 정렬에서는 나흘 지난 건이 목록 중간에 묻힌다 — 기안자가 나흘째\n * 기다리는 동안.\n *\n * 두 목록은 같은 성격이다(내가 처리해야 할 것). 순서 기준이 다르면 화면을 옮길 때마다 다른\n * 순서를 본다.\n *\n * 기한이 없는 건은 뒤로 간다 — 서버가 그 자리를 정한다(applyApprovalSortings).\n */\n sorters: [\n { name: 'dueAt',\n desc: false\n }\n ]\n }\n\n if (this.group === 'reference') {\n /*\n * ── 내 참조가 어떤 상태인가 ─────────────────────────────────────────\n * 이 묶음은 진행 중인 참조만 보인다. 끝난 건은 별도 「완료」 탭에서 결재 이력과 함께 확인한다.\n *\n * 닫힘 표시는, 이미 읽어 둔 목록 응답이 새로고침 직전에 도착한 경우를 위한 방어 표시다.\n */\n this.gristConfig.columns = [\n ...this.gristConfig.columns,\n {\n type: 'string',\n name: 'myReference',\n header: i18next.t('field.my-reference'),\n record: {\n editable: false,\n renderer: (value: any, column: any, record: any) => {\n const closed = record?.judgment === 'closed'\n const comment = (record?.comment || '').trim()\n\n if (!closed) {\n return html`<span class=\"quiet\">${i18next.t('text.reference-open')}</span>`\n }\n\n if (!comment) {\n return html`<span class=\"pill quiet\"\n ><span class=\"dot\"></span>${i18next.t('text.reference-closed-silent')}</span\n >`\n }\n\n /*\n * 의견은 있는데 시각이 없으면 **언제인지 모른다** — commentedAt 이 생기기 전에 적힌\n * 줄이다. 모르는 것을 「결정 전」으로도 「결정 후」로도 적지 않고, 의견만 보인다.\n */\n const after =\n record?.commentedAt &&\n record?.terminatedAt &&\n new Date(record.commentedAt).getTime() > new Date(record.terminatedAt).getTime()\n\n return html`\n <span class=\"line\">\n <span>${comment}</span>\n ${after ? html`<span class=\"pill warn\">${i18next.t('text.reference-after-decision')}</span>` : ''}\n </span>\n `\n }\n },\n width: 260\n }\n ]\n }\n\n if (this.group === 'completed') {\n this.gristConfig.columns = [\n ...this.gristConfig.columns,\n {\n type: 'select',\n name: 'participation',\n header: i18next.t('field.wl-participation'),\n record: {\n editable: false,\n options: [\n { display: i18next.t('label.participation-approval'), value: 'approval' },\n { display: i18next.t('label.participation-reference'), value: 'reference' }\n ]\n },\n width: 80\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n await this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\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) { if (this.filters?.includes('important')) { filters = adjustFilters(filters, importantFilters())\n }\n\n if (this.filters?.includes('due')) { filters = adjustFilters(filters, dueSoonFilters())\n }\n\n if (this.filters?.includes('resubmitted')) { filters = adjustFilters(filters, [{ name: 'round', operator: 'gte', value: 2 }])\n }\n\n const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: ${this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList'}(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id\n round\n comment\n commentedAt\n judgment\n participation\n terminatedAt\n activityThread { activityInstance { activityId: id\n name\n description\n priority\n input\n refBy\n activityType\n viewType\n viewSource\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n }\n state\n output\n dueAt\n assignee { id\n name\n }\n assignedAt\n }\n updatedAt\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 (this.group !== 'completed') this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records: (response.data.responses.items || []).map(item => { let thread = item.activityThread\n return { id: item.id,\n state: thread.state,\n ...thread.activityInstance,\n dueAt: thread.dueAt,\n assignee: thread.assignee,\n assignedAt: thread.assignedAt,\n output: thread.output,\n round: item.round,\n comment: item.comment,\n judgment: item.judgment,\n participation: item.participation || 'approval',\n commentedAt: item.commentedAt,\n terminatedAt: item.terminatedAt,\n updatedAt: item.updatedAt\n }\n })\n }\n }\n\n openActivityApproval(activityApproval) { navigate(`activity-approval/${activityApproval.id}?title=${activityApproval.name}`)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"approval-pending-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/approval-pending-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'\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 { asyncReplace } from 'lit/directives/async-replace.js'\nimport { DataGrist, FetchOption, getRenderer } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { countChips, dueSoonChip, importantChip, withChips } from '../../chip-filters.js'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { listWithThumbnail } from './list-thumbnail.js'\nimport { APPROVAL_GROUPS, ApprovalGroup, countsOnTab, groupAddress, groupAt } from './work-box.js'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice, sleep } from '@operato/utils'\n\nimport { p13n } from '@operato/p13n'\n\nimport { approvalMarks, dueCell, priorityCell, subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('approval-pending-list-page')\nexport class ApprovalPendingListPage extends p13n(localize(i18next)(PageView)) { static styles = [\n /* The frame owns the page shell; the grist is the content it sizes (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n /*\n * 세로로 쌓는다 — 묶음 고르는 줄이 표 **위**에 서야 한다.\n *\n * 방향을 빼면 가로로 배치되어, 그 줄이 표 왼쪽에 세로 띠로 서고 버튼 글자가 세로 가운데에\n * 떠서 표 밑처럼 보인다. 표도 그 띠만큼 밀려 오른쪽 칸이 잘린다. 전에는 자식이 ox-grist\n * 하나뿐이라 방향이 드러나지 않았다.\n */\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n .header { grid-template-areas: 'filters actions';\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 * ox-filters-form 은 폭 0으로 남아 자리를 지키고, 그 뒤에 gap 12px 이 붙어 칩들을 밀어냈다.\n *\n * 실측: 표 셀 212 · 필터 영역 212 · 칩 224. 왼쪽 기준선이 다시 둘이 됐다.\n *\n * 컴포넌트가 스스로 [empty] 를 달아 주므로 그것으로 접는다. 필터가 생기면 그 표식이 사라져\n * 다시 나온다.\n */\n .header .filters ox-filters-form[empty] {\n display: none;\n }\n\n /*\n * 세 묶음 — 표 위. 지금 보는 쪽은 밑줄과 굵기로 말하고, 옆에 건수를 적는다.\n *\n * 건수를 안 눌러도 보이게 두는 것이 요점이다. 참조에 몇 건이 있는지 모르면 열어 볼 이유가 없다.\n *\n * ── 필터 칩보다 무거워야 한다 ─────────────────────────────────────────────\n * 처음에 13px 맨글자로 두었더니, 바로 아래 「중요·만기·재상신」 칩이 테두리를 가져서 더 세게\n * 보였다. **보는 대상을 바꾸는 것이 대상을 좁히는 것보다 약해 보였다.** 그래서 글자를 14px 로\n * 올리고(칩은 13px) 세로 여백을 넓혀 제목 다음 자리를 준다.\n *\n * 좌우 여백은 품질 화면 탭에서 베끼지 않는다 — 그 화면은 --spacing-large 라 이 화면의 왼쪽\n * 기준선 212px(표 셀과 같은 값)을 깨뜨린다. 무게만 같게 하고 기준선은 화면이 정한다.\n */\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n\n /**\n * 지금 어느 묶음을 보고 있나.\n *\n * ── 왜 한 화면에 세 묶음인가 ─────────────────────────────────────────────\n * 참조를 별도 화면으로 만들면 **아무도 열지 않는다.** 참조는 안 봐도 아무 일이 안 일어나므로,\n * 아침에 업무 앱을 열면 「승인 대기」를 보지 「참조」를 따로 열지 않는다. 참조를 만든 이유가 의견을\n * 듣는 것인데 안 여는 화면에 넣으면 의견이 안 온다.\n *\n * 그래서 한 화면에 두고, 완료 이력도 같은 자리에서 다시 찾을 수 있게 한다.\n *\n * ── 그렇다고 한 목록에 섞지 않는다 ────────────────────────────────────────\n * 세 묶음의 물음이 다르다 — 「내가 결정할 것」, 「내가 알아야 할 것」, 「끝난 참조 이력」. 섞으면\n * 참조가 「내가 승인해야 하나」로 읽히고, 배지에 12가 뜨는데 결정할 것은 3건이 된다.\n *\n * ── 주소가 주인이다 ──────────────────────────────────────────────────────\n * `.../approval-pending-list/reference` 로 붙여 보낼 수 있다. 대상이 바뀌는 것이므로 필터와 달리\n * 주소에 담는다.\n */\n @state() private group: ApprovalGroup = 'approval'\n\n /** 세 묶음의 건수. 탭에 함께 적는다 — 안 눌러도 얼마나 있는지 보여야 한다. */\n @state() private counts: Partial<Record<ApprovalGroup, number>> = {}\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n @state() filters?: string[]\n\n /** How many each chip would show under the list's other conditions, counted by the list's own door. */\n @state() chipCounts = new Map<string, number>()\n\n get context() { return { title: i18next.t('title.approval pending 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/approval-pending-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 ['approval', 'label.group-approval', 'text.group-approval-hint'],\n ['reference', 'label.group-reference', 'text.group-reference-hint'],\n ['completed', 'label.group-completed', 'text.group-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\n 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=${this.counted([\n importantChip(),\n dueSoonChip(),\n { display: i18next.t('label.filter-resubmitted'),\n value: 'resubmitted'\n }\n ])}\n @change=${(e: CustomEvent) => { 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 /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: ApprovalGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, APPROVAL_GROUPS))\n }\n\n private async syncGroup(key?: string) {\n const group = groupAt(key, APPROVAL_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /**\n * 안 보고 있는 묶음의 건수를 따로 센다 — 한 줄만 받아 `total` 을 읽는다.\n *\n * 보고 있는 쪽의 수는 목록 조회가 이미 알려 준다(fetchHandler). 그래서 여기서는 나머지 둘만 묻는다.\n */\n private async countOther() {\n const queries = {\n approval: 'approvalPendingList',\n reference: 'approvalReferenceList'\n } as const\n const others = (Object.keys(queries) as Array<keyof typeof queries>).filter(group => group !== this.group)\n const results = await Promise.all(\n others.map(async group => ({\n group,\n response: await client.query({\n query: gql`\n query ($pagination: Pagination) {\n responses: ${queries[group]}(pagination: $pagination) {\n total\n }\n }\n `,\n variables: { pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n }))\n )\n\n /*\n * A count we could not fetch is not zero.\n *\n * This read `?? 0`, and the client runs with errorPolicy: 'all' — a failed query comes back as\n * a resolved response carrying `errors`, not a rejection. So any failure drew the other tab as\n * 「0」, which says \"nothing is waiting on you\". The render already draws nothing when the count\n * is undefined, so leaving it unknown is both honest and already handled.\n */\n const counts = { ...this.counts }\n for (const { group, response } of results) {\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') counts[group] = total\n }\n this.counts = counts\n }\n\n async pageInitialized(lifecycle) {\n /*\n * 주소가 묶음을 정한다. 주소로 바로 들어온 경우가 여기서 잡힌다 — pageUpdated 가 이 함수보다 먼저\n * 지나가므로 그것만 믿으면 `/reference` 링크가 결재 묶음을 보여준다.\n */\n await 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 /*\n * 빈 화면이 참조를 가르친다.\n *\n * 참조를 처음 누른 사람은 여기서 그 개념을 만난다. 기본 문장 「해당하는 것이 없습니다」는\n * 참조가 무엇인지 말해 주지 않는다 — 내가 결정해야 하는 것인지, 안 봐도 되는 것인지 모른 채\n * 화면을 닫는다.\n *\n * 그래서 없을 때 그 묶음이 무엇인지 적는다.\n */\n emptyNote:\n this.group === 'reference'\n ? {\n icon: 'visibility',\n title: i18next.t('text.no-reference-title'),\n description: i18next.t('text.no-reference-description')\n }\n : this.group === 'completed'\n ? {\n icon: 'task_alt',\n title: i18next.t('text.no-completed-approval-title'),\n description: i18next.t('text.no-completed-approval-description')\n }\n : {\n icon: 'task_alt',\n title: i18next.t('text.no-approval-title'),\n description: i18next.t('text.no-approval-description')\n },\n /*\n * ── 승인자가 먼저 묻는 순서대로 둔다 (2026-09-01) ─────────────────────\n *\n * 전에는 앞자리를 「열기」 버튼과 **모든 줄이 같은 값인 상태 칸**이 차지했고, 승인자가 가장 먼저\n * 묻는 「누가 올렸나」는 1200px 밖에 있었다. 실측으로 이름부터 담당까지 폭 합이 1287px 이었고\n * 보이는 폭은 1150px 이었다.\n *\n * 순서를 물음의 순서로 바꾼다 — 무엇을 · 누가 · 언제까지 · 얼마나 급한가.\n *\n * ── 「열기」 버튼을 없앤다 ─────────────────────────────────────────────\n * 줄을 누르면 이미 열린다(아래 rows.handlers.click). 같은 일을 하는 버튼이 줄마다 72px 을\n * 차지하고 있었다.\n *\n * 다만 그 버튼의 아이콘이 신호를 하나 들고 있었다 — `comment` 가 있으면 `label`, 없으면\n * `new_label`. **승인자가 보다가 메모를 남기고 미뤄 둔 것**이라는 뜻이다. 버리지 않고 이름 옆에\n * 말로 적는다. 태그 아이콘 두 개로는 아무도 그 뜻으로 읽지 않는다.\n *\n * 열람 여부는 담는 값이 없다 — `ActivityApproval` 에 `readAt` 이 없어서, 열어만 보고 나가면\n * 흔적이 남지 않는다. 지금 표시하는 것은 「메모를 남겨 뒀나」이지 「열어 봤나」가 아니다.\n */\n columns: [\n { type: 'gutter', gutterName: 'sequence', fixed: true },\n {\n type: 'string',\n name: 'name',\n fixed: true,\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n /*\n * 이름과 설명을 한 칸에 둔다. 둘은 함께 읽는 것인데 275px 짜리 칸으로 갈라 두면 눈이\n * 오가고, 그 사이를 우선순위·차수가 가로막고 있었다.\n */\n renderer: subjectCell(approvalMarks)\n },\n filter: 'search',\n sortable: true,\n width: 320\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: 110\n },\n {\n type: 'resource-object',\n name: 'assignee',\n header: i18next.t('field.wl-owner'),\n record: { editable: false },\n width: 110\n },\n {\n /*\n * 기한 한 칸 — 남은 시간이 위, 절대 시각이 아래다.\n *\n * 전에는 「만기 시간」(180px)과 「남은 시간」(180px)이 따로 있었다. 사람이 묻는 것은 「얼마나\n * 남았나」 하나이고, 절대 시각은 그것을 확인할 때만 본다. 두 칸으로 360px 을 쓸 일이 아니다.\n */\n type: 'string',\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: 170\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 width: 80\n },\n {\n type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: {\n editable: false,\n options: [\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-ended'), value: 'ended' }\n ]\n },\n width: 90\n },\n {\n type: 'number',\n name: 'round',\n header: i18next.t('field.wl-round'),\n record: { editable: false, align: 'right' },\n width: 60\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: 160\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false },\n sortable: true,\n filter: false,\n width: 160\n },\n {\n type: 'string',\n name: 'viewSource',\n header: i18next.t('field.wl-view-source'),\n record: {\n editable: false,\n renderer: function (value, column, record, rowIndex, field) {\n const { viewType, viewSource } = record.activity || {}\n var type = viewType !== 'board' ? 'string' : 'board'\n return getRenderer(type)(viewSource, 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 handlers: {\n click: (columns, data, column, record, rowIndex) => {\n this.openActivityApproval(record)\n }\n }\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { this.openActivityApproval(record)\n }\n }\n },\n /*\n * 급한 것부터 — 「할 일」 목록과 같은 순서다.\n *\n * 최근 변경 내림차순이었다. 받은 편지함으로는 말이 되지만 이 목록의 물음은 「무엇을 먼저\n * 판단해야 하나」다. 그 정렬에서는 나흘 지난 건이 목록 중간에 묻힌다 — 기안자가 나흘째\n * 기다리는 동안.\n *\n * 두 목록은 같은 성격이다(내가 처리해야 할 것). 순서 기준이 다르면 화면을 옮길 때마다 다른\n * 순서를 본다.\n *\n * 기한이 없는 건은 뒤로 간다 — 서버가 그 자리를 정한다(applyApprovalSortings).\n */\n sorters: [\n { name: 'dueAt',\n desc: false\n }\n ]\n }\n\n if (this.group === 'reference') {\n /*\n * ── 내 참조가 어떤 상태인가 ─────────────────────────────────────────\n * 이 묶음은 진행 중인 참조만 보인다. 끝난 건은 별도 「완료」 탭에서 결재 이력과 함께 확인한다.\n *\n * 닫힘 표시는, 이미 읽어 둔 목록 응답이 새로고침 직전에 도착한 경우를 위한 방어 표시다.\n */\n this.gristConfig.columns = [\n ...this.gristConfig.columns,\n {\n type: 'string',\n name: 'myReference',\n header: i18next.t('field.my-reference'),\n record: {\n editable: false,\n renderer: (value: any, column: any, record: any) => {\n const closed = record?.judgment === 'closed'\n const comment = (record?.comment || '').trim()\n\n if (!closed) {\n return html`<span class=\"quiet\">${i18next.t('text.reference-open')}</span>`\n }\n\n if (!comment) {\n return html`<span class=\"pill quiet\"\n ><span class=\"dot\"></span>${i18next.t('text.reference-closed-silent')}</span\n >`\n }\n\n /*\n * 의견은 있는데 시각이 없으면 **언제인지 모른다** — commentedAt 이 생기기 전에 적힌\n * 줄이다. 모르는 것을 「결정 전」으로도 「결정 후」로도 적지 않고, 의견만 보인다.\n */\n const after =\n record?.commentedAt &&\n record?.terminatedAt &&\n new Date(record.commentedAt).getTime() > new Date(record.terminatedAt).getTime()\n\n return html`\n <span class=\"line\">\n <span>${comment}</span>\n ${after ? html`<span class=\"pill warn\">${i18next.t('text.reference-after-decision')}</span>` : ''}\n </span>\n `\n }\n },\n width: 260\n }\n ]\n }\n\n if (this.group === 'completed') {\n this.gristConfig.columns = [\n ...this.gristConfig.columns,\n {\n type: 'select',\n name: 'participation',\n header: i18next.t('field.wl-participation'),\n record: {\n editable: false,\n options: [\n { display: i18next.t('label.participation-approval'), value: 'approval' },\n { display: i18next.t('label.participation-reference'), value: 'reference' }\n ]\n },\n width: 80\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n await this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n if (this.active) {\n this.grist?.fetch()\n }\n }\n\n /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */\n private counted(chips: { display: string; value: string; hint?: string }[]) {\n return chips.map(chip => ({ ...chip, count: this.chipCounts.get(chip.value) ?? 0 }))\n }\n\n /* The chips' numbers - asked beside the list, on the list's filters before any chip is added. */\n private countChips(filters: any[]) {\n countChips(this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList', ['important', 'due', 'resubmitted'], filters)\n .then(counts => (this.chipCounts = counts))\n .catch(e => console.error(e))\n }\n\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 this.countChips(filters)\n filters = withChips(filters, this.filters)\n\n const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: ${this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList'}(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id\n round\n comment\n commentedAt\n judgment\n participation\n terminatedAt\n activityThread { activityInstance { activityId: id\n name\n description\n priority\n input\n refBy\n activityType\n viewType\n viewSource\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n }\n state\n output\n dueAt\n assignee { id\n name\n }\n assignedAt\n }\n updatedAt\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 (this.group !== 'completed') this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records: (response.data.responses.items || []).map(item => { let thread = item.activityThread\n return { id: item.id,\n state: thread.state,\n ...thread.activityInstance,\n dueAt: thread.dueAt,\n assignee: thread.assignee,\n assignedAt: thread.assignedAt,\n output: thread.output,\n round: item.round,\n comment: item.comment,\n judgment: item.judgment,\n participation: item.participation || 'approval',\n commentedAt: item.commentedAt,\n terminatedAt: item.terminatedAt,\n updatedAt: item.updatedAt\n }\n })\n }\n }\n\n openActivityApproval(activityApproval) { navigate(`activity-approval/${activityApproval.id}?title=${activityApproval.name}`)\n }\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import '@operato/event-view/ox-event-view.js';
|
|
3
|
+
import '@operato/input/ox-input-select-buttons.js';
|
|
3
4
|
import { PageView } from '@operato/shell';
|
|
4
5
|
import { OxEventView } from '@operato/event-view';
|
|
5
6
|
import { BizEvent, CALENDAR, EventProvider } from '@operato/event-view/types.js';
|
|
@@ -16,6 +17,8 @@ export declare class DoneListCalendarPage extends DoneListCalendarPage_base {
|
|
|
16
17
|
}[];
|
|
17
18
|
/** The kinds turned off. */
|
|
18
19
|
turnedOff: Set<string>;
|
|
20
|
+
/** How many each kind has on the days drawn, its chip on or off. */
|
|
21
|
+
counts: Map<string, number>;
|
|
19
22
|
/** A new object whenever what is shown changes - the calendar asks again only when it is handed a different one. */
|
|
20
23
|
provider?: EventProvider;
|
|
21
24
|
get context(): {
|
|
@@ -26,7 +29,8 @@ export declare class DoneListCalendarPage extends DoneListCalendarPage_base {
|
|
|
26
29
|
/** The chips are known once - which sources have anything for this person - and then the calendar is asked. */
|
|
27
30
|
firstUpdated(): Promise<void>;
|
|
28
31
|
private calendarProvider;
|
|
29
|
-
|
|
32
|
+
/** Show the kinds chosen; every other kind is turned off. */
|
|
33
|
+
private showOnly;
|
|
30
34
|
/**
|
|
31
35
|
* The days not worked, painted - asked of every source that says them, chip on or off. One that cannot answer paints
|
|
32
36
|
* nothing and is logged; the entries still come.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@material/web/icon/icon.js';
|
|
3
3
|
import '@operato/event-view/ox-event-view.js';
|
|
4
|
+
import '@operato/input/ox-input-select-buttons.js';
|
|
4
5
|
import { html, css } from 'lit';
|
|
5
6
|
import gql from 'graphql-tag';
|
|
6
7
|
import { customElement, query, state } from 'lit/decorators.js';
|
|
@@ -117,6 +118,8 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
117
118
|
this.kinds = [];
|
|
118
119
|
/** The kinds turned off. */
|
|
119
120
|
this.turnedOff = new Set();
|
|
121
|
+
/** How many each kind has on the days drawn, its chip on or off. */
|
|
122
|
+
this.counts = new Map();
|
|
120
123
|
}
|
|
121
124
|
static { this.styles = [
|
|
122
125
|
/* The frame owns the page shell; the calendar is the content it sizes (ADR-0060 decision 8). */
|
|
@@ -146,42 +149,11 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
146
149
|
font-size: 1.2em;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
|
-
/* What is on the calendar - each chip shows or hides one kind,
|
|
150
|
-
|
|
151
|
-
display: flex;
|
|
152
|
-
flex-wrap: wrap;
|
|
153
|
-
gap: 6px;
|
|
154
|
-
align-items: center;
|
|
152
|
+
/* What is on the calendar - each chip shows or hides one kind, with how many it has on the days drawn. */
|
|
153
|
+
ox-input-select-buttons {
|
|
155
154
|
margin: 10px 10px 0 10px;
|
|
156
155
|
}
|
|
157
156
|
|
|
158
|
-
button.chip {
|
|
159
|
-
display: inline-flex;
|
|
160
|
-
align-items: center;
|
|
161
|
-
gap: 6px;
|
|
162
|
-
border: 1px solid var(--ui-line);
|
|
163
|
-
border-radius: 999px;
|
|
164
|
-
padding: 3px 10px;
|
|
165
|
-
background: transparent;
|
|
166
|
-
color: var(--ui-ink);
|
|
167
|
-
font: inherit;
|
|
168
|
-
font-size: 12px;
|
|
169
|
-
cursor: pointer;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
button.chip[aria-pressed='true'] {
|
|
173
|
-
background: var(--ui-surface-raised, var(--md-sys-color-surface-variant));
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
button.chip[aria-pressed='false'] {
|
|
177
|
-
opacity: 0.6;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
button.chip .warn {
|
|
181
|
-
color: var(--md-sys-color-error);
|
|
182
|
-
font-size: 11px;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
157
|
ox-event-view {
|
|
186
158
|
flex: 1;
|
|
187
159
|
padding: 10px;
|
|
@@ -206,12 +178,19 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
206
178
|
${
|
|
207
179
|
/* One kind alone has nothing to filter. */
|
|
208
180
|
this.kinds.length > 1
|
|
209
|
-
? html `<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
? html `<ox-input-select-buttons
|
|
182
|
+
multiple
|
|
183
|
+
role="group"
|
|
184
|
+
aria-label=${i18next.t('label.calendar-kinds')}
|
|
185
|
+
style="--ox-input-select-buttons-label-text-transform: none"
|
|
186
|
+
.value=${this.kinds.map(kind => kind.key).filter(key => !this.turnedOff.has(key))}
|
|
187
|
+
.options=${this.kinds.map(kind =>
|
|
188
|
+
/* A kind not read has no number to say - its chip says it was not read instead. */
|
|
189
|
+
this.failed.includes(kind.key)
|
|
190
|
+
? { value: kind.key, display: `${kind.label()} · ${i18next.t('text.calendar-kind-not-loaded')}` }
|
|
191
|
+
: { value: kind.key, display: kind.label(), count: this.counts.get(kind.key) ?? 0 })}
|
|
192
|
+
@change=${(e) => this.showOnly(e.detail ?? [])}
|
|
193
|
+
></ox-input-select-buttons>`
|
|
215
194
|
: ''}
|
|
216
195
|
<ox-event-view class="page-fill" mode="monthly" .eventProvider=${this.provider}></ox-event-view>
|
|
217
196
|
`;
|
|
@@ -228,13 +207,9 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
228
207
|
fetchDayStatesForCalendar: calendar => this.fetchDayStatesForCalendar(calendar)
|
|
229
208
|
};
|
|
230
209
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
next.delete(key);
|
|
235
|
-
else
|
|
236
|
-
next.add(key);
|
|
237
|
-
this.turnedOff = next;
|
|
210
|
+
/** Show the kinds chosen; every other kind is turned off. */
|
|
211
|
+
showOnly(shown) {
|
|
212
|
+
this.turnedOff = new Set(this.kinds.map(kind => kind.key).filter(key => !shown.includes(key)));
|
|
238
213
|
this.provider = this.calendarProvider();
|
|
239
214
|
}
|
|
240
215
|
/**
|
|
@@ -259,16 +234,18 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
259
234
|
const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000);
|
|
260
235
|
/*
|
|
261
236
|
* worklist's own and every shown source, asked apart: one that fails leaves the others on the grid, and the band
|
|
262
|
-
* above it says something was not read - never a day with nothing on it. A kind turned off is
|
|
237
|
+
* above it says something was not read - never a day with nothing on it. A kind turned off is still asked: its chip
|
|
238
|
+
* says how many it has on these days, and only its entries are left off the grid.
|
|
263
239
|
*/
|
|
264
|
-
const
|
|
265
|
-
const { entries, failed } = await loadWorkCalendar([
|
|
266
|
-
...(
|
|
240
|
+
const kinds = new Set(this.kinds.map(kind => kind.key));
|
|
241
|
+
const { entries, counts, failed } = await loadWorkCalendar([
|
|
242
|
+
...(kinds.has(OWN) ? [[OWN, this.activityEntries(fromDate.toISOString(), toDate.toISOString())]] : []),
|
|
267
243
|
...workCalendarSources()
|
|
268
|
-
.filter(source =>
|
|
244
|
+
.filter(source => kinds.has(source.key))
|
|
269
245
|
.map(source => [source.key, source.load(fromDate, toDate)])
|
|
270
|
-
]);
|
|
246
|
+
], this.turnedOff);
|
|
271
247
|
this.failed = failed;
|
|
248
|
+
this.counts = counts;
|
|
272
249
|
const eventMap = new Map();
|
|
273
250
|
calendar.forEach(({ date }) => {
|
|
274
251
|
const localDateString = date.toLocaleDateString();
|
|
@@ -387,6 +364,10 @@ __decorate([
|
|
|
387
364
|
state(),
|
|
388
365
|
__metadata("design:type", Object)
|
|
389
366
|
], DoneListCalendarPage.prototype, "turnedOff", void 0);
|
|
367
|
+
__decorate([
|
|
368
|
+
state(),
|
|
369
|
+
__metadata("design:type", Object)
|
|
370
|
+
], DoneListCalendarPage.prototype, "counts", void 0);
|
|
390
371
|
__decorate([
|
|
391
372
|
state(),
|
|
392
373
|
__metadata("design:type", Object)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"done-list-calendar-page.js","sourceRoot":"","sources":["../../../client/pages/todo/done-list-calendar-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/event-view/ox-event-view.js'\n\nimport { PropertyValues, html, css } from 'lit'\nimport gql from 'graphql-tag'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { OxEventView } from '@operato/event-view'\nimport { ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { BizEvent, CALENDAR, EventProvider } from '@operato/event-view/types.js'\n\nimport { applyingSources, entriesOfDay, loadWorkCalendar, nonWorkingStates, workCalendarSources, type WorkCalendarEntry } from '../../work-calendar-sources.js'\n\n/** The chip of worklist's own entries - my to-dos and approvals - beside the registered sources' chips. */\nconst OWN = 'worklist'\n\n/** Priority 0..3. Anything outside the range clamps to the most urgent colour. */\nconst PRIORITY_COLORS = ['black', 'darkgray', 'orange', 'red']\n\n/**\n * Which mark a finished item wears.\n *\n * Pending is the one that is not finished, and it reads as an empty circle: every filled mark on\n * this calendar means \"over\", so a pending item must not borrow one.\n *\n * A state this function does not know draws nothing. The old expression ended in\n * `: 'assignment_return'`, so anything unrecognised became sent-back — and Aborted, added to\n * ActivityEventStatus alongside this change, would have landed there. An icon the screen cannot\n * vouch for is worse than a blank, because the reader cannot tell an invented mark from a reported\n * one.\n *\n * The case fold is a guard, not a fix for anything observed here. ActivityEvent.state is declared\n * `@Field({ nullable: true })` with no explicit type, so type-graphql reflects it as String and the\n * wire carries the enum's value — lowercase, as this function reads it. Declaring it\n * `@Field(type => ActivityEventStatus)` instead is a one-word edit that would silently switch the\n * wire to the enum's **keys**: registerEnumType publishes by key. That switch is not hypothetical.\n * It is what organization/client/types/approval-line.ts hit, where `participation` is declared as\n * the enum, arrives as `Reference`, and was compared against `reference` — false every time, for\n * as long as the check had existed.\n */\nfunction eventIcon(state?: string, basis?: string): string {\n switch (String(state || '').toLowerCase()) {\n /*\n * 안 끝난 것은 **좌표가 표를 정한다.**\n *\n * 기한으로 놓인 것은 시계다 — 「이 날까지」. 기한이 없어 받은 날에 놓인 것은 받은 함이다 —\n * 「이 날 왔다」. 둘을 같은 표로 그리면 한 칸 안에서 구별이 안 되고, 결재자가 기한을 도착으로\n * 읽고 지나치거나 도착을 기한으로 읽고 한 주를 헛되이 다시 짠다.\n *\n * 손댈 곳이 화면뿐이라 화면이 갈라야 한다 — 여기 오면 둘 다 그냥 date 다.\n */\n case 'pending':\n return String(basis || '').toLowerCase() == 'handed-over' ? 'move_to_inbox' : 'schedule'\n case 'done':\n return 'done'\n /* Given up on, not finished. A different mark, not a missing one. */\n case 'aborted':\n return 'block'\n case 'approved':\n return 'done_all'\n case 'rejected':\n return 'assignment_return'\n default:\n return ''\n }\n}\n\n/**\n * 한 칸에 몇 줄까지.\n *\n * 이 화면은 monthly 만 쓴다. 넘치는 것을 줄로 늘리면 칸이 커지고 뒷주가 화면 밖으로 밀린다 —\n * plant 달력이 하루 스물다섯 건에서 실제로 그렇게 됐다. 넘치면 수로 말한다.\n */\nconst MOST_PER_DAY = 4\n\n/** 급한 것이 앞이다 — 기한 걸린 것 · 받아 둔 것 · 끝난 것. */\nfunction rank(event: { state?: string; basis?: string }): number {\n if (String(event.state || '').toLowerCase() != 'pending') {\n return 2\n }\n\n return String(event.basis || '').toLowerCase() == 'handed-over' ? 1 : 0\n}\n\n/** 이 날짜가 무슨 뜻인지 — 표만으로 못 읽는 사람을 위해 한 줄로. */\nfunction basisText(state?: string, basis?: string): string {\n if (String(state || '').toLowerCase() != 'pending') {\n return i18next.t('text.finished-on-this-day')\n }\n\n return String(basis || '').toLowerCase() == 'handed-over'\n ? i18next.t('text.handed-over-on-this-day')\n : i18next.t('text.due-on-this-day')\n}\n\n/**\n * 물은 것을 실제로 받았나 — **아니면 던진다.**\n *\n * 이 앱의 Apollo client 는 `errorPolicy: 'all'` 로 서 있다\n * ([읽었음] operato/webcomponents/graphql/src/graphql-client.ts:15). 질의가 실패해도 **거절되지\n * 않는다.** `errors` 를 실은 응답이 오고 `data` 는 비거나 반만 찬다.\n *\n * 그래서 `if (response.data)` 로 읽으면 실패가 **빈 목록과 구별되지 않는다.** 달력에서 그것은\n * 「이번 달에 아무것도 없다」로 그려진다 — 결재자에게 할 일이 없다고 말하는 것이라 값이 비싸다.\n * 못 불러온 것과 없는 것은 다른 사실이고, 화면은 그 둘을 절대 섞으면 안 된다.\n *\n * plant 레인이 자기 달력에서 같은 구멍을 재서 알려 줬다 — 요청만 실패시키고 화면을 보니 칩은\n * 그대로인 채 그 층만 빈 채로 그려졌다.\n */\nfunction askedFor<T>(response: { data?: any; errors?: readonly unknown[] }, field: string): T[] {\n if (response.errors?.length) {\n throw new Error(`[activityEvents] ${JSON.stringify(response.errors)}`)\n }\n\n const value = response.data?.[field]\n\n if (!Array.isArray(value)) {\n throw new Error(`[activityEvents] \"${field}\" is missing from the response`)\n }\n\n return value as T[]\n}\n\n@customElement('done-list-calendar-page')\nexport class DoneListCalendarPage extends localize(i18next)(PageView) {\n static styles = [\n /* The frame owns the page shell; the calendar is the content it sizes (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n css`\n :host {\n color: var(--md-sys-color-on-background);\n }\n\n /* 못 불러왔다는 말은 달력 위에 선다 — 빈 달력만 보고 「없구나」 하고 닫지 않도록. */\n .failed {\n display: flex;\n align-items: center;\n gap: 6px;\n\n margin: 10px 10px 0 10px;\n padding: 8px 10px;\n border-radius: 6px;\n\n background-color: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n font-size: var(--ui-t-body, 13px);\n }\n\n .failed md-icon {\n font-size: 1.2em;\n }\n\n /* What is on the calendar - each chip shows or hides one kind, the way the factory calendar's do. */\n .filters {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n margin: 10px 10px 0 10px;\n }\n\n button.chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: 1px solid var(--ui-line);\n border-radius: 999px;\n padding: 3px 10px;\n background: transparent;\n color: var(--ui-ink);\n font: inherit;\n font-size: 12px;\n cursor: pointer;\n }\n\n button.chip[aria-pressed='true'] {\n background: var(--ui-surface-raised, var(--md-sys-color-surface-variant));\n }\n\n button.chip[aria-pressed='false'] {\n opacity: 0.6;\n }\n\n button.chip .warn {\n color: var(--md-sys-color-error);\n font-size: 11px;\n }\n\n ox-event-view {\n flex: 1;\n padding: 10px;\n overflow: auto;\n }\n `\n ]\n\n @query('ox-event-view') eventView!: OxEventView\n\n /** 못 불러온 것들의 key — 「없다」와 절대 섞지 않는다. 하나라도 있으면 화면이 그렇게 말하고, 그 칩이 자기라고 말한다. */\n @state() failed: string[] = []\n\n /** The chips - worklist's own and every source that has anything for this person. */\n @state() kinds: { key: string; label: () => string }[] = []\n\n /** The kinds turned off. */\n @state() turnedOff = new Set<string>()\n\n /** A new object whenever what is shown changes - the calendar asks again only when it is handed a different one. */\n @state() provider?: EventProvider\n\n get context() {\n return {\n title: i18next.t('title.my work calendar'),\n help: 'worklist/done-list-calendar-page'\n }\n }\n\n render() {\n return html`\n ${\n this.failed.length\n ? html`<div class=\"failed\" role=\"alert\">\n <md-icon>cloud_off</md-icon>\n <span>${i18next.t('text.calendar-not-loaded')}</span>\n </div>`\n : ''\n }\n ${\n /* One kind alone has nothing to filter. */\n this.kinds.length > 1\n ? html`<div class=\"filters\" role=\"group\" aria-label=${i18next.t('label.calendar-kinds')}>\n ${this.kinds.map(\n kind => html`<button class=\"chip\" aria-pressed=${!this.turnedOff.has(kind.key)} @click=${() => this.toggle(kind.key)}>\n ${kind.label()}\n ${this.failed.includes(kind.key) ? html`<span class=\"warn\">${i18next.t('text.calendar-kind-not-loaded')}</span>` : ''}\n </button>`\n )}\n </div>`\n : ''\n }\n <ox-event-view class=\"page-fill\" mode=\"monthly\" .eventProvider=${this.provider}></ox-event-view>\n `\n }\n\n /** The chips are known once - which sources have anything for this person - and then the calendar is asked. */\n async firstUpdated() {\n const sources = await applyingSources(workCalendarSources())\n this.kinds = [{ key: OWN, label: () => i18next.t('label.calendar-my-work') }, ...sources.map(source => ({ key: source.key, label: () => source.label() }))]\n this.provider = this.calendarProvider()\n }\n\n private calendarProvider(): EventProvider {\n return {\n fetchEventsForCalendar: calendar => this.fetchEventsForCalendar(calendar),\n fetchDayStatesForCalendar: calendar => this.fetchDayStatesForCalendar(calendar)\n }\n }\n\n private toggle(key: string) {\n const next = new Set(this.turnedOff)\n if (next.has(key)) next.delete(key)\n else next.add(key)\n this.turnedOff = next\n this.provider = this.calendarProvider()\n }\n\n /**\n * The days not worked, painted - asked of every source that says them, chip on or off. One that cannot answer paints\n * nothing and is logged; the entries still come.\n */\n async fetchDayStatesForCalendar(calendar: CALENDAR) {\n const fromDate = calendar[0].date\n const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000)\n const answers = await Promise.allSettled(workCalendarSources().filter(source => source.nonWorkingDays).map(source => source.nonWorkingDays!(fromDate, toDate)))\n const notWorked = new Set<string>()\n for (const answer of answers) {\n if (answer.status === 'fulfilled') answer.value.forEach(day => notWorked.add(day))\n else console.error(answer.reason)\n }\n return nonWorkingStates(calendar, notWorked)\n }\n\n async fetchEventsForCalendar(calendar: CALENDAR): Promise<Map<Date, BizEvent[]>> {\n const fromDate = calendar[0].date\n const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000)\n\n /*\n * worklist's own and every shown source, asked apart: one that fails leaves the others on the grid, and the band\n * above it says something was not read - never a day with nothing on it. A kind turned off is not asked at all.\n */\n const shown = new Set(this.kinds.map(kind => kind.key).filter(key => !this.turnedOff.has(key)))\n const { entries, failed } = await loadWorkCalendar([\n ...(shown.has(OWN) ? [[OWN, this.activityEntries(fromDate.toISOString(), toDate.toISOString())] as [string, Promise<WorkCalendarEntry[]>]] : []),\n ...workCalendarSources()\n .filter(source => shown.has(source.key))\n .map(source => [source.key, source.load(fromDate, toDate)] as [string, Promise<WorkCalendarEntry[]>])\n ])\n this.failed = failed\n\n const eventMap = new Map<Date, BizEvent[]>()\n\n calendar.forEach(({ date }) => {\n const localDateString = date.toLocaleDateString()\n\n /*\n * **자르기 전에 차례를 세운다.** 상한만 두고 자르면 먼저 온 순서로 잘린다 — 기한이 걸린\n * 결재 한 건이 끝난 스무 건 뒤에 묻히면 「+20건 더」만 보이고, 그 날 할 일이 있다는 것을\n * 아무도 못 본다. 급한 것이 앞이다: 그날 할 것(기한·회의) → 받은 날에 놓인 것 → 끝난 것.\n */\n const { shown: shownOfDay, hidden } = entriesOfDay(entries, localDateString, MOST_PER_DAY)\n\n const events: BizEvent[] = shownOfDay.map(({ name, priority, date, icon, href, note, allDay }) => {\n const color = PRIORITY_COLORS[Math.min(Math.max(priority || 0, 0), PRIORITY_COLORS.length - 1)]\n /* A whole day has no time - 「00:00」 before a day of leave would say a time nobody set. */\n const at = allDay\n ? ''\n : html`${new Date(date).toLocaleTimeString([], {\n hourCycle: 'h23',\n hour: '2-digit',\n minute: '2-digit'\n })} `\n const body = html`${icon ? html`<md-icon style=\"font-size:1em;\">${icon}</md-icon> ` : ''}${at}${name}`\n\n return {\n /*\n * BizEvent 는 title · color 를 요구한다. 그리는 것은 template 이지만, 부품이 template\n * 없이 그리는 길로 갈 때 쓰는 값이라 비워 두지 않는다 — 그때 이름 없는 칸이 뜬다.\n */\n title: name,\n color,\n /* 열 수 없는 것은 링크가 아니다 — 눌러도 아무것도 못 하는 곳으로 보내지 않는다. */\n template: href\n ? html`<a href=${href} title=${note ?? ''} style=\"color:${color};display:block;text-decoration:none;\">${body}</a>`\n : html`<span title=${note ?? ''} style=\"color:${color};display:block;\">${body}</span>`\n }\n })\n\n if (hidden > 0) {\n /* 넘치면 **수로 말한다** — 줄을 늘리면 뒷주가 화면 밖으로 밀린다. */\n const more = i18next.t('text.and-n-more', { n: hidden })\n events.push({\n title: more,\n color: 'inherit',\n template: html`<span style=\"opacity:0.7\">${more}</span>`\n })\n }\n\n /*\n * **키는 받은 그 Date 객체 그대로다.** 같은 날을 새로 만들어 넣으면 조회가 빗나가고 그 칸이\n * 빈 채로 그려진다 — 오류는 안 난다.\n */\n eventMap.set(date, events)\n })\n\n return eventMap\n }\n\n /** worklist's own - my to-dos and approvals, open and finished - as calendar entries. */\n private async activityEntries(from: string, to: string): Promise<WorkCalendarEntry[]> {\n const response = await client.query({\n query: gql`\n query ($from: String!, $to: String!) {\n responses: activityEvents(from: $from, to: $to) {\n id\n name\n type\n state\n basis\n priority\n date\n }\n }\n `,\n variables: { from, to }\n })\n\n return askedFor<any>(response, 'responses').map(({ id, name, type, state, basis, priority, date }) => {\n /*\n * 안 끝난 것은 **하는 화면**으로 간다.\n *\n * activity-thread-view 는 끝난 업무를 읽는 화면이다. 아직 할 일을 거기로 보내면 손댈\n * 데가 없는 화면에 도착한다 — 달력에서 눌렀는데 아무것도 못 한다.\n */\n const pending = String(state || '').toLowerCase() == 'pending'\n const path = type == 'activity-thread' ? (pending ? 'activity-thread' : 'activity-thread-view') : 'activity-approval'\n return {\n id: `${type}:${id}`,\n name,\n date,\n rank: rank({ state, basis }) as 0 | 1 | 2,\n priority,\n icon: eventIcon(state, basis),\n href: `${path}/${id}?title=${encodeURIComponent(name)}`,\n note: basisText(state, basis)\n }\n })\n }\n\n pageUpdated(changes: any, lifecycle: any, before: any) {\n if (this.active) {\n /*\n * this page is activated\n */\n } else {\n /* this page is deactivated */\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"done-list-calendar-page.js","sourceRoot":"","sources":["../../../client/pages/todo/done-list-calendar-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/event-view/ox-event-view.js'\nimport '@operato/input/ox-input-select-buttons.js'\n\nimport { PropertyValues, html, css } from 'lit'\nimport gql from 'graphql-tag'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { OxEventView } from '@operato/event-view'\nimport { ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { BizEvent, CALENDAR, EventProvider } from '@operato/event-view/types.js'\n\nimport { applyingSources, entriesOfDay, loadWorkCalendar, nonWorkingStates, workCalendarSources, type WorkCalendarEntry } from '../../work-calendar-sources.js'\n\n/** The chip of worklist's own entries - my to-dos and approvals - beside the registered sources' chips. */\nconst OWN = 'worklist'\n\n/** Priority 0..3. Anything outside the range clamps to the most urgent colour. */\nconst PRIORITY_COLORS = ['black', 'darkgray', 'orange', 'red']\n\n/**\n * Which mark a finished item wears.\n *\n * Pending is the one that is not finished, and it reads as an empty circle: every filled mark on\n * this calendar means \"over\", so a pending item must not borrow one.\n *\n * A state this function does not know draws nothing. The old expression ended in\n * `: 'assignment_return'`, so anything unrecognised became sent-back — and Aborted, added to\n * ActivityEventStatus alongside this change, would have landed there. An icon the screen cannot\n * vouch for is worse than a blank, because the reader cannot tell an invented mark from a reported\n * one.\n *\n * The case fold is a guard, not a fix for anything observed here. ActivityEvent.state is declared\n * `@Field({ nullable: true })` with no explicit type, so type-graphql reflects it as String and the\n * wire carries the enum's value — lowercase, as this function reads it. Declaring it\n * `@Field(type => ActivityEventStatus)` instead is a one-word edit that would silently switch the\n * wire to the enum's **keys**: registerEnumType publishes by key. That switch is not hypothetical.\n * It is what organization/client/types/approval-line.ts hit, where `participation` is declared as\n * the enum, arrives as `Reference`, and was compared against `reference` — false every time, for\n * as long as the check had existed.\n */\nfunction eventIcon(state?: string, basis?: string): string {\n switch (String(state || '').toLowerCase()) {\n /*\n * 안 끝난 것은 **좌표가 표를 정한다.**\n *\n * 기한으로 놓인 것은 시계다 — 「이 날까지」. 기한이 없어 받은 날에 놓인 것은 받은 함이다 —\n * 「이 날 왔다」. 둘을 같은 표로 그리면 한 칸 안에서 구별이 안 되고, 결재자가 기한을 도착으로\n * 읽고 지나치거나 도착을 기한으로 읽고 한 주를 헛되이 다시 짠다.\n *\n * 손댈 곳이 화면뿐이라 화면이 갈라야 한다 — 여기 오면 둘 다 그냥 date 다.\n */\n case 'pending':\n return String(basis || '').toLowerCase() == 'handed-over' ? 'move_to_inbox' : 'schedule'\n case 'done':\n return 'done'\n /* Given up on, not finished. A different mark, not a missing one. */\n case 'aborted':\n return 'block'\n case 'approved':\n return 'done_all'\n case 'rejected':\n return 'assignment_return'\n default:\n return ''\n }\n}\n\n/**\n * 한 칸에 몇 줄까지.\n *\n * 이 화면은 monthly 만 쓴다. 넘치는 것을 줄로 늘리면 칸이 커지고 뒷주가 화면 밖으로 밀린다 —\n * plant 달력이 하루 스물다섯 건에서 실제로 그렇게 됐다. 넘치면 수로 말한다.\n */\nconst MOST_PER_DAY = 4\n\n/** 급한 것이 앞이다 — 기한 걸린 것 · 받아 둔 것 · 끝난 것. */\nfunction rank(event: { state?: string; basis?: string }): number {\n if (String(event.state || '').toLowerCase() != 'pending') {\n return 2\n }\n\n return String(event.basis || '').toLowerCase() == 'handed-over' ? 1 : 0\n}\n\n/** 이 날짜가 무슨 뜻인지 — 표만으로 못 읽는 사람을 위해 한 줄로. */\nfunction basisText(state?: string, basis?: string): string {\n if (String(state || '').toLowerCase() != 'pending') {\n return i18next.t('text.finished-on-this-day')\n }\n\n return String(basis || '').toLowerCase() == 'handed-over'\n ? i18next.t('text.handed-over-on-this-day')\n : i18next.t('text.due-on-this-day')\n}\n\n/**\n * 물은 것을 실제로 받았나 — **아니면 던진다.**\n *\n * 이 앱의 Apollo client 는 `errorPolicy: 'all'` 로 서 있다\n * ([읽었음] operato/webcomponents/graphql/src/graphql-client.ts:15). 질의가 실패해도 **거절되지\n * 않는다.** `errors` 를 실은 응답이 오고 `data` 는 비거나 반만 찬다.\n *\n * 그래서 `if (response.data)` 로 읽으면 실패가 **빈 목록과 구별되지 않는다.** 달력에서 그것은\n * 「이번 달에 아무것도 없다」로 그려진다 — 결재자에게 할 일이 없다고 말하는 것이라 값이 비싸다.\n * 못 불러온 것과 없는 것은 다른 사실이고, 화면은 그 둘을 절대 섞으면 안 된다.\n *\n * plant 레인이 자기 달력에서 같은 구멍을 재서 알려 줬다 — 요청만 실패시키고 화면을 보니 칩은\n * 그대로인 채 그 층만 빈 채로 그려졌다.\n */\nfunction askedFor<T>(response: { data?: any; errors?: readonly unknown[] }, field: string): T[] {\n if (response.errors?.length) {\n throw new Error(`[activityEvents] ${JSON.stringify(response.errors)}`)\n }\n\n const value = response.data?.[field]\n\n if (!Array.isArray(value)) {\n throw new Error(`[activityEvents] \"${field}\" is missing from the response`)\n }\n\n return value as T[]\n}\n\n@customElement('done-list-calendar-page')\nexport class DoneListCalendarPage extends localize(i18next)(PageView) {\n static styles = [\n /* The frame owns the page shell; the calendar is the content it sizes (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n css`\n :host {\n color: var(--md-sys-color-on-background);\n }\n\n /* 못 불러왔다는 말은 달력 위에 선다 — 빈 달력만 보고 「없구나」 하고 닫지 않도록. */\n .failed {\n display: flex;\n align-items: center;\n gap: 6px;\n\n margin: 10px 10px 0 10px;\n padding: 8px 10px;\n border-radius: 6px;\n\n background-color: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n font-size: var(--ui-t-body, 13px);\n }\n\n .failed md-icon {\n font-size: 1.2em;\n }\n\n /* What is on the calendar - each chip shows or hides one kind, with how many it has on the days drawn. */\n ox-input-select-buttons {\n margin: 10px 10px 0 10px;\n }\n\n ox-event-view {\n flex: 1;\n padding: 10px;\n overflow: auto;\n }\n `\n ]\n\n @query('ox-event-view') eventView!: OxEventView\n\n /** 못 불러온 것들의 key — 「없다」와 절대 섞지 않는다. 하나라도 있으면 화면이 그렇게 말하고, 그 칩이 자기라고 말한다. */\n @state() failed: string[] = []\n\n /** The chips - worklist's own and every source that has anything for this person. */\n @state() kinds: { key: string; label: () => string }[] = []\n\n /** The kinds turned off. */\n @state() turnedOff = new Set<string>()\n\n /** How many each kind has on the days drawn, its chip on or off. */\n @state() counts = new Map<string, number>()\n\n /** A new object whenever what is shown changes - the calendar asks again only when it is handed a different one. */\n @state() provider?: EventProvider\n\n get context() {\n return {\n title: i18next.t('title.my work calendar'),\n help: 'worklist/done-list-calendar-page'\n }\n }\n\n render() {\n return html`\n ${\n this.failed.length\n ? html`<div class=\"failed\" role=\"alert\">\n <md-icon>cloud_off</md-icon>\n <span>${i18next.t('text.calendar-not-loaded')}</span>\n </div>`\n : ''\n }\n ${\n /* One kind alone has nothing to filter. */\n this.kinds.length > 1\n ? html`<ox-input-select-buttons\n multiple\n role=\"group\"\n aria-label=${i18next.t('label.calendar-kinds')}\n style=\"--ox-input-select-buttons-label-text-transform: none\"\n .value=${this.kinds.map(kind => kind.key).filter(key => !this.turnedOff.has(key))}\n .options=${this.kinds.map(kind =>\n /* A kind not read has no number to say - its chip says it was not read instead. */\n this.failed.includes(kind.key)\n ? { value: kind.key, display: `${kind.label()} · ${i18next.t('text.calendar-kind-not-loaded')}` }\n : { value: kind.key, display: kind.label(), count: this.counts.get(kind.key) ?? 0 }\n )}\n @change=${(e: CustomEvent) => this.showOnly((e.detail as string[]) ?? [])}\n ></ox-input-select-buttons>`\n : ''\n }\n <ox-event-view class=\"page-fill\" mode=\"monthly\" .eventProvider=${this.provider}></ox-event-view>\n `\n }\n\n /** The chips are known once - which sources have anything for this person - and then the calendar is asked. */\n async firstUpdated() {\n const sources = await applyingSources(workCalendarSources())\n this.kinds = [{ key: OWN, label: () => i18next.t('label.calendar-my-work') }, ...sources.map(source => ({ key: source.key, label: () => source.label() }))]\n this.provider = this.calendarProvider()\n }\n\n private calendarProvider(): EventProvider {\n return {\n fetchEventsForCalendar: calendar => this.fetchEventsForCalendar(calendar),\n fetchDayStatesForCalendar: calendar => this.fetchDayStatesForCalendar(calendar)\n }\n }\n\n /** Show the kinds chosen; every other kind is turned off. */\n private showOnly(shown: string[]) {\n this.turnedOff = new Set(this.kinds.map(kind => kind.key).filter(key => !shown.includes(key)))\n this.provider = this.calendarProvider()\n }\n\n /**\n * The days not worked, painted - asked of every source that says them, chip on or off. One that cannot answer paints\n * nothing and is logged; the entries still come.\n */\n async fetchDayStatesForCalendar(calendar: CALENDAR) {\n const fromDate = calendar[0].date\n const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000)\n const answers = await Promise.allSettled(workCalendarSources().filter(source => source.nonWorkingDays).map(source => source.nonWorkingDays!(fromDate, toDate)))\n const notWorked = new Set<string>()\n for (const answer of answers) {\n if (answer.status === 'fulfilled') answer.value.forEach(day => notWorked.add(day))\n else console.error(answer.reason)\n }\n return nonWorkingStates(calendar, notWorked)\n }\n\n async fetchEventsForCalendar(calendar: CALENDAR): Promise<Map<Date, BizEvent[]>> {\n const fromDate = calendar[0].date\n const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000)\n\n /*\n * worklist's own and every shown source, asked apart: one that fails leaves the others on the grid, and the band\n * above it says something was not read - never a day with nothing on it. A kind turned off is still asked: its chip\n * says how many it has on these days, and only its entries are left off the grid.\n */\n const kinds = new Set(this.kinds.map(kind => kind.key))\n const { entries, counts, failed } = await loadWorkCalendar(\n [\n ...(kinds.has(OWN) ? [[OWN, this.activityEntries(fromDate.toISOString(), toDate.toISOString())] as [string, Promise<WorkCalendarEntry[]>]] : []),\n ...workCalendarSources()\n .filter(source => kinds.has(source.key))\n .map(source => [source.key, source.load(fromDate, toDate)] as [string, Promise<WorkCalendarEntry[]>])\n ],\n this.turnedOff\n )\n this.failed = failed\n this.counts = counts\n\n const eventMap = new Map<Date, BizEvent[]>()\n\n calendar.forEach(({ date }) => {\n const localDateString = date.toLocaleDateString()\n\n /*\n * **자르기 전에 차례를 세운다.** 상한만 두고 자르면 먼저 온 순서로 잘린다 — 기한이 걸린\n * 결재 한 건이 끝난 스무 건 뒤에 묻히면 「+20건 더」만 보이고, 그 날 할 일이 있다는 것을\n * 아무도 못 본다. 급한 것이 앞이다: 그날 할 것(기한·회의) → 받은 날에 놓인 것 → 끝난 것.\n */\n const { shown: shownOfDay, hidden } = entriesOfDay(entries, localDateString, MOST_PER_DAY)\n\n const events: BizEvent[] = shownOfDay.map(({ name, priority, date, icon, href, note, allDay }) => {\n const color = PRIORITY_COLORS[Math.min(Math.max(priority || 0, 0), PRIORITY_COLORS.length - 1)]\n /* A whole day has no time - 「00:00」 before a day of leave would say a time nobody set. */\n const at = allDay\n ? ''\n : html`${new Date(date).toLocaleTimeString([], {\n hourCycle: 'h23',\n hour: '2-digit',\n minute: '2-digit'\n })} `\n const body = html`${icon ? html`<md-icon style=\"font-size:1em;\">${icon}</md-icon> ` : ''}${at}${name}`\n\n return {\n /*\n * BizEvent 는 title · color 를 요구한다. 그리는 것은 template 이지만, 부품이 template\n * 없이 그리는 길로 갈 때 쓰는 값이라 비워 두지 않는다 — 그때 이름 없는 칸이 뜬다.\n */\n title: name,\n color,\n /* 열 수 없는 것은 링크가 아니다 — 눌러도 아무것도 못 하는 곳으로 보내지 않는다. */\n template: href\n ? html`<a href=${href} title=${note ?? ''} style=\"color:${color};display:block;text-decoration:none;\">${body}</a>`\n : html`<span title=${note ?? ''} style=\"color:${color};display:block;\">${body}</span>`\n }\n })\n\n if (hidden > 0) {\n /* 넘치면 **수로 말한다** — 줄을 늘리면 뒷주가 화면 밖으로 밀린다. */\n const more = i18next.t('text.and-n-more', { n: hidden })\n events.push({\n title: more,\n color: 'inherit',\n template: html`<span style=\"opacity:0.7\">${more}</span>`\n })\n }\n\n /*\n * **키는 받은 그 Date 객체 그대로다.** 같은 날을 새로 만들어 넣으면 조회가 빗나가고 그 칸이\n * 빈 채로 그려진다 — 오류는 안 난다.\n */\n eventMap.set(date, events)\n })\n\n return eventMap\n }\n\n /** worklist's own - my to-dos and approvals, open and finished - as calendar entries. */\n private async activityEntries(from: string, to: string): Promise<WorkCalendarEntry[]> {\n const response = await client.query({\n query: gql`\n query ($from: String!, $to: String!) {\n responses: activityEvents(from: $from, to: $to) {\n id\n name\n type\n state\n basis\n priority\n date\n }\n }\n `,\n variables: { from, to }\n })\n\n return askedFor<any>(response, 'responses').map(({ id, name, type, state, basis, priority, date }) => {\n /*\n * 안 끝난 것은 **하는 화면**으로 간다.\n *\n * activity-thread-view 는 끝난 업무를 읽는 화면이다. 아직 할 일을 거기로 보내면 손댈\n * 데가 없는 화면에 도착한다 — 달력에서 눌렀는데 아무것도 못 한다.\n */\n const pending = String(state || '').toLowerCase() == 'pending'\n const path = type == 'activity-thread' ? (pending ? 'activity-thread' : 'activity-thread-view') : 'activity-approval'\n return {\n id: `${type}:${id}`,\n name,\n date,\n rank: rank({ state, basis }) as 0 | 1 | 2,\n priority,\n icon: eventIcon(state, basis),\n href: `${path}/${id}?title=${encodeURIComponent(name)}`,\n note: basisText(state, basis)\n }\n })\n }\n\n pageUpdated(changes: any, lifecycle: any, before: any) {\n if (this.active) {\n /*\n * this page is activated\n */\n } else {\n /* this page is deactivated */\n }\n }\n}\n"]}
|