@things-factory/worklist 10.1.234 → 10.1.236
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/pages/todo/done-list-calendar-page.d.ts +8 -0
- package/dist-client/pages/todo/done-list-calendar-page.js +22 -2
- package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/work-calendar-sources.d.ts +20 -0
- package/dist-client/work-calendar-sources.js +20 -0
- package/dist-client/work-calendar-sources.js.map +1 -1
- package/package.json +5 -5
|
@@ -27,6 +27,14 @@ export declare class DoneListCalendarPage extends DoneListCalendarPage_base {
|
|
|
27
27
|
firstUpdated(): Promise<void>;
|
|
28
28
|
private calendarProvider;
|
|
29
29
|
private toggle;
|
|
30
|
+
/**
|
|
31
|
+
* The days not worked, painted - asked of every source that says them, chip on or off. One that cannot answer paints
|
|
32
|
+
* nothing and is logged; the entries still come.
|
|
33
|
+
*/
|
|
34
|
+
fetchDayStatesForCalendar(calendar: CALENDAR): Promise<Map<Date, {
|
|
35
|
+
readonly name: "non-working";
|
|
36
|
+
readonly color: "var(--calendar-day-state-non-working-background-color, rgba(168, 48, 110, 0.1))";
|
|
37
|
+
}>>;
|
|
30
38
|
fetchEventsForCalendar(calendar: CALENDAR): Promise<Map<Date, BizEvent[]>>;
|
|
31
39
|
/** worklist's own - my to-dos and approvals, open and finished - as calendar entries. */
|
|
32
40
|
private activityEntries;
|
|
@@ -9,7 +9,7 @@ import { client } from '@operato/graphql';
|
|
|
9
9
|
import { i18next, localize } from '@operato/i18n';
|
|
10
10
|
import { OxEventView } from '@operato/event-view';
|
|
11
11
|
import { ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
|
|
12
|
-
import { applyingSources, entriesOfDay, loadWorkCalendar, workCalendarSources } from '../../work-calendar-sources.js';
|
|
12
|
+
import { applyingSources, entriesOfDay, loadWorkCalendar, nonWorkingStates, workCalendarSources } from '../../work-calendar-sources.js';
|
|
13
13
|
/** The chip of worklist's own entries - my to-dos and approvals - beside the registered sources' chips. */
|
|
14
14
|
const OWN = 'worklist';
|
|
15
15
|
/** Priority 0..3. Anything outside the range clamps to the most urgent colour. */
|
|
@@ -223,7 +223,10 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
223
223
|
this.provider = this.calendarProvider();
|
|
224
224
|
}
|
|
225
225
|
calendarProvider() {
|
|
226
|
-
return {
|
|
226
|
+
return {
|
|
227
|
+
fetchEventsForCalendar: calendar => this.fetchEventsForCalendar(calendar),
|
|
228
|
+
fetchDayStatesForCalendar: calendar => this.fetchDayStatesForCalendar(calendar)
|
|
229
|
+
};
|
|
227
230
|
}
|
|
228
231
|
toggle(key) {
|
|
229
232
|
const next = new Set(this.turnedOff);
|
|
@@ -234,6 +237,23 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
234
237
|
this.turnedOff = next;
|
|
235
238
|
this.provider = this.calendarProvider();
|
|
236
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* The days not worked, painted - asked of every source that says them, chip on or off. One that cannot answer paints
|
|
242
|
+
* nothing and is logged; the entries still come.
|
|
243
|
+
*/
|
|
244
|
+
async fetchDayStatesForCalendar(calendar) {
|
|
245
|
+
const fromDate = calendar[0].date;
|
|
246
|
+
const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000);
|
|
247
|
+
const answers = await Promise.allSettled(workCalendarSources().filter(source => source.nonWorkingDays).map(source => source.nonWorkingDays(fromDate, toDate)));
|
|
248
|
+
const notWorked = new Set();
|
|
249
|
+
for (const answer of answers) {
|
|
250
|
+
if (answer.status === 'fulfilled')
|
|
251
|
+
answer.value.forEach(day => notWorked.add(day));
|
|
252
|
+
else
|
|
253
|
+
console.error(answer.reason);
|
|
254
|
+
}
|
|
255
|
+
return nonWorkingStates(calendar, notWorked);
|
|
256
|
+
}
|
|
237
257
|
async fetchEventsForCalendar(calendar) {
|
|
238
258
|
const fromDate = calendar[0].date;
|
|
239
259
|
const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000);
|
|
@@ -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, 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 { fetchEventsForCalendar: calendar => this.fetchEventsForCalendar(calendar) }\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 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'\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"]}
|