@things-factory/worklist 10.1.258 → 10.1.260
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/chip-counts.d.ts +13 -0
- package/dist-client/chip-counts.js +11 -0
- package/dist-client/chip-counts.js.map +1 -1
- package/dist-client/chip-filters.d.ts +29 -0
- package/dist-client/chip-filters.js +17 -1
- package/dist-client/chip-filters.js.map +1 -1
- package/dist-client/pages/approval-progress/approval-progress-page.d.ts +0 -4
- package/dist-client/pages/approval-progress/approval-progress-page.js +37 -31
- package/dist-client/pages/approval-progress/approval-progress-page.js.map +1 -1
- package/dist-client/pages/todo/approval-pending-list-page.d.ts +2 -3
- package/dist-client/pages/todo/approval-pending-list-page.js +33 -47
- package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.js +13 -10
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/pages/todo/todo-list-page.d.ts +0 -3
- package/dist-client/pages/todo/todo-list-page.js +30 -42
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-installation/activity-installation-controller.js +1 -0
- package/dist-server/controllers/activity-installation/activity-installation-controller.js.map +1 -1
- package/dist-server/controllers/activity-installation/installable-to-activity.d.ts +10 -0
- package/dist-server/controllers/activity-installation/installable-to-activity.js +22 -1
- package/dist-server/controllers/activity-installation/installable-to-activity.js.map +1 -1
- package/dist-server/controllers/activity-instance/assign.js +7 -2
- package/dist-server/controllers/activity-instance/assign.js.map +1 -1
- package/dist-server/controllers/activity-instance/complete.d.ts +13 -0
- package/dist-server/controllers/activity-instance/complete.js +58 -0
- package/dist-server/controllers/activity-instance/complete.js.map +1 -0
- package/dist-server/controllers/activity-instance/index.d.ts +1 -0
- package/dist-server/controllers/activity-instance/index.js +1 -0
- package/dist-server/controllers/activity-instance/index.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval.d.ts +3 -0
- package/dist-server/service/activity-approval/activity-approval.js +8 -0
- package/dist-server/service/activity-approval/activity-approval.js.map +1 -1
- package/dist-server/service/activity-instance/event-subscriber.d.ts +1 -0
- package/dist-server/service/activity-instance/event-subscriber.js +11 -0
- package/dist-server/service/activity-instance/event-subscriber.js.map +1 -1
- package/dist-server/service/approval-notice/approval-notice.js +3 -2
- package/dist-server/service/approval-notice/approval-notice.js.map +1 -1
- package/dist-server/service/approval-progress/approval-progress-query.js +4 -0
- package/dist-server/service/approval-progress/approval-progress-query.js.map +1 -1
- package/dist-server/service/approval-progress/approval-progress-rule.d.ts +4 -0
- package/dist-server/service/approval-progress/approval-progress-rule.js +8 -0
- package/dist-server/service/approval-progress/approval-progress-rule.js.map +1 -1
- package/dist-server/service/approval-progress/approval-progress-type.d.ts +1 -0
- package/dist-server/service/approval-progress/approval-progress-type.js +4 -0
- package/dist-server/service/approval-progress/approval-progress-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/tests/assign-role-pool.test.ts +27 -1
- package/tests/complete-db.test.ts +62 -0
- package/translations/en.json +3 -2
- package/translations/es.json +3 -2
- package/translations/ja.json +3 -2
- package/translations/ko.json +3 -2
- package/translations/ms.json +3 -2
- package/translations/zh.json +3 -2
|
@@ -5,3 +5,16 @@
|
|
|
5
5
|
* makes and the door that totals the sets.
|
|
6
6
|
*/
|
|
7
7
|
export declare function chipCounts<F>(keys: readonly string[], filtersFor: (key: string) => F[], totals: (sets: F[][]) => Promise<number[]>): Promise<Record<string, number>>;
|
|
8
|
+
/** The grid column whose filter holds the chips pressed - kept in the address with the list's other conditions. */
|
|
9
|
+
export declare const CHIPS_FILTER = "chips";
|
|
10
|
+
/**
|
|
11
|
+
* The grid's filters split into the chips pressed (the `chips` filter, one or several) and the list's other
|
|
12
|
+
* conditions, which the chips' named conditions are added to. Pure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function splitChips<F extends {
|
|
15
|
+
name: string;
|
|
16
|
+
value?: unknown;
|
|
17
|
+
}>(filters: readonly F[]): {
|
|
18
|
+
chips: string[];
|
|
19
|
+
filters: F[];
|
|
20
|
+
};
|
|
@@ -8,4 +8,15 @@ export async function chipCounts(keys, filtersFor, totals) {
|
|
|
8
8
|
const counted = await totals(keys.map(key => filtersFor(key)));
|
|
9
9
|
return Object.fromEntries(keys.map((key, at) => [key, counted[at] ?? 0]));
|
|
10
10
|
}
|
|
11
|
+
/** The grid column whose filter holds the chips pressed - kept in the address with the list's other conditions. */
|
|
12
|
+
export const CHIPS_FILTER = 'chips';
|
|
13
|
+
/**
|
|
14
|
+
* The grid's filters split into the chips pressed (the `chips` filter, one or several) and the list's other
|
|
15
|
+
* conditions, which the chips' named conditions are added to. Pure.
|
|
16
|
+
*/
|
|
17
|
+
export function splitChips(filters) {
|
|
18
|
+
const chosen = filters.find(one => one.name === CHIPS_FILTER)?.value;
|
|
19
|
+
const chips = (Array.isArray(chosen) ? chosen : chosen ? [chosen] : []).map(String);
|
|
20
|
+
return { chips, filters: filters.filter(one => one.name !== CHIPS_FILTER) };
|
|
21
|
+
}
|
|
11
22
|
//# sourceMappingURL=chip-counts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chip-counts.js","sourceRoot":"","sources":["../client/chip-counts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,IAAuB,EAAE,UAAgC,EAAE,MAA0C;IACvI,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC9D,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3E,CAAC","sourcesContent":["/**\n * The numbers beside a list's condition chips (「중요」, 「만기」 ...): each is how many the list would show with that\n * chip pressed under the list's other conditions - the list's own door asked for its total, one set of filters per\n * chip, so the number is counted by the server exactly as the list is. Pure: the caller gives the filters each chip\n * makes and the door that totals the sets.\n */\nexport async function chipCounts<F>(keys: readonly string[], filtersFor: (key: string) => F[], totals: (sets: F[][]) => Promise<number[]>): Promise<Record<string, number>> {\n const counted = await totals(keys.map(key => filtersFor(key)))\n return Object.fromEntries(keys.map((key, at) => [key, counted[at] ?? 0]))\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chip-counts.js","sourceRoot":"","sources":["../client/chip-counts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,IAAuB,EAAE,UAAgC,EAAE,MAA0C;IACvI,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC9D,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED,mHAAmH;AACnH,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAA;AAEnC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAA8C,OAAqB;IAC3F,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,KAAK,CAAA;IACpE,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACnF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,CAAA;AAC7E,CAAC","sourcesContent":["/**\n * The numbers beside a list's condition chips (「중요」, 「만기」 ...): each is how many the list would show with that\n * chip pressed under the list's other conditions - the list's own door asked for its total, one set of filters per\n * chip, so the number is counted by the server exactly as the list is. Pure: the caller gives the filters each chip\n * makes and the door that totals the sets.\n */\nexport async function chipCounts<F>(keys: readonly string[], filtersFor: (key: string) => F[], totals: (sets: F[][]) => Promise<number[]>): Promise<Record<string, number>> {\n const counted = await totals(keys.map(key => filtersFor(key)))\n return Object.fromEntries(keys.map((key, at) => [key, counted[at] ?? 0]))\n}\n\n/** The grid column whose filter holds the chips pressed - kept in the address with the list's other conditions. */\nexport const CHIPS_FILTER = 'chips'\n\n/**\n * The grid's filters split into the chips pressed (the `chips` filter, one or several) and the list's other\n * conditions, which the chips' named conditions are added to. Pure.\n */\nexport function splitChips<F extends { name: string; value?: unknown }>(filters: readonly F[]): { chips: string[]; filters: F[] } {\n const chosen = filters.find(one => one.name === CHIPS_FILTER)?.value\n const chips = (Array.isArray(chosen) ? chosen : chosen ? [chosen] : []).map(String)\n return { chips, filters: filters.filter(one => one.name !== CHIPS_FILTER) }\n}\n"]}
|
|
@@ -59,3 +59,32 @@ export declare function withChips(filters: any[], chosen?: string | string[] | n
|
|
|
59
59
|
* read's `signal`.
|
|
60
60
|
*/
|
|
61
61
|
export declare function countChips(query: string, keys: string[], filters: any[], signal?: AbortSignal): Promise<Record<string, number>>;
|
|
62
|
+
/**
|
|
63
|
+
* The chips as the grid's own filter (FOOTER-BUTTON-REVIEW G09): a column no one sees whose filter is the chips, so the
|
|
64
|
+
* pressed ones live in the address with search, sort and page - a shared link, coming back and reloading read the same
|
|
65
|
+
* list, and pressing one reads page 1 again. Their numbers are the grid's counts for this column (`countHandler`
|
|
66
|
+
* answering `{ chips: ... }`). The chips need no label: each names its condition.
|
|
67
|
+
*/
|
|
68
|
+
export declare function chipsColumn(chips: {
|
|
69
|
+
display: string;
|
|
70
|
+
value: string;
|
|
71
|
+
hint?: string;
|
|
72
|
+
}[]): {
|
|
73
|
+
type: string;
|
|
74
|
+
name: string;
|
|
75
|
+
header: string;
|
|
76
|
+
hidden: boolean;
|
|
77
|
+
record: {
|
|
78
|
+
editable: boolean;
|
|
79
|
+
};
|
|
80
|
+
filter: {
|
|
81
|
+
type: string;
|
|
82
|
+
operator: string;
|
|
83
|
+
label: string;
|
|
84
|
+
options: {
|
|
85
|
+
display: string;
|
|
86
|
+
value: string;
|
|
87
|
+
hint?: string;
|
|
88
|
+
}[];
|
|
89
|
+
};
|
|
90
|
+
};
|
|
@@ -2,7 +2,7 @@ import gql from 'graphql-tag';
|
|
|
2
2
|
import { client } from '@operato/graphql';
|
|
3
3
|
import { i18next } from '@operato/i18n';
|
|
4
4
|
import { adjustFilters } from '@operato/utils';
|
|
5
|
-
import { chipCounts } from './chip-counts.js';
|
|
5
|
+
import { chipCounts, CHIPS_FILTER } from './chip-counts.js';
|
|
6
6
|
import { ActivityThreadStatus } from './types/activity-thread.js';
|
|
7
7
|
/**
|
|
8
8
|
* 목록 위의 칩이 무엇을 걸러 내는가 — **한 곳에서 정한다.**
|
|
@@ -101,4 +101,20 @@ export async function countChips(query, keys, filters, signal) {
|
|
|
101
101
|
return sets.map((_, at) => response.data?.[`c${at}`]?.total ?? 0);
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* The chips as the grid's own filter (FOOTER-BUTTON-REVIEW G09): a column no one sees whose filter is the chips, so the
|
|
106
|
+
* pressed ones live in the address with search, sort and page - a shared link, coming back and reloading read the same
|
|
107
|
+
* list, and pressing one reads page 1 again. Their numbers are the grid's counts for this column (`countHandler`
|
|
108
|
+
* answering `{ chips: ... }`). The chips need no label: each names its condition.
|
|
109
|
+
*/
|
|
110
|
+
export function chipsColumn(chips) {
|
|
111
|
+
return {
|
|
112
|
+
type: 'string',
|
|
113
|
+
name: CHIPS_FILTER,
|
|
114
|
+
header: i18next.t('label.filter'),
|
|
115
|
+
hidden: true,
|
|
116
|
+
record: { editable: false },
|
|
117
|
+
filter: { type: 'select-buttons', operator: 'in', label: '', options: chips }
|
|
118
|
+
};
|
|
119
|
+
}
|
|
104
120
|
//# sourceMappingURL=chip-filters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chip-filters.js","sourceRoot":"","sources":["../client/chip-filters.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"chip-filters.js","sourceRoot":"","sources":["../client/chip-filters.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { adjustFilters } from '@operato/utils'\n\nimport { chipCounts, CHIPS_FILTER } from './chip-counts.js'\nimport { ActivityThreadStatus } from './types/activity-thread.js'\n\n/**\n * 목록 위의 칩이 무엇을 걸러 내는가 — **한 곳에서 정한다.**\n *\n * ── 왜 모았나 (2026-09-02) ─────────────────────────────────────────────────\n * 「중요」와 「만기」가 다섯 화면에 있는데, 그 뜻이 다섯 곳에 복사돼 있었다.\n *\n * priority gte 2 5곳\n * dueAt lte (지금 + 24 * 3600 * 1000) 4곳\n *\n * 한 화면에서 「중요」를 우선순위 3 이상으로 바꾸면 나머지 넷은 2로 남는다. 그러면 **같은 이름의 칩이\n * 화면마다 다른 것을 걸러 낸다.** 사용자는 그것을 알 방법이 없다.\n *\n * ── 칩은 컬럼 필터가 아니다 ────────────────────────────────────────────────\n * `ox-filters-form` 은 칸 하나와 연산자 하나를 그린다. 이 칩들은 **이름 붙인 조건 묶음**이다 —\n * 「중요」는 `priority = ?` 가 아니라 `priority >= 2` 이고, 「만기」는 지금 시각에서 계산한다.\n *\n * 그래서 사용자가 스스로 만들 수 없다. 「중요 = 우선순위 2 이상」은 제품이 아는 사실이다.\n *\n * ── 그러니 그 뜻을 화면이 말해야 한다 ──────────────────────────────────────\n * 이름만 보이면 눌러 보고 결과를 되짚어야 한다. 칩마다 `hint` 를 함께 낸다(마우스를 올리면 보인다).\n */\n\n/** 「중요」의 경계. 이 값 이상이 중요하다. */\nexport const IMPORTANT_FROM = 2\n\n/** 「만기」의 창. 이 시간 안에 만기가 오는 것. */\nexport const DUE_WITHIN_HOURS = 24\n\n/*\n * 연산자를 리터럴로 좁힌다(`as const`). `adjustFilters` 가 받는 타입은 연산자가 정해진 낱말 중\n * 하나인데, 그 타입이 내보내지지 않아 여기서 가져올 수 없다. `string` 으로 두면 넘길 때 거절된다.\n */\n\n/** 우선순위가 경계 이상인 것. */\nexport function importantFilters() {\n return [{ name: 'priority', operator: 'gte' as const, value: IMPORTANT_FROM }]\n}\n\n/**\n * 만기가 창 안에 드는 것.\n *\n * 부를 때마다 지금 시각으로 계산한다 — 화면을 열어 둔 채 시간이 지나면 「만기 임박」의 범위도 함께\n * 움직여야 한다.\n */\nexport function dueSoonFilters() {\n const until = new Date(Date.now() + DUE_WITHIN_HOURS * 3600 * 1000).toISOString().replace('T', ' ')\n\n return [{ name: 'dueAt', operator: 'lte' as const, value: until }]\n}\n\n/** 칩 하나 — 이름과 뜻. */\nexport function importantChip() {\n return {\n display: i18next.t('label.filter-important'),\n value: 'important',\n hint: i18next.t('text.filter-important-hint', { from: IMPORTANT_FROM })\n }\n}\n\nexport function dueSoonChip() {\n return {\n display: i18next.t('label.filter-due'),\n value: 'due',\n hint: i18next.t('text.filter-due-hint', { hours: DUE_WITHIN_HOURS })\n }\n}\n\n/*\n * 칩마다 거는 조건 — 화면마다 if 로 따로 적던 것을 여기 한 곳에 둔다. 같은 이름의 칩은 어느 화면에서나 같은 것을\n * 걸러 낸다(위 「왜 모았나」). 시각에서 계산하는 것은 부를 때마다 지금으로 계산한다.\n */\nconst CONDITIONS: Record<string, () => { name: string; operator: any; value: any }[]> = {\n important: importantFilters,\n due: dueSoonFilters,\n proceeding: () => [{ name: 'state', operator: 'eq', value: ActivityThreadStatus.Started }],\n /* 최근 24시간 이내에 끝낸 일 */\n recent: () => [{ name: 'terminatedAt', operator: 'gte', value: new Date(Date.now() - 24 * 3600 * 1000).toISOString().replace('T', ' ') }],\n aborted: () => [{ name: 'state', operator: 'eq', value: ActivityThreadStatus.Aborted }],\n resubmitted: () => [{ name: 'round', operator: 'gte', value: 2 }],\n rejected: () => [{ name: 'judgment', operator: 'eq', value: 'rejected' }]\n}\n\n/** The list's filters with the pressed chips' conditions added. */\nexport function withChips(filters: any[], chosen?: string | string[] | null): any[] {\n const keys = chosen instanceof Array ? chosen : chosen ? [chosen] : []\n return keys.reduce((narrowed, key) => (CONDITIONS[key] ? adjustFilters(narrowed, CONDITIONS[key]()) : narrowed), filters)\n}\n\n/**\n * How many each chip would show under the list's other conditions (`filters`, without the pressed chip) - the list\n * door `query` asked for its total once per chip, in one request. A list's `countHandler` asks it under the grid\n * read's `signal`.\n */\nexport async function countChips(query: string, keys: string[], filters: any[], signal?: AbortSignal): Promise<Record<string, number>> {\n return chipCounts(\n keys,\n key => withChips(filters, key),\n async sets => {\n const response = await client.query({\n query: gql`\n query (${sets.map((_, at) => `$f${at}: [Filter!]`).join(', ')}) {\n ${sets.map((_, at) => `c${at}: ${query}(filters: $f${at}, pagination: { page: 1, limit: 1 }) { total }`).join('\\n')}\n }\n `,\n variables: Object.fromEntries(sets.map((set, at) => [`f${at}`, set])),\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal }, queryDeduplication: false }\n })\n return sets.map((_, at) => response.data?.[`c${at}`]?.total ?? 0)\n }\n )\n}\n\n/**\n * The chips as the grid's own filter (FOOTER-BUTTON-REVIEW G09): a column no one sees whose filter is the chips, so the\n * pressed ones live in the address with search, sort and page - a shared link, coming back and reloading read the same\n * list, and pressing one reads page 1 again. Their numbers are the grid's counts for this column (`countHandler`\n * answering `{ chips: ... }`). The chips need no label: each names its condition.\n */\nexport function chipsColumn(chips: { display: string; value: string; hint?: string }[]) {\n return {\n type: 'string',\n name: CHIPS_FILTER,\n header: i18next.t('label.filter'),\n hidden: true,\n record: { editable: false },\n filter: { type: 'select-buttons', operator: 'in', label: '', options: chips }\n }\n}\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import '@operato/data-grist';
|
|
2
2
|
import '@operato/data-grist/ox-filters-form.js';
|
|
3
|
-
import '@operato/input/ox-input-select-buttons.js';
|
|
4
3
|
import '../activity-instance/activity-instance-view.js';
|
|
5
4
|
import { DataGrist, FetchOption } from '@operato/data-grist';
|
|
6
5
|
import { PageView } from '@operato/shell';
|
|
@@ -16,9 +15,6 @@ export declare class ApprovalProgressPage extends ApprovalProgressPage_base {
|
|
|
16
15
|
grist: DataGrist;
|
|
17
16
|
gristConfig?: any;
|
|
18
17
|
mode: 'GRID' | 'LIST' | 'CARD';
|
|
19
|
-
/** The chips pressed — states, and 기한 넘김. */
|
|
20
|
-
chips: string[];
|
|
21
|
-
counts: Map<string, number>;
|
|
22
18
|
get context(): {
|
|
23
19
|
title: string;
|
|
24
20
|
search: {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@operato/data-grist';
|
|
3
3
|
import '@operato/data-grist/ox-filters-form.js';
|
|
4
|
-
import '@operato/input/ox-input-select-buttons.js';
|
|
5
4
|
import '../activity-instance/activity-instance-view.js';
|
|
6
5
|
import gql from 'graphql-tag';
|
|
7
6
|
import { css, html } from 'lit';
|
|
@@ -18,6 +17,8 @@ import { waitedParts } from '../../approval-progress.js';
|
|
|
18
17
|
import { whenShortText } from '../../when.js';
|
|
19
18
|
const STATES = ['PENDING', 'APPROVED', 'REJECTED', 'ABORTED'];
|
|
20
19
|
const OVERDUE = 'OVERDUE';
|
|
20
|
+
/** The grid column whose filter holds the chips pressed. */
|
|
21
|
+
const CHIPS = 'chips';
|
|
21
22
|
/**
|
|
22
23
|
* 결재 현황 — every approval of the domain, whatever its kind, and where each stands (ADR-0183).
|
|
23
24
|
*
|
|
@@ -28,9 +29,6 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
28
29
|
constructor() {
|
|
29
30
|
super(...arguments);
|
|
30
31
|
this.mode = isMobileDevice() ? 'CARD' : 'GRID';
|
|
31
|
-
/** The chips pressed — states, and 기한 넘김. */
|
|
32
|
-
this.chips = [STATES[0]];
|
|
33
|
-
this.counts = new Map();
|
|
34
32
|
}
|
|
35
33
|
static { this.styles = [
|
|
36
34
|
/* The work surface frame for a list screen (ADR-0060 decision 8). */
|
|
@@ -67,25 +65,17 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
67
65
|
}
|
|
68
66
|
};
|
|
69
67
|
}
|
|
68
|
+
/*
|
|
69
|
+
* The kind, department, raised days, the chips (states and 기한 넘김), search and page are the grid's own, kept in
|
|
70
|
+
* the address (FOOTER-BUTTON-REVIEW G09): a shared link, coming back and reloading read the same list, and a change of
|
|
71
|
+
* them reads page 1 again. `mode` is only how the rows are drawn, never a condition.
|
|
72
|
+
*/
|
|
70
73
|
render() {
|
|
71
74
|
return html `
|
|
72
|
-
<ox-grist class="page-fill" .mode=${this.mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
|
|
75
|
+
<ox-grist class="page-fill" .mode=${this.mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>
|
|
73
76
|
<div slot="headroom" class="header">
|
|
74
77
|
<div class="filters">
|
|
75
78
|
<ox-filters-form class="filter" without-search></ox-filters-form>
|
|
76
|
-
<ox-input-select-buttons
|
|
77
|
-
multiple
|
|
78
|
-
.value=${this.chips}
|
|
79
|
-
.options=${[...STATES, OVERDUE].map(value => ({
|
|
80
|
-
value,
|
|
81
|
-
display: i18next.t(`label.approval-progress-${value.toLowerCase()}`),
|
|
82
|
-
count: this.counts.get(value) ?? 0
|
|
83
|
-
}))}
|
|
84
|
-
@change=${(e) => {
|
|
85
|
-
this.chips = e.currentTarget?.value || [];
|
|
86
|
-
this.grist.fetch();
|
|
87
|
-
}}
|
|
88
|
-
></ox-input-select-buttons>
|
|
89
79
|
</div>
|
|
90
80
|
</div>
|
|
91
81
|
</ox-grist>
|
|
@@ -127,7 +117,7 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
127
117
|
{ type: 'string', name: 'departmentName', header: i18next.t('field.approval-department'), record: { editable: false }, width: 100 },
|
|
128
118
|
{ type: 'string', name: 'stateLabel', header: i18next.t('label.status'), record: { editable: false, align: 'center' }, width: 70 },
|
|
129
119
|
{ type: 'string', name: 'stepText', header: i18next.t('field.approval-step'), record: { editable: false, align: 'center' }, width: 60 },
|
|
130
|
-
{ type: 'string', name: 'waiting', header: i18next.t('field.approval-
|
|
120
|
+
{ type: 'string', name: 'waiting', header: i18next.t('field.approval-approver'), record: { editable: false }, width: 180 },
|
|
131
121
|
{ type: 'string', name: 'waited', header: i18next.t('field.approval-waited'), record: { editable: false }, width: 100 },
|
|
132
122
|
{
|
|
133
123
|
type: 'datetime',
|
|
@@ -137,7 +127,22 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
137
127
|
width: 130
|
|
138
128
|
},
|
|
139
129
|
{ type: 'date', name: 'raisedAt', header: i18next.t('field.approval-raised-at'), record: { editable: false, renderer: value => whenShortText(value) }, filter: { operator: 'between' }, width: 140 },
|
|
140
|
-
{ type: 'datetime', name: 'endedAt', header: i18next.t('field.approval-ended-at'), record: { editable: false, renderer: value => whenShortText(value) }, width: 140 }
|
|
130
|
+
{ type: 'datetime', name: 'endedAt', header: i18next.t('field.approval-ended-at'), record: { editable: false, renderer: value => whenShortText(value) }, width: 140 },
|
|
131
|
+
{
|
|
132
|
+
/* The chips - the states and 기한 넘김, waiting ones first; each names itself, so no label. Their numbers are the read's. */
|
|
133
|
+
type: 'string',
|
|
134
|
+
name: CHIPS,
|
|
135
|
+
header: i18next.t('label.status'),
|
|
136
|
+
hidden: true,
|
|
137
|
+
record: { editable: false },
|
|
138
|
+
filter: {
|
|
139
|
+
type: 'select-buttons',
|
|
140
|
+
operator: 'in',
|
|
141
|
+
label: '',
|
|
142
|
+
value: [STATES[0]],
|
|
143
|
+
options: [...STATES, OVERDUE].map(value => ({ value, display: i18next.t(`label.approval-progress-${value.toLowerCase()}`) }))
|
|
144
|
+
}
|
|
145
|
+
}
|
|
141
146
|
],
|
|
142
147
|
rows: { appendable: false, selectable: false },
|
|
143
148
|
sorters: []
|
|
@@ -190,14 +195,16 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
190
195
|
const kinds = valueOf('activityName');
|
|
191
196
|
const [from, to] = valueOf('raisedAt') || [];
|
|
192
197
|
const search = filters.find(one => one.operator === 'search')?.value?.replace(/^%|%$/g, '');
|
|
198
|
+
const pressed = valueOf(CHIPS);
|
|
199
|
+
const chips = pressed ? [].concat(pressed) : [];
|
|
193
200
|
return {
|
|
194
201
|
activityNames: kinds ? [].concat(kinds) : undefined,
|
|
195
202
|
departmentIds: valueOf('departmentId') ? [valueOf('departmentId')] : undefined,
|
|
196
203
|
from: from ? new Date(from) : undefined,
|
|
197
204
|
/* The range's last day counts whole - the server's `to` is exclusive. */
|
|
198
205
|
to: to ? new Date(new Date(to).getTime() + 24 * 3600 * 1000) : undefined,
|
|
199
|
-
states:
|
|
200
|
-
overdueOnly:
|
|
206
|
+
states: chips.filter(chip => chip !== OVERDUE),
|
|
207
|
+
overdueOnly: chips.includes(OVERDUE) || undefined,
|
|
201
208
|
search: search || undefined
|
|
202
209
|
};
|
|
203
210
|
}
|
|
@@ -218,6 +225,7 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
218
225
|
step
|
|
219
226
|
steps
|
|
220
227
|
waitingOn
|
|
228
|
+
decidedBy
|
|
221
229
|
waitingRole
|
|
222
230
|
waitingSince
|
|
223
231
|
dueAt
|
|
@@ -238,7 +246,10 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
238
246
|
fetchPolicy: 'no-cache'
|
|
239
247
|
});
|
|
240
248
|
const result = response.data?.approvalProgress;
|
|
241
|
-
|
|
249
|
+
/* The chips' numbers come with the rows - handed to the grid as its counts for the chips column, which the form draws. */
|
|
250
|
+
const counts = { [CHIPS]: Object.fromEntries([...(result?.counts || []).map((one) => [one.state, one.count]), [OVERDUE, result?.overdue ?? 0]]) };
|
|
251
|
+
this.grist.counts = counts;
|
|
252
|
+
this.grist.dispatchEvent(new CustomEvent('counts-change', { detail: counts }));
|
|
242
253
|
return {
|
|
243
254
|
total: result?.total || 0,
|
|
244
255
|
records: (result?.items || []).map((item) => ({
|
|
@@ -251,7 +262,10 @@ let ApprovalProgressPage = class ApprovalProgressPage extends localize(i18next)(
|
|
|
251
262
|
}))
|
|
252
263
|
};
|
|
253
264
|
}
|
|
265
|
+
/* Who decides it: whom a waiting case waits on, who approved last or rejected a decided one. */
|
|
254
266
|
waitingText(item) {
|
|
267
|
+
if (item.state !== 'PENDING')
|
|
268
|
+
return (item.decidedBy || []).join(', ');
|
|
255
269
|
const names = (item.waitingOn || []).join(', ');
|
|
256
270
|
return item.waitingRole ? `${item.waitingRole}${names ? ` (${names})` : ''}` : names;
|
|
257
271
|
}
|
|
@@ -279,14 +293,6 @@ __decorate([
|
|
|
279
293
|
state(),
|
|
280
294
|
__metadata("design:type", String)
|
|
281
295
|
], ApprovalProgressPage.prototype, "mode", void 0);
|
|
282
|
-
__decorate([
|
|
283
|
-
state(),
|
|
284
|
-
__metadata("design:type", Array)
|
|
285
|
-
], ApprovalProgressPage.prototype, "chips", void 0);
|
|
286
|
-
__decorate([
|
|
287
|
-
state(),
|
|
288
|
-
__metadata("design:type", Object)
|
|
289
|
-
], ApprovalProgressPage.prototype, "counts", void 0);
|
|
290
296
|
ApprovalProgressPage = __decorate([
|
|
291
297
|
customElement('approval-progress-page')
|
|
292
298
|
], ApprovalProgressPage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-progress-page.js","sourceRoot":"","sources":["../../../client/pages/approval-progress/approval-progress-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 '../activity-instance/activity-instance-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { dueCell } from '../../activity-cells.js'\nimport { waitedParts } from '../../approval-progress.js'\nimport { whenShortText } from '../../when.js'\n\nconst STATES = ['PENDING', 'APPROVED', 'REJECTED', 'ABORTED'] as const\nconst OVERDUE = 'OVERDUE'\n\n/**\n * 결재 현황 — every approval of the domain, whatever its kind, and where each stands (ADR-0183).\n *\n * The rows, the step and whom it waits on are the server's (`approvalProgress`); this page only asks with the\n * conditions pressed and draws. A row opens the case's own view, whose door checks the reader again.\n */\n@customElement('approval-progress-page')\nexport class ApprovalProgressPage extends localize(i18next)(PageView) {\n static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n .header {\n grid-template-areas: 'filters actions';\n }\n\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n `\n ]\n\n @query('ox-grist') grist!: DataGrist\n\n @state() gristConfig?: any\n @state() mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n /** The chips pressed — states, and 기한 넘김. */\n @state() chips: string[] = [STATES[0]]\n @state() counts = new Map<string, number>()\n\n get context() {\n return {\n title: i18next.t('title.approval progress'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n }\n }\n }\n\n render() {\n return html`\n <ox-grist class=\"page-fill\" .mode=${this.mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n <ox-input-select-buttons\n multiple\n .value=${this.chips}\n .options=${[...STATES, OVERDUE].map(value => ({\n value,\n display: i18next.t(`label.approval-progress-${value.toLowerCase()}`),\n count: this.counts.get(value) ?? 0\n }))}\n @change=${(e: CustomEvent) => {\n this.chips = (e.currentTarget as any)?.value || []\n this.grist.fetch()\n }}\n ></ox-input-select-buttons>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized() {\n this.gristConfig = {\n pagination: { pages: [50, 100, 200] },\n list: { fields: ['headline', 'activityLabel'], details: ['requesterName', 'waiting', 'waited'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'assignment',\n iconOnly: false,\n title: i18next.t('button.view'),\n width: 72,\n handlers: { click: (_columns, _data, _column, record) => this.openCase(record) }\n },\n {\n /* The kind filter - the kinds that have a case here, as the server names them. */\n type: 'select',\n name: 'activityName',\n header: i18next.t('field.approval-kind'),\n hidden: true,\n filter: { operator: 'in', options: () => this.kindOptions() }\n },\n { type: 'string', name: 'activityLabel', header: i18next.t('field.approval-kind'), record: { editable: false }, width: 140 },\n { type: 'string', name: 'headline', header: i18next.t('field.approval-headline'), record: { editable: false }, filter: 'search', width: 260 },\n { type: 'string', name: 'requesterName', header: i18next.t('field.approval-requester'), record: { editable: false }, filter: 'search', width: 90 },\n {\n type: 'select',\n name: 'departmentId',\n header: i18next.t('field.approval-department'),\n hidden: true,\n filter: { operator: 'eq', options: () => this.departmentOptions() }\n },\n { type: 'string', name: 'departmentName', header: i18next.t('field.approval-department'), record: { editable: false }, width: 100 },\n { type: 'string', name: 'stateLabel', header: i18next.t('label.status'), record: { editable: false, align: 'center' }, width: 70 },\n { type: 'string', name: 'stepText', header: i18next.t('field.approval-step'), record: { editable: false, align: 'center' }, width: 60 },\n { type: 'string', name: 'waiting', header: i18next.t('field.approval-waiting-on'), record: { editable: false }, width: 180 },\n { type: 'string', name: 'waited', header: i18next.t('field.approval-waited'), record: { editable: false }, width: 100 },\n {\n type: 'datetime',\n name: 'dueAt',\n header: i18next.t('field.approval-due-at'),\n record: { editable: false, renderer: dueCell(() => this.active) },\n width: 130\n },\n { type: 'date', name: 'raisedAt', header: i18next.t('field.approval-raised-at'), record: { editable: false, renderer: value => whenShortText(value) }, filter: { operator: 'between' }, width: 140 },\n { type: 'datetime', name: 'endedAt', header: i18next.t('field.approval-ended-at'), record: { editable: false, renderer: value => whenShortText(value) }, width: 140 }\n ],\n rows: { appendable: false, selectable: false },\n sorters: []\n }\n }\n\n private openCase(record: any) {\n openPopup(html`<activity-instance-view activity-instance-id=${record.id}></activity-instance-view>`, {\n backdrop: true,\n size: 'large',\n title: record.headline\n })\n }\n\n private async kindOptions() {\n const response = await client.query({\n query: gql`\n query {\n approvalProgress(pagination: { page: 1, limit: 1 }) {\n kinds {\n name\n label\n labelTKey\n }\n }\n }\n `\n })\n return (response.data?.approvalProgress?.kinds || []).map((kind: any) => ({\n value: kind.name,\n display: String(i18next.t(kind.labelTKey, { defaultValue: kind.label }))\n }))\n }\n\n private async departmentOptions() {\n const response = await client.query({\n query: gql`\n query {\n departments(pagination: { page: 1, limit: 500 }, sortings: [{ name: \"name\" }]) {\n items {\n id\n name\n }\n }\n }\n `\n })\n return (response.data?.departments?.items || []).map((one: any) => ({ value: one.id, display: one.name }))\n }\n\n /** The grid's conditions as the server's filter - the column filters, the search box and the chips. */\n private filterOf(filters: any[]) {\n const valueOf = (name: string) => filters.find(one => one.name === name && one.operator !== 'search')?.value\n const kinds = valueOf('activityName')\n const [from, to] = valueOf('raisedAt') || []\n const search = filters.find(one => one.operator === 'search')?.value?.replace(/^%|%$/g, '')\n\n return {\n activityNames: kinds ? [].concat(kinds) : undefined,\n departmentIds: valueOf('departmentId') ? [valueOf('departmentId')] : undefined,\n from: from ? new Date(from) : undefined,\n /* The range's last day counts whole - the server's `to` is exclusive. */\n to: to ? new Date(new Date(to).getTime() + 24 * 3600 * 1000) : undefined,\n states: this.chips.filter(chip => chip !== OVERDUE),\n overdueOnly: this.chips.includes(OVERDUE) || undefined,\n search: search || undefined\n }\n }\n\n async fetchHandler({ page, limit, filters = [] }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filter: ApprovalProgressFilter, $pagination: Pagination) {\n approvalProgress(filter: $filter, pagination: $pagination) {\n items {\n id\n activityName\n activityLabel\n activityLabelTKey\n headline\n requesterName\n departmentName\n state\n step\n steps\n waitingOn\n waitingRole\n waitingSince\n dueAt\n overdue\n raisedAt\n endedAt\n }\n total\n counts {\n state\n count\n }\n overdue\n }\n }\n `,\n variables: { filter: this.filterOf(filters), pagination: { page, limit } },\n fetchPolicy: 'no-cache'\n })\n\n const result = response.data?.approvalProgress\n this.counts = new Map([...(result?.counts || []).map((one: any) => [one.state, one.count]), [OVERDUE, result?.overdue ?? 0]])\n\n return {\n total: result?.total || 0,\n records: (result?.items || []).map((item: any) => ({\n ...item,\n activityLabel: item.activityLabelTKey ? String(i18next.t(item.activityLabelTKey, { defaultValue: item.activityLabel })) : item.activityLabel,\n stateLabel: i18next.t(`label.approval-progress-${String(item.state).toLowerCase()}`),\n stepText: item.step ? `${item.step} / ${item.steps}` : '',\n waiting: this.waitingText(item),\n waited: this.waitedText(item)\n }))\n }\n }\n\n private waitingText(item: any) {\n const names = (item.waitingOn || []).join(', ')\n return item.waitingRole ? `${item.waitingRole}${names ? ` (${names})` : ''}` : names\n }\n\n private waitedText(item: any) {\n const parts = item.state === 'PENDING' ? waitedParts(item.waitingSince) : undefined\n if (!parts) return ''\n /* Past due is the due column's to say (dueCell) - said here too, it would be said twice. */\n return parts.days\n ? i18next.t('text.waited-days', parts)\n : parts.hours\n ? i18next.t('text.waited-hours', parts)\n : i18next.t('text.waited-minutes', parts)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"approval-progress-page.js","sourceRoot":"","sources":["../../../client/pages/approval-progress/approval-progress-page.ts"],"names":[],"mappings":";AAAA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,wCAAwC,CAAA;AAC/C,OAAO,gDAAgD,CAAA;AAEvD,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,CAAU,CAAA;AACtE,MAAM,OAAO,GAAG,SAAS,CAAA;AACzB,4DAA4D;AAC5D,MAAM,KAAK,GAAG,OAAO,CAAA;AAErB;;;;;GAKG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAA9D;;QAwBI,SAAI,GAA6B,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IAmP9E,CAAC;aA1QQ,WAAM,GAAG;QACd,qEAAqE;QACrE,qBAAqB;QACrB,eAAe;QACf,iBAAiB;QACjB,kBAAkB;QAClB,GAAG,CAAA;;;;;;;;;;;KAWF;KACF,AAlBY,CAkBZ;IAOD,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;YAC3C,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,MAAc,EAAE,EAAE;oBAC1B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAChC,CAAC;gBACD,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;aACpC;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,GAAG,EAAE;oBACZ,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAA;gBAC7B,CAAC;aACF;SACF,CAAA;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM;QACJ,OAAO,IAAI,CAAA;0CAC2B,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,WAAW,kBAAkB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,MAAM;;;;;;;KAO7J,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,WAAW,GAAG;YACjB,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE;YACrC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE;YAChG,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE;gBAC1C;oBACE,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,QAAQ;oBACpB,IAAI,EAAE,YAAY;oBAClB,QAAQ,EAAE,KAAK;oBACf,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;oBAC/B,KAAK,EAAE,EAAE;oBACT,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;iBACjF;gBACD;oBACE,kFAAkF;oBAClF,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;oBACxC,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE;iBAC9D;gBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC5H,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC7I,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;gBAClJ;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;oBAC9C,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE;iBACpE;gBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACnI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;gBAClI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;gBACvI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC1H,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACvH;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;oBAC1C,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBACjE,KAAK,EAAE,GAAG;iBACX;gBACD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACpM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACrK;oBACE,yHAAyH;oBACzH,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,KAAK;oBACX,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;oBACjC,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE;wBACN,IAAI,EAAE,gBAAgB;wBACtB,QAAQ,EAAE,IAAI;wBACd,KAAK,EAAE,EAAE;wBACT,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;wBAClB,OAAO,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,2BAA2B,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;qBAC9H;iBACF;aACF;YACD,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE;YAC9C,OAAO,EAAE,EAAE;SACZ,CAAA;IACH,CAAC;IAEO,QAAQ,CAAC,MAAW;QAC1B,SAAS,CAAC,IAAI,CAAA,gDAAgD,MAAM,CAAC,EAAE,4BAA4B,EAAE;YACnG,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,MAAM,CAAC,QAAQ;SACvB,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;OAUT;SACF,CAAC,CAAA;QACF,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,CAAC;YACxE,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;SACzE,CAAC,CAAC,CAAA;IACL,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;OAST;SACF,CAAC,CAAA;QACF,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC5G,CAAC;IAED,uGAAuG;IAC/F,QAAQ,CAAC,OAAc;QAC7B,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,KAAK,CAAA;QAC5G,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;QACrC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QAC3F,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QAC9B,MAAM,KAAK,GAAa,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAEzD,OAAO;YACL,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YACnD,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YAC9E,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YACvC,yEAAyE;YACzE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YACxE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC;YAC9C,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS;YACjD,MAAM,EAAE,MAAM,IAAI,SAAS;SAC5B,CAAA;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,EAAe;QAC3D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BT;YACD,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YAC1E,WAAW,EAAE,UAAU;SACxB,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;QAC9C,0HAA0H;QAC1H,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACtJ,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QAE9E,OAAO;YACL,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;YACzB,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,CAAC;gBACjD,GAAG,IAAI;gBACP,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;gBAC5I,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,2BAA2B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpF,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;gBACzD,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBAC/B,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;aAC9B,CAAC,CAAC;SACJ,CAAA;IACH,CAAC;IAED,gGAAgG;IACxF,WAAW,CAAC,IAAS;QAC3B,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACtE,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/C,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACtF,CAAC;IAEO,UAAU,CAAC,IAAS;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACnF,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAA;QACrB,4FAA4F;QAC5F,OAAO,KAAK,CAAC,IAAI;YACf,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,EAAE,KAAK,CAAC;YACtC,CAAC,CAAC,KAAK,CAAC,KAAK;gBACX,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,EAAE,KAAK,CAAC;gBACvC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAA;IAC/C,CAAC;;AArPkB;IAAlB,KAAK,CAAC,UAAU,CAAC;8BAAS,SAAS;mDAAA;AAE3B;IAAR,KAAK,EAAE;;yDAAkB;AACjB;IAAR,KAAK,EAAE;;kDAAoE;AAxBjE,oBAAoB;IADhC,aAAa,CAAC,wBAAwB,CAAC;GAC3B,oBAAoB,CA2QhC","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '../activity-instance/activity-instance-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { dueCell } from '../../activity-cells.js'\nimport { waitedParts } from '../../approval-progress.js'\nimport { whenShortText } from '../../when.js'\n\nconst STATES = ['PENDING', 'APPROVED', 'REJECTED', 'ABORTED'] as const\nconst OVERDUE = 'OVERDUE'\n/** The grid column whose filter holds the chips pressed. */\nconst CHIPS = 'chips'\n\n/**\n * 결재 현황 — every approval of the domain, whatever its kind, and where each stands (ADR-0183).\n *\n * The rows, the step and whom it waits on are the server's (`approvalProgress`); this page only asks with the\n * conditions pressed and draws. A row opens the case's own view, whose door checks the reader again.\n */\n@customElement('approval-progress-page')\nexport class ApprovalProgressPage extends localize(i18next)(PageView) {\n static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n .header {\n grid-template-areas: 'filters actions';\n }\n\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n `\n ]\n\n @query('ox-grist') grist!: DataGrist\n\n @state() gristConfig?: any\n @state() mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n get context() {\n return {\n title: i18next.t('title.approval progress'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n }\n }\n }\n\n /*\n * The kind, department, raised days, the chips (states and 기한 넘김), search and page are the grid's own, kept in\n * the address (FOOTER-BUTTON-REVIEW G09): a shared link, coming back and reloading read the same list, and a change of\n * them reads page 1 again. `mode` is only how the rows are drawn, never a condition.\n */\n render() {\n return html`\n <ox-grist class=\"page-fill\" .mode=${this.mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized() {\n this.gristConfig = {\n pagination: { pages: [50, 100, 200] },\n list: { fields: ['headline', 'activityLabel'], details: ['requesterName', 'waiting', 'waited'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'assignment',\n iconOnly: false,\n title: i18next.t('button.view'),\n width: 72,\n handlers: { click: (_columns, _data, _column, record) => this.openCase(record) }\n },\n {\n /* The kind filter - the kinds that have a case here, as the server names them. */\n type: 'select',\n name: 'activityName',\n header: i18next.t('field.approval-kind'),\n hidden: true,\n filter: { operator: 'in', options: () => this.kindOptions() }\n },\n { type: 'string', name: 'activityLabel', header: i18next.t('field.approval-kind'), record: { editable: false }, width: 140 },\n { type: 'string', name: 'headline', header: i18next.t('field.approval-headline'), record: { editable: false }, filter: 'search', width: 260 },\n { type: 'string', name: 'requesterName', header: i18next.t('field.approval-requester'), record: { editable: false }, filter: 'search', width: 90 },\n {\n type: 'select',\n name: 'departmentId',\n header: i18next.t('field.approval-department'),\n hidden: true,\n filter: { operator: 'eq', options: () => this.departmentOptions() }\n },\n { type: 'string', name: 'departmentName', header: i18next.t('field.approval-department'), record: { editable: false }, width: 100 },\n { type: 'string', name: 'stateLabel', header: i18next.t('label.status'), record: { editable: false, align: 'center' }, width: 70 },\n { type: 'string', name: 'stepText', header: i18next.t('field.approval-step'), record: { editable: false, align: 'center' }, width: 60 },\n { type: 'string', name: 'waiting', header: i18next.t('field.approval-approver'), record: { editable: false }, width: 180 },\n { type: 'string', name: 'waited', header: i18next.t('field.approval-waited'), record: { editable: false }, width: 100 },\n {\n type: 'datetime',\n name: 'dueAt',\n header: i18next.t('field.approval-due-at'),\n record: { editable: false, renderer: dueCell(() => this.active) },\n width: 130\n },\n { type: 'date', name: 'raisedAt', header: i18next.t('field.approval-raised-at'), record: { editable: false, renderer: value => whenShortText(value) }, filter: { operator: 'between' }, width: 140 },\n { type: 'datetime', name: 'endedAt', header: i18next.t('field.approval-ended-at'), record: { editable: false, renderer: value => whenShortText(value) }, width: 140 },\n {\n /* The chips - the states and 기한 넘김, waiting ones first; each names itself, so no label. Their numbers are the read's. */\n type: 'string',\n name: CHIPS,\n header: i18next.t('label.status'),\n hidden: true,\n record: { editable: false },\n filter: {\n type: 'select-buttons',\n operator: 'in',\n label: '',\n value: [STATES[0]],\n options: [...STATES, OVERDUE].map(value => ({ value, display: i18next.t(`label.approval-progress-${value.toLowerCase()}`) }))\n }\n }\n ],\n rows: { appendable: false, selectable: false },\n sorters: []\n }\n }\n\n private openCase(record: any) {\n openPopup(html`<activity-instance-view activity-instance-id=${record.id}></activity-instance-view>`, {\n backdrop: true,\n size: 'large',\n title: record.headline\n })\n }\n\n private async kindOptions() {\n const response = await client.query({\n query: gql`\n query {\n approvalProgress(pagination: { page: 1, limit: 1 }) {\n kinds {\n name\n label\n labelTKey\n }\n }\n }\n `\n })\n return (response.data?.approvalProgress?.kinds || []).map((kind: any) => ({\n value: kind.name,\n display: String(i18next.t(kind.labelTKey, { defaultValue: kind.label }))\n }))\n }\n\n private async departmentOptions() {\n const response = await client.query({\n query: gql`\n query {\n departments(pagination: { page: 1, limit: 500 }, sortings: [{ name: \"name\" }]) {\n items {\n id\n name\n }\n }\n }\n `\n })\n return (response.data?.departments?.items || []).map((one: any) => ({ value: one.id, display: one.name }))\n }\n\n /** The grid's conditions as the server's filter - the column filters, the search box and the chips. */\n private filterOf(filters: any[]) {\n const valueOf = (name: string) => filters.find(one => one.name === name && one.operator !== 'search')?.value\n const kinds = valueOf('activityName')\n const [from, to] = valueOf('raisedAt') || []\n const search = filters.find(one => one.operator === 'search')?.value?.replace(/^%|%$/g, '')\n const pressed = valueOf(CHIPS)\n const chips: string[] = pressed ? [].concat(pressed) : []\n\n return {\n activityNames: kinds ? [].concat(kinds) : undefined,\n departmentIds: valueOf('departmentId') ? [valueOf('departmentId')] : undefined,\n from: from ? new Date(from) : undefined,\n /* The range's last day counts whole - the server's `to` is exclusive. */\n to: to ? new Date(new Date(to).getTime() + 24 * 3600 * 1000) : undefined,\n states: chips.filter(chip => chip !== OVERDUE),\n overdueOnly: chips.includes(OVERDUE) || undefined,\n search: search || undefined\n }\n }\n\n async fetchHandler({ page, limit, filters = [] }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filter: ApprovalProgressFilter, $pagination: Pagination) {\n approvalProgress(filter: $filter, pagination: $pagination) {\n items {\n id\n activityName\n activityLabel\n activityLabelTKey\n headline\n requesterName\n departmentName\n state\n step\n steps\n waitingOn\n decidedBy\n waitingRole\n waitingSince\n dueAt\n overdue\n raisedAt\n endedAt\n }\n total\n counts {\n state\n count\n }\n overdue\n }\n }\n `,\n variables: { filter: this.filterOf(filters), pagination: { page, limit } },\n fetchPolicy: 'no-cache'\n })\n\n const result = response.data?.approvalProgress\n /* The chips' numbers come with the rows - handed to the grid as its counts for the chips column, which the form draws. */\n const counts = { [CHIPS]: Object.fromEntries([...(result?.counts || []).map((one: any) => [one.state, one.count]), [OVERDUE, result?.overdue ?? 0]]) }\n this.grist.counts = counts\n this.grist.dispatchEvent(new CustomEvent('counts-change', { detail: counts }))\n\n return {\n total: result?.total || 0,\n records: (result?.items || []).map((item: any) => ({\n ...item,\n activityLabel: item.activityLabelTKey ? String(i18next.t(item.activityLabelTKey, { defaultValue: item.activityLabel })) : item.activityLabel,\n stateLabel: i18next.t(`label.approval-progress-${String(item.state).toLowerCase()}`),\n stepText: item.step ? `${item.step} / ${item.steps}` : '',\n waiting: this.waitingText(item),\n waited: this.waitedText(item)\n }))\n }\n }\n\n /* Who decides it: whom a waiting case waits on, who approved last or rejected a decided one. */\n private waitingText(item: any) {\n if (item.state !== 'PENDING') return (item.decidedBy || []).join(', ')\n const names = (item.waitingOn || []).join(', ')\n return item.waitingRole ? `${item.waitingRole}${names ? ` (${names})` : ''}` : names\n }\n\n private waitedText(item: any) {\n const parts = item.state === 'PENDING' ? waitedParts(item.waitingSince) : undefined\n if (!parts) return ''\n /* Past due is the due column's to say (dueCell) - said here too, it would be said twice. */\n return parts.days\n ? i18next.t('text.waited-days', parts)\n : parts.hours\n ? i18next.t('text.waited-hours', parts)\n : i18next.t('text.waited-minutes', parts)\n }\n}\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import '@operato/data-grist';
|
|
2
2
|
import '@operato/data-grist/ox-filters-form.js';
|
|
3
|
-
import '@operato/input/ox-input-select-buttons.js';
|
|
4
3
|
import '../../components/work-box-groups.js';
|
|
5
4
|
import { DataGrist, FetchOption } from '@operato/data-grist';
|
|
6
5
|
import { PageView } from '@operato/shell';
|
|
@@ -52,7 +51,6 @@ export declare class ApprovalPendingListPage extends ApprovalPendingListPage_bas
|
|
|
52
51
|
private get shownCounts();
|
|
53
52
|
mode: 'GRID' | 'LIST' | 'CARD';
|
|
54
53
|
grist: DataGrist;
|
|
55
|
-
filters?: string[];
|
|
56
54
|
get context(): {
|
|
57
55
|
title: string;
|
|
58
56
|
search: {
|
|
@@ -71,8 +69,9 @@ export declare class ApprovalPendingListPage extends ApprovalPendingListPage_bas
|
|
|
71
69
|
private syncGroup;
|
|
72
70
|
pageInitialized(lifecycle: any): Promise<void>;
|
|
73
71
|
private applyConfig;
|
|
72
|
+
/** The chips that narrow every group - each a named condition (chip-filters). */
|
|
73
|
+
private chips;
|
|
74
74
|
pageUpdated(changes: any, lifecycle: any, changedBefore: any): Promise<void>;
|
|
75
|
-
private counted;
|
|
76
75
|
countHandler({ filters, signal }: FetchOption): Promise<{
|
|
77
76
|
chips: Record<string, number>;
|
|
78
77
|
}>;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@operato/data-grist';
|
|
3
3
|
import '@operato/data-grist/ox-filters-form.js';
|
|
4
|
-
import '@operato/input/ox-input-select-buttons.js';
|
|
5
4
|
import '../../components/work-box-groups.js';
|
|
6
5
|
import gql from 'graphql-tag';
|
|
7
6
|
import { css, html } from 'lit';
|
|
8
7
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
8
|
+
import { keyed } from 'lit/directives/keyed.js';
|
|
9
9
|
import { DataGrist, getRenderer } from '@operato/data-grist';
|
|
10
10
|
import { client, QueryController } from '@operato/graphql';
|
|
11
|
-
import {
|
|
11
|
+
import { splitChips } from '../../chip-counts.js';
|
|
12
|
+
import { chipsColumn, countChips, dueSoonChip, importantChip, withChips } from '../../chip-filters.js';
|
|
12
13
|
import { i18next, localize } from '@operato/i18n';
|
|
13
14
|
import { navigate, PageView } from '@operato/shell';
|
|
14
15
|
import { listWithThumbnail } from './list-thumbnail.js';
|
|
@@ -198,40 +199,28 @@ let ApprovalPendingListPage = class ApprovalPendingListPage extends p13n(localiz
|
|
|
198
199
|
@select=${(e) => this.selectGroup(e.detail)}
|
|
199
200
|
></work-box-groups>
|
|
200
201
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{ display: i18next.t('label.filter-resubmitted'),
|
|
220
|
-
value: 'resubmitted'
|
|
221
|
-
}
|
|
222
|
-
])}
|
|
223
|
-
@change=${(e) => {
|
|
224
|
-
this.filters = e.currentTarget?.value;
|
|
225
|
-
this.grist.fetch();
|
|
226
|
-
}}
|
|
227
|
-
></ox-input-select-buttons>
|
|
228
|
-
<!-- <ox-filters-form class="filter" autofocus without-search></ox-filters-form> -->
|
|
202
|
+
<!--
|
|
203
|
+
The group is a different list, named by the path; the list's own query - the chips, search, sort, page - is the
|
|
204
|
+
grid's, kept in the address (FOOTER-BUTTON-REVIEW G09). A group is its own grid, bound to its own path.
|
|
205
|
+
-->
|
|
206
|
+
${keyed(this.group, html `<ox-grist
|
|
207
|
+
class="page-fill"
|
|
208
|
+
.mode=${mode}
|
|
209
|
+
.config=${this.gristConfig}
|
|
210
|
+
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
211
|
+
.countHandler=${this.countHandler.bind(this)}
|
|
212
|
+
.personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')}
|
|
213
|
+
?url-params-sensitive=${this.active}
|
|
214
|
+
>
|
|
215
|
+
<div slot="headroom" class="header">
|
|
216
|
+
<div class="filters">
|
|
217
|
+
<!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). 칩도 이 폼이 그린다(chipsColumn). -->
|
|
218
|
+
<ox-filters-form class="filter" without-search></ox-filters-form>
|
|
219
|
+
</div>
|
|
229
220
|
</div>
|
|
230
221
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<ox-grist-personalizer slot="setting"></ox-grist-personalizer>
|
|
234
|
-
</ox-grist>
|
|
222
|
+
<ox-grist-personalizer slot="setting"></ox-grist-personalizer>
|
|
223
|
+
</ox-grist>`)}
|
|
235
224
|
`;
|
|
236
225
|
}
|
|
237
226
|
/** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */
|
|
@@ -543,30 +532,31 @@ let ApprovalPendingListPage = class ApprovalPendingListPage extends p13n(localiz
|
|
|
543
532
|
}
|
|
544
533
|
];
|
|
545
534
|
}
|
|
535
|
+
this.gristConfig.columns = [...this.gristConfig.columns, chipsColumn(this.chips())];
|
|
536
|
+
}
|
|
537
|
+
/** The chips that narrow every group - each a named condition (chip-filters). */
|
|
538
|
+
chips() {
|
|
539
|
+
return [importantChip(), dueSoonChip(), { display: i18next.t('label.filter-resubmitted'), value: 'resubmitted' }];
|
|
546
540
|
}
|
|
541
|
+
/* The grid re-reads by its own address when the page comes back - nothing to ask here. */
|
|
547
542
|
async pageUpdated(changes, lifecycle, changedBefore) {
|
|
548
543
|
if (lifecycle?.resourceId !== changedBefore?.resourceId) {
|
|
549
544
|
await this.syncGroup(lifecycle?.resourceId);
|
|
550
545
|
}
|
|
551
|
-
if (this.active) {
|
|
552
|
-
this.grist?.fetch();
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
/* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */
|
|
556
|
-
counted(chips) {
|
|
557
|
-
return chips.map(chip => ({ ...chip, count: this.grist?.counts?.chips?.[chip.value] ?? 0 }));
|
|
558
546
|
}
|
|
559
547
|
/* The chips' numbers - asked beside each read, on the list's filters before any chip is added. */
|
|
560
548
|
async countHandler({ filters = [], signal }) {
|
|
561
|
-
return { chips: await countChips(this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList', ['important', 'due', 'resubmitted'], filters, signal) };
|
|
549
|
+
return { chips: await countChips(this.group === 'reference' ? 'approvalReferenceList' : this.group === 'completed' ? 'approvalCompletedList' : 'approvalPendingList', ['important', 'due', 'resubmitted'], splitChips(filters).filters, signal) };
|
|
562
550
|
}
|
|
551
|
+
/* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */
|
|
563
552
|
async fetchHandler(options) {
|
|
564
553
|
const fetched = await this.fetchRows(options);
|
|
565
554
|
this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || []);
|
|
566
555
|
return fetched;
|
|
567
556
|
}
|
|
568
557
|
async fetchRows({ page, limit, sortings = [], filters = [] }) {
|
|
569
|
-
filters =
|
|
558
|
+
const { chips, filters: others } = splitChips(filters);
|
|
559
|
+
filters = withChips(others, chips);
|
|
570
560
|
const response = await client.query({ query: gql `
|
|
571
561
|
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
|
|
572
562
|
round
|
|
@@ -659,10 +649,6 @@ __decorate([
|
|
|
659
649
|
query('ox-grist'),
|
|
660
650
|
__metadata("design:type", DataGrist)
|
|
661
651
|
], ApprovalPendingListPage.prototype, "grist", void 0);
|
|
662
|
-
__decorate([
|
|
663
|
-
state(),
|
|
664
|
-
__metadata("design:type", Array)
|
|
665
|
-
], ApprovalPendingListPage.prototype, "filters", void 0);
|
|
666
652
|
ApprovalPendingListPage = __decorate([
|
|
667
653
|
customElement('approval-pending-list-page')
|
|
668
654
|
], ApprovalPendingListPage);
|