@things-factory/worklist 10.1.208 → 10.1.210
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/components/timeline-entries.js +2 -1
- package/dist-client/components/timeline-entries.js.map +1 -1
- package/dist-client/pages/activity-instance/activity-instance-view.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.js +36 -12
- package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-calendar-page.d.ts +16 -3
- package/dist-client/pages/todo/done-list-calendar-page.js +107 -19
- package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +1 -2
- package/dist-client/pages/todo/draft-list-page.js +11 -14
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/work-calendar-sources.d.ts +24 -6
- package/dist-client/work-calendar-sources.js +18 -6
- package/dist-client/work-calendar-sources.js.map +1 -1
- package/dist-server/controllers/activity-approval/check-authority.d.ts +2 -13
- package/dist-server/controllers/activity-approval/check-authority.js +2 -49
- package/dist-server/controllers/activity-approval/check-authority.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegate.js +1 -8
- package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegation.d.ts +5 -15
- package/dist-server/controllers/activity-approval/delegation.js +2 -16
- package/dist-server/controllers/activity-approval/delegation.js.map +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.d.ts +2 -2
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js +1 -1
- package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js.map +1 -1
- package/dist-server/controllers/activity-approval/seat-standing.d.ts +66 -0
- package/dist-server/controllers/activity-approval/seat-standing.js +57 -0
- package/dist-server/controllers/activity-approval/seat-standing.js.map +1 -0
- package/dist-server/controllers/activity-instance/issue.js +9 -15
- package/dist-server/controllers/activity-instance/issue.js.map +1 -1
- package/dist-server/controllers/activity-thread/abort.js +7 -0
- package/dist-server/controllers/activity-thread/abort.js.map +1 -1
- package/dist-server/controllers/activity-thread/restart.js +4 -2
- package/dist-server/controllers/activity-thread/restart.js.map +1 -1
- package/dist-server/controllers/activity-thread/submit.js +5 -1
- package/dist-server/controllers/activity-thread/submit.js.map +1 -1
- package/dist-server/controllers/common.js +1 -1
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/service/activity/index.d.ts +2 -2
- package/dist-server/service/activity-approval/index.d.ts +1 -1
- package/dist-server/service/activity-approval/my-pending-approvals.d.ts +5 -5
- package/dist-server/service/activity-approval/my-pending-approvals.js +5 -8
- package/dist-server/service/activity-approval/my-pending-approvals.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.d.ts +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +9 -4
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/index.d.ts +1 -1
- package/dist-server/service/activity-instance/request-box.d.ts +2 -0
- package/dist-server/service/activity-instance/request-box.js +18 -0
- package/dist-server/service/activity-instance/request-box.js.map +1 -0
- package/dist-server/service/activity-summary/activity-summary-query.js +3 -3
- package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
- package/dist-server/service/activity-summary/index.d.ts +1 -1
- package/dist-server/service/activity-template/index.d.ts +2 -2
- package/dist-server/service/activity-thread/index.d.ts +1 -1
- package/dist-server/service/activity-thread/my-open-threads.d.ts +1 -2
- package/dist-server/service/activity-thread/my-open-threads.js +2 -3
- package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
- package/dist-server/service/index.d.ts +3 -3
- package/dist-server/service/subscription/subscription-filters.d.ts +2 -2
- package/dist-server/service/subscription/subscription-filters.js +2 -2
- package/dist-server/service/subscription/subscription-filters.js.map +1 -1
- package/dist-server/service/work-door/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/shared/task-followup.d.ts +9 -0
- package/shared/task-followup.js +25 -0
- package/tests/delegate-approval.test.ts +7 -4
- package/tests/open-doors.test.ts +1 -1
- package/translations/en.json +7 -3
- package/translations/es.json +7 -3
- package/translations/ja.json +7 -3
- package/translations/ko.json +7 -3
- package/translations/ms.json +7 -3
- package/translations/zh.json +7 -3
- package/dist-server/controllers/activity-approval/own-request.d.ts +0 -162
- package/dist-server/controllers/activity-approval/own-request.js +0 -135
- package/dist-server/controllers/activity-approval/own-request.js.map +0 -1
|
@@ -9,7 +9,9 @@ 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 { entriesOfDay, loadWorkCalendar, workCalendarSources } from '../../work-calendar-sources.js';
|
|
12
|
+
import { applyingSources, entriesOfDay, loadWorkCalendar, workCalendarSources } from '../../work-calendar-sources.js';
|
|
13
|
+
/** The chip of worklist's own entries - my to-dos and approvals - beside the registered sources' chips. */
|
|
14
|
+
const OWN = 'worklist';
|
|
13
15
|
/** Priority 0..3. Anything outside the range clamps to the most urgent colour. */
|
|
14
16
|
const PRIORITY_COLORS = ['black', 'darkgray', 'orange', 'red'];
|
|
15
17
|
/**
|
|
@@ -109,8 +111,12 @@ function askedFor(response, field) {
|
|
|
109
111
|
let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(PageView) {
|
|
110
112
|
constructor() {
|
|
111
113
|
super(...arguments);
|
|
112
|
-
/** 못
|
|
113
|
-
this.failed =
|
|
114
|
+
/** 못 불러온 것들의 key — 「없다」와 절대 섞지 않는다. 하나라도 있으면 화면이 그렇게 말하고, 그 칩이 자기라고 말한다. */
|
|
115
|
+
this.failed = [];
|
|
116
|
+
/** The chips - worklist's own and every source that has anything for this person. */
|
|
117
|
+
this.kinds = [];
|
|
118
|
+
/** The kinds turned off. */
|
|
119
|
+
this.turnedOff = new Set();
|
|
114
120
|
}
|
|
115
121
|
static { this.styles = [
|
|
116
122
|
/* The frame owns the page shell; the calendar is the content it sizes (ADR-0060 decision 8). */
|
|
@@ -140,6 +146,42 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
140
146
|
font-size: 1.2em;
|
|
141
147
|
}
|
|
142
148
|
|
|
149
|
+
/* What is on the calendar - each chip shows or hides one kind, the way the factory calendar's do. */
|
|
150
|
+
.filters {
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-wrap: wrap;
|
|
153
|
+
gap: 6px;
|
|
154
|
+
align-items: center;
|
|
155
|
+
margin: 10px 10px 0 10px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
button.chip {
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
gap: 6px;
|
|
162
|
+
border: 1px solid var(--ui-line);
|
|
163
|
+
border-radius: 999px;
|
|
164
|
+
padding: 3px 10px;
|
|
165
|
+
background: transparent;
|
|
166
|
+
color: var(--ui-ink);
|
|
167
|
+
font: inherit;
|
|
168
|
+
font-size: 12px;
|
|
169
|
+
cursor: pointer;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
button.chip[aria-pressed='true'] {
|
|
173
|
+
background: var(--ui-surface-raised, var(--md-sys-color-surface-variant));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
button.chip[aria-pressed='false'] {
|
|
177
|
+
opacity: 0.6;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
button.chip .warn {
|
|
181
|
+
color: var(--md-sys-color-error);
|
|
182
|
+
font-size: 11px;
|
|
183
|
+
}
|
|
184
|
+
|
|
143
185
|
ox-event-view {
|
|
144
186
|
flex: 1;
|
|
145
187
|
padding: 10px;
|
|
@@ -155,25 +197,56 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
155
197
|
}
|
|
156
198
|
render() {
|
|
157
199
|
return html `
|
|
158
|
-
${this.failed
|
|
200
|
+
${this.failed.length
|
|
159
201
|
? html `<div class="failed" role="alert">
|
|
160
202
|
<md-icon>cloud_off</md-icon>
|
|
161
203
|
<span>${i18next.t('text.calendar-not-loaded')}</span>
|
|
162
204
|
</div>`
|
|
163
205
|
: ''}
|
|
164
|
-
|
|
206
|
+
${
|
|
207
|
+
/* One kind alone has nothing to filter. */
|
|
208
|
+
this.kinds.length > 1
|
|
209
|
+
? html `<div class="filters" role="group" aria-label=${i18next.t('label.calendar-kinds')}>
|
|
210
|
+
${this.kinds.map(kind => html `<button class="chip" aria-pressed=${!this.turnedOff.has(kind.key)} @click=${() => this.toggle(kind.key)}>
|
|
211
|
+
${kind.label()}
|
|
212
|
+
${this.failed.includes(kind.key) ? html `<span class="warn">${i18next.t('text.calendar-kind-not-loaded')}</span>` : ''}
|
|
213
|
+
</button>`)}
|
|
214
|
+
</div>`
|
|
215
|
+
: ''}
|
|
216
|
+
<ox-event-view class="page-fill" mode="monthly" .eventProvider=${this.provider}></ox-event-view>
|
|
165
217
|
`;
|
|
166
218
|
}
|
|
219
|
+
/** The chips are known once - which sources have anything for this person - and then the calendar is asked. */
|
|
220
|
+
async firstUpdated() {
|
|
221
|
+
const sources = await applyingSources(workCalendarSources());
|
|
222
|
+
this.kinds = [{ key: OWN, label: () => i18next.t('label.calendar-my-work') }, ...sources.map(source => ({ key: source.key, label: () => source.label() }))];
|
|
223
|
+
this.provider = this.calendarProvider();
|
|
224
|
+
}
|
|
225
|
+
calendarProvider() {
|
|
226
|
+
return { fetchEventsForCalendar: calendar => this.fetchEventsForCalendar(calendar) };
|
|
227
|
+
}
|
|
228
|
+
toggle(key) {
|
|
229
|
+
const next = new Set(this.turnedOff);
|
|
230
|
+
if (next.has(key))
|
|
231
|
+
next.delete(key);
|
|
232
|
+
else
|
|
233
|
+
next.add(key);
|
|
234
|
+
this.turnedOff = next;
|
|
235
|
+
this.provider = this.calendarProvider();
|
|
236
|
+
}
|
|
167
237
|
async fetchEventsForCalendar(calendar) {
|
|
168
238
|
const fromDate = calendar[0].date;
|
|
169
239
|
const toDate = new Date(calendar[calendar.length - 1].date.getTime() + 24 * 60 * 60 * 1000);
|
|
170
240
|
/*
|
|
171
|
-
* worklist's own and every
|
|
172
|
-
*
|
|
241
|
+
* worklist's own and every shown source, asked apart: one that fails leaves the others on the grid, and the band
|
|
242
|
+
* above it says something was not read - never a day with nothing on it. A kind turned off is not asked at all.
|
|
173
243
|
*/
|
|
244
|
+
const shown = new Set(this.kinds.map(kind => kind.key).filter(key => !this.turnedOff.has(key)));
|
|
174
245
|
const { entries, failed } = await loadWorkCalendar([
|
|
175
|
-
this.activityEntries(fromDate.toISOString(), toDate.toISOString()),
|
|
176
|
-
...workCalendarSources()
|
|
246
|
+
...(shown.has(OWN) ? [[OWN, this.activityEntries(fromDate.toISOString(), toDate.toISOString())]] : []),
|
|
247
|
+
...workCalendarSources()
|
|
248
|
+
.filter(source => shown.has(source.key))
|
|
249
|
+
.map(source => [source.key, source.load(fromDate, toDate)])
|
|
177
250
|
]);
|
|
178
251
|
this.failed = failed;
|
|
179
252
|
const eventMap = new Map();
|
|
@@ -184,15 +257,18 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
184
257
|
* 결재 한 건이 끝난 스무 건 뒤에 묻히면 「+20건 더」만 보이고, 그 날 할 일이 있다는 것을
|
|
185
258
|
* 아무도 못 본다. 급한 것이 앞이다: 그날 할 것(기한·회의) → 받은 날에 놓인 것 → 끝난 것.
|
|
186
259
|
*/
|
|
187
|
-
const { shown, hidden } = entriesOfDay(entries, localDateString, MOST_PER_DAY);
|
|
188
|
-
const events =
|
|
260
|
+
const { shown: shownOfDay, hidden } = entriesOfDay(entries, localDateString, MOST_PER_DAY);
|
|
261
|
+
const events = shownOfDay.map(({ name, priority, date, icon, href, note, allDay }) => {
|
|
189
262
|
const color = PRIORITY_COLORS[Math.min(Math.max(priority || 0, 0), PRIORITY_COLORS.length - 1)];
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
263
|
+
/* A whole day has no time - 「00:00」 before a day of leave would say a time nobody set. */
|
|
264
|
+
const at = allDay
|
|
265
|
+
? ''
|
|
266
|
+
: html `${new Date(date).toLocaleTimeString([], {
|
|
267
|
+
hourCycle: 'h23',
|
|
268
|
+
hour: '2-digit',
|
|
269
|
+
minute: '2-digit'
|
|
270
|
+
})} `;
|
|
271
|
+
const body = html `${icon ? html `<md-icon style="font-size:1em;">${icon}</md-icon> ` : ''}${at}${name}`;
|
|
196
272
|
return {
|
|
197
273
|
/*
|
|
198
274
|
* BizEvent 는 title · color 를 요구한다. 그리는 것은 template 이지만, 부품이 template
|
|
@@ -276,13 +352,25 @@ let DoneListCalendarPage = class DoneListCalendarPage extends localize(i18next)(
|
|
|
276
352
|
__decorate([
|
|
277
353
|
query('ox-event-view'),
|
|
278
354
|
__metadata("design:type", OxEventView
|
|
279
|
-
/** 못
|
|
355
|
+
/** 못 불러온 것들의 key — 「없다」와 절대 섞지 않는다. 하나라도 있으면 화면이 그렇게 말하고, 그 칩이 자기라고 말한다. */
|
|
280
356
|
)
|
|
281
357
|
], DoneListCalendarPage.prototype, "eventView", void 0);
|
|
282
358
|
__decorate([
|
|
283
359
|
state(),
|
|
284
|
-
__metadata("design:type",
|
|
360
|
+
__metadata("design:type", Array)
|
|
285
361
|
], DoneListCalendarPage.prototype, "failed", void 0);
|
|
362
|
+
__decorate([
|
|
363
|
+
state(),
|
|
364
|
+
__metadata("design:type", Array)
|
|
365
|
+
], DoneListCalendarPage.prototype, "kinds", void 0);
|
|
366
|
+
__decorate([
|
|
367
|
+
state(),
|
|
368
|
+
__metadata("design:type", Object)
|
|
369
|
+
], DoneListCalendarPage.prototype, "turnedOff", void 0);
|
|
370
|
+
__decorate([
|
|
371
|
+
state(),
|
|
372
|
+
__metadata("design:type", Object)
|
|
373
|
+
], DoneListCalendarPage.prototype, "provider", void 0);
|
|
286
374
|
DoneListCalendarPage = __decorate([
|
|
287
375
|
customElement('done-list-calendar-page')
|
|
288
376
|
], DoneListCalendarPage);
|
|
@@ -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 } from '@operato/event-view/types.js'\n\nimport { entriesOfDay, loadWorkCalendar, workCalendarSources, type WorkCalendarEntry } from '../../work-calendar-sources.js'\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 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 /** 못 불러왔다 — 「없다」와 절대 섞지 않는다. 이 값이 서면 화면이 그렇게 말한다. */\n @state() failed = false\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\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 <ox-event-view class=\"page-fill\" mode=\"monthly\" .eventProvider=${this}></ox-event-view>\n `\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 registered source, asked apart: one that fails leaves the others on the grid, and the\n * band above it says something was not read - never a day with nothing on it.\n */\n const { entries, failed } = await loadWorkCalendar([\n this.activityEntries(fromDate.toISOString(), toDate.toISOString()),\n ...workCalendarSources().map(source => source.load(fromDate, toDate))\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, hidden } = entriesOfDay(entries, localDateString, MOST_PER_DAY)\n\n const events: BizEvent[] = shown.map(({ name, priority, date, icon, href, note }) => {\n const color = PRIORITY_COLORS[Math.min(Math.max(priority || 0, 0), PRIORITY_COLORS.length - 1)]\n const at = 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, 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"]}
|
|
@@ -37,7 +37,6 @@ export declare class DraftListPage extends DraftListPage_base {
|
|
|
37
37
|
private syncGroup;
|
|
38
38
|
/** 안 보고 있는 기다리는 묶음의 건수 — 한 줄만 받아 total 을 읽는다. 못 읽은 수는 0 이 아니다. */
|
|
39
39
|
private countOther;
|
|
40
|
-
private stateFilterOf;
|
|
41
40
|
pageInitialized(lifecycle: any): Promise<void>;
|
|
42
41
|
private applyConfig;
|
|
43
42
|
pageUpdated(changes: any, lifecycle: any, changedBefore: any): Promise<void>;
|
|
@@ -50,7 +49,7 @@ export declare class DraftListPage extends DraftListPage_base {
|
|
|
50
49
|
records: any;
|
|
51
50
|
}>;
|
|
52
51
|
/**
|
|
53
|
-
*
|
|
52
|
+
* 작성 중으로 돌아온 요청은 수정 화면, 진행 중·완료는 읽기 화면으로 연다.
|
|
54
53
|
*
|
|
55
54
|
* 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중
|
|
56
55
|
* 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제
|
|
@@ -11,9 +11,9 @@ import { client } from '@operato/graphql';
|
|
|
11
11
|
import { i18next, localize } from '@operato/i18n';
|
|
12
12
|
import { navigate, PageView } from '@operato/shell';
|
|
13
13
|
import { listWithThumbnail } from './list-thumbnail.js';
|
|
14
|
-
import { countsOnTab,
|
|
14
|
+
import { countsOnTab, DRAFT_GROUPS, groupAddress, groupAt, threadToView } from './work-box.js';
|
|
15
15
|
import { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
|
|
16
|
-
import {
|
|
16
|
+
import { isMobileDevice } from '@operato/utils';
|
|
17
17
|
import { ActivityStartingTypes } from '../../types/types.js';
|
|
18
18
|
import { ActivityInstanceStatus } from '../../types/activity-instance.js';
|
|
19
19
|
import { subjectCell } from '../../activity-cells.js';
|
|
@@ -147,22 +147,19 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
147
147
|
const other = this.group === 'progress' ? 'draft' : 'progress';
|
|
148
148
|
const response = await client.query({
|
|
149
149
|
query: gql `
|
|
150
|
-
query ($filters: [Filter!], $pagination: Pagination) {
|
|
151
|
-
responses: draftList(filters: $filters, pagination: $pagination) {
|
|
150
|
+
query ($filters: [Filter!], $pagination: Pagination, $group: String) {
|
|
151
|
+
responses: draftList(filters: $filters, pagination: $pagination, group: $group) {
|
|
152
152
|
total
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
`,
|
|
156
|
-
variables: { filters: [
|
|
156
|
+
variables: { group: other, filters: [], pagination: { page: 1, limit: 1 } },
|
|
157
157
|
fetchPolicy: 'no-cache'
|
|
158
158
|
});
|
|
159
159
|
const total = response.errors?.length ? undefined : response.data?.responses?.total;
|
|
160
160
|
if (typeof total == 'number')
|
|
161
161
|
this.counts = { ...this.counts, [other]: total };
|
|
162
162
|
}
|
|
163
|
-
stateFilterOf(group) {
|
|
164
|
-
return { name: 'state', operator: 'in', value: [...DRAFT_GROUP_STATES[group]] };
|
|
165
|
-
}
|
|
166
163
|
async pageInitialized(lifecycle) {
|
|
167
164
|
/* pageUpdated 가 이 함수보다 먼저 지나가므로 주소로 바로 들어온 경우는 여기서 잡힌다. */
|
|
168
165
|
this.syncGroup(lifecycle?.resourceId);
|
|
@@ -251,7 +248,7 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
251
248
|
if (!record.id) {
|
|
252
249
|
return;
|
|
253
250
|
}
|
|
254
|
-
if (
|
|
251
|
+
if (record.state === 'draft') {
|
|
255
252
|
this.openActivityInstanceStart(record);
|
|
256
253
|
}
|
|
257
254
|
else {
|
|
@@ -283,9 +280,8 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
283
280
|
return fetched;
|
|
284
281
|
}
|
|
285
282
|
async fetchRows({ page, limit, sortings = [], filters = [] }) {
|
|
286
|
-
filters = adjustFilters(filters, [this.stateFilterOf(this.group)]);
|
|
287
283
|
const response = await client.query({ query: gql `
|
|
288
|
-
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id
|
|
284
|
+
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $group: String) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings, group: $group) { items { id
|
|
289
285
|
name
|
|
290
286
|
description
|
|
291
287
|
priority
|
|
@@ -337,7 +333,7 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
337
333
|
}
|
|
338
334
|
}
|
|
339
335
|
`,
|
|
340
|
-
variables: { filters,
|
|
336
|
+
variables: { filters, group: this.group,
|
|
341
337
|
pagination: { page, limit },
|
|
342
338
|
sortings
|
|
343
339
|
}
|
|
@@ -354,7 +350,7 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
354
350
|
};
|
|
355
351
|
}
|
|
356
352
|
/**
|
|
357
|
-
*
|
|
353
|
+
* 작성 중으로 돌아온 요청은 수정 화면, 진행 중·완료는 읽기 화면으로 연다.
|
|
358
354
|
*
|
|
359
355
|
* 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중
|
|
360
356
|
* 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제
|
|
@@ -366,7 +362,8 @@ let DraftListPage = class DraftListPage extends localize(i18next)(PageView) {
|
|
|
366
362
|
openActivityThreadView(record) {
|
|
367
363
|
const threadId = threadToView(record);
|
|
368
364
|
if (threadId) {
|
|
369
|
-
|
|
365
|
+
const page = this.group === 'draft' ? 'activity-thread' : 'activity-thread-view';
|
|
366
|
+
navigate(`${page}/${threadId}?title=${encodeURIComponent(record.name)}&box=draft-list`);
|
|
370
367
|
}
|
|
371
368
|
}
|
|
372
369
|
openActivityInstanceStart(activityInstance) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draft-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/draft-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '../../components/activity-starter-form.js'\nimport '../../components/work-box-groups.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { listWithThumbnail } from './list-thumbnail.js'\nimport { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, DraftGroup, groupAddress, groupAt, threadToView } from './work-box.js'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice } from '@operato/utils'\nimport { OxPopup } from '@operato/popup'\n\nimport { ActivityStartingTypes } from '../../types/types.js'\nimport { ActivityInstanceStatus } from '../../types/activity-instance.js'\n\nimport { subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('draft-list-page')\nexport class DraftListPage extends localize(i18next)(PageView) { static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n .header { grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n /**\n * 지금 어느 묶음을 보고 있나 — 작성 중 · 진행 중 · 완료 (pages/todo/work-box.ts).\n *\n * 남에게 시킨 일의 함이다. 전에는 작성 중만 보였고, 올린 건은 상태 거르기를 바꿔야 보였다 —\n * 지출결의를 올린 사람이 상신함을 열면 0 건이었다(2026-10-16).\n */\n @state() private group: DraftGroup = 'draft'\n\n /** 기다리는 두 묶음의 건수. 끝난 묶음은 이력이라 세지 않는다. */\n @state() private counts: Partial<Record<DraftGroup, number>> = {}\n\n get context() { return { title: i18next.t('title.draft list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: { handler: () => { this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/draft-list-page',\n actions: []\n }\n }\n\n render() { const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <work-box-groups\n .groups=${(\n [\n ['draft', 'label.group-draft', 'text.group-draft-hint'],\n ['progress', 'label.group-progress', 'text.group-progress-hint'],\n ['completed', 'label.group-completed', 'text.group-sent-completed-hint']\n ] as const\n ).map(([key, label, hint]) => ({ key, label, hint, count: countsOnTab(key) ? this.counts[key] : undefined }))}\n .selected=${this.group}\n @select=${(e: CustomEvent) => this.selectGroup(e.detail)}\n ></work-box-groups>\n\n <ox-grist class=\"page-fill\" .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: DraftGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, DRAFT_GROUPS))\n }\n\n private syncGroup(key?: string) {\n const group = groupAt(key, DRAFT_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /** 안 보고 있는 기다리는 묶음의 건수 — 한 줄만 받아 total 을 읽는다. 못 읽은 수는 0 이 아니다. */\n private async countOther() {\n const other: DraftGroup = this.group === 'progress' ? 'draft' : 'progress'\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n responses: draftList(filters: $filters, pagination: $pagination) {\n total\n }\n }\n `,\n variables: { filters: [this.stateFilterOf(other)], pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') this.counts = { ...this.counts, [other]: total }\n }\n\n private stateFilterOf(group: DraftGroup) {\n return { name: 'state', operator: 'in' as const, value: [...DRAFT_GROUP_STATES[group]] }\n }\n\n async pageInitialized(lifecycle) {\n /* pageUpdated 가 이 함수보다 먼저 지나가므로 주소로 바로 들어온 경우는 여기서 잡힌다. */\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n private applyConfig() {\n this.gristConfig = { list: { thumbnail: 'thumbnail',\n fields: ['name', 'description'],\n details: ['createdAt', 'due']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 375\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n { type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: { editable: false,\n /*\n * 이 목록은 **인스턴스**를 보인다. 고를 수 있는 상태도 인스턴스의 것이어야 한다 — 전에는\n * 스레드 상태 posted · escalated 가 섞여 있었고 issued 가 빠져 있었다. 서버는 인스턴스에\n * 없는 이름을 거절하므로 그 둘을 고르면 오류가 났다.\n */\n options: Object.values(ActivityInstanceStatus).map(value => ({\n display: i18next.t(`label.activity-state-${value}`),\n value\n }))\n },\n width: 85\n },\n { type: 'select',\n name: 'startingType',\n label: true,\n header: i18next.t('field.wl-starting-type'),\n record: { editable: false,\n options: ActivityStartingTypes\n },\n width: 90\n },\n { type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false\n },\n sortable: true,\n width: 180\n },\n { type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { if (!record.id) { return\n }\n\n if (this.group === 'draft') {\n this.openActivityInstanceStart(record)\n } else {\n this.openActivityThreadView(record)\n }\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n if (this.active) { this.grist?.fetch()\n }\n }\n\n /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */\n async fetchHandler(options: FetchOption) {\n const fetched = await this.fetchRows(options)\n\n this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || [])\n\n return fetched\n }\n\n async fetchRows({ page, limit, sortings = [], filters = [] }: FetchOption) {\n filters = adjustFilters(filters, [this.stateFilterOf(this.group)])\n\n const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id\n name\n description\n priority\n state\n input\n output\n refBy\n activity { id\n startingType\n }\n activityType\n assignees { type\n value\n assignee { id\n name\n description\n controlNo\n }\n }\n approvalLine { type\n value\n participation\n notifyAfter\n approver { id\n name\n description\n controlNo\n }\n }\n threadsMin\n threadsMax\n uiType\n uiSource\n dueAt\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n activityThreads {\n id\n assignee {\n id\n }\n }\n }\n total\n }\n }\n `,\n variables: { filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n const total = response.data.responses.total || 0\n /* 보고 있는 묶음의 수는 이 조회가 알려 준다. 나머지는 countOther 가 센다. */\n if (countsOnTab(this.group)) this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n /**\n * 올린 뒤의 건은 고칠 것이 없다 — 어디까지 왔는지를 본다.\n *\n * 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중\n * 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제\n * 할 일의 완료가 여는 읽기 화면(activity-thread-view)을 같이 쓴다.\n *\n * 내가 올린 건의 스레드는 대개 내 것이다(post) — 그것을 연다. 남에게 맡긴 건이면 그 건의 첫\n * 스레드를 연다. 올린 사람은 그 건의 스레드를 읽을 수 있다(assert-may-read · participates).\n */\n openActivityThreadView(record) {\n const threadId = threadToView(record)\n\n if (threadId) {\n navigate(`activity-thread-view/${threadId}?title=${record.name}`)\n }\n }\n\n openActivityInstanceStart(activityInstance) { navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"draft-list-page.js","sourceRoot":"","sources":["../../../client/pages/todo/draft-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '../../components/activity-starter-form.js'\nimport '../../components/work-box-groups.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { listWithThumbnail } from './list-thumbnail.js'\nimport { countsOnTab, DRAFT_GROUP_STATES, DRAFT_GROUPS, DraftGroup, groupAddress, groupAt, threadToView } from './work-box.js'\nimport { CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { adjustFilters, isMobileDevice } from '@operato/utils'\nimport { OxPopup } from '@operato/popup'\n\nimport { ActivityStartingTypes } from '../../types/types.js'\nimport { ActivityInstanceStatus } from '../../types/activity-instance.js'\n\nimport { subjectCell } from '../../activity-cells.js'\n\nconst MIN = 60\nconst HOUR = 60 * MIN\nconst DAY = 24 * HOUR\n\n@customElement('draft-list-page')\nexport class DraftListPage extends localize(i18next)(PageView) { static styles = [\n /* The work surface frame for a list screen (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonHeaderStyles,\n css`\n :host {\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n .header { grid-template-areas: 'filters actions';\n }\n\n /*\n * ── 헤드룸의 왼쪽 기준선은 표와 같다 ─────────────────────────────────\n * CommonHeaderStyles 의 .filters 는 배경과 모서리와 여백을 가진 영역이다. 그 배경이\n * --md-sys-color-surface 인데 이 제품에서는 바탕색과 같은 값이라, **보이지 않는 영역이\n * 자리만 차지하고** 검색창을 여백만큼(12px) 안쪽으로 밀었다.\n *\n * 실측: 표 왼쪽 끝 212 · 필터 영역 212 · 검색창 224. 화면의 왼쪽 기준선이 둘이 됐다.\n *\n * 그 규칙들은 .header 안에 중첩되어 있어(.header .filters) 밑줄 없는 .filters 로는 이길 수\n * 없다 — 특정도가 0,1,0 대 0,2,0 이다.\n */\n .header .filters {\n padding: 0;\n background: none;\n border-radius: 0;\n gap: 12px;\n }\n\n `\n ]\n\n @property({ type: Object }) gristConfig?: any\n @property({ type: String }) mode: 'GRID' | 'LIST' | 'CARD' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') grist!: DataGrist\n\n /**\n * 지금 어느 묶음을 보고 있나 — 작성 중 · 진행 중 · 완료 (pages/todo/work-box.ts).\n *\n * 남에게 시킨 일의 함이다. 전에는 작성 중만 보였고, 올린 건은 상태 거르기를 바꿔야 보였다 —\n * 지출결의를 올린 사람이 상신함을 열면 0 건이었다(2026-10-16).\n */\n @state() private group: DraftGroup = 'draft'\n\n /** 기다리는 두 묶음의 건수. 끝난 묶음은 이력이라 세지 않는다. */\n @state() private counts: Partial<Record<DraftGroup, number>> = {}\n\n get context() { return { title: i18next.t('title.draft list'),\n /*\n * 검색의 자리는 **기기가 정한다.**\n *\n * PC 에서는 화면 안으로 내린다. 상단 바에 두면 거른 조건과 걸러진 결과가 화면의 위아래 끝으로\n * 갈라지고, 지금 무엇으로 걸렀는지가 목록 옆에서 보이지 않는다.\n *\n * 좁은 화면에서는 상단 바에 그대로 둔다. 헤드룸에 두면 검색창과 필터가 목록을 그만큼 밀어\n * 내리고, 카드 두 장이 화면 밖으로 나간다. 상단 바는 그 자리를 아끼려고 있는 것이다.\n *\n * 이 저장소에는 두 방식이 다 있다 — 헤드룸 50곳, 상단 바 51곳. 정형인 것은 구조\n * (.header / .filters / .filter)이고 검색의 자리는 화면이 정한다.\n */\n /*\n * 검색은 **페이지 제목 줄의 오른쪽 끝**에 둔다 — 다른 화면들과 같은 자리다.\n *\n * 전에는 좁은 화면에서만 여기에 넣고, 넓은 화면에서는 헤드룸의 ox-filters-form 이 검색을\n * 그렸다. 그래서 같은 앱 안에서 검색 상자의 자리가 화면마다 달랐다.\n *\n * 헤드룸에는 좁히는 칩만 남는다. 폼은 without-search 로 남겨 두어, 나중에 어느 칸에\n * filter 를 달면 그 UI 가 저절로 생긴다(비면 아무것도 그리지 않는다).\n */\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: { handler: () => { this.grist.toggleHeadroom()\n }\n },\n help: 'worklist/draft-list-page',\n actions: []\n }\n }\n\n render() { const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <work-box-groups\n .groups=${(\n [\n ['draft', 'label.group-draft', 'text.group-draft-hint'],\n ['progress', 'label.group-progress', 'text.group-progress-hint'],\n ['completed', 'label.group-completed', 'text.group-sent-completed-hint']\n ] as const\n ).map(([key, label, hint]) => ({ key, label, hint, count: countsOnTab(key) ? this.counts[key] : undefined }))}\n .selected=${this.group}\n @select=${(e: CustomEvent) => this.selectGroup(e.detail)}\n ></work-box-groups>\n\n <ox-grist class=\"page-fill\" .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <!-- 좁은 화면에서는 상단 바가 검색을 갖는다(위 context 주석 참조). -->\n <ox-filters-form class=\"filter\" without-search></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n /** 주소만 바꾼다 — 목록도 설정도 pageUpdated 가 한 벌로 다시 세운다. */\n private selectGroup(group: DraftGroup) {\n if (this.group === group) {\n return\n }\n\n navigate(groupAddress((this as any).lifecycle?.page, group, DRAFT_GROUPS))\n }\n\n private syncGroup(key?: string) {\n const group = groupAt(key, DRAFT_GROUPS)\n\n if (this.group === group && this.gristConfig) {\n return\n }\n\n this.group = group\n this.applyConfig()\n }\n\n /** 안 보고 있는 기다리는 묶음의 건수 — 한 줄만 받아 total 을 읽는다. 못 읽은 수는 0 이 아니다. */\n private async countOther() {\n const other: DraftGroup = this.group === 'progress' ? 'draft' : 'progress'\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $group: String) {\n responses: draftList(filters: $filters, pagination: $pagination, group: $group) {\n total\n }\n }\n `,\n variables: { group: other, filters: [], pagination: { page: 1, limit: 1 } },\n fetchPolicy: 'no-cache'\n })\n\n const total = response.errors?.length ? undefined : response.data?.responses?.total\n if (typeof total == 'number') this.counts = { ...this.counts, [other]: total }\n }\n\n async pageInitialized(lifecycle) {\n /* pageUpdated 가 이 함수보다 먼저 지나가므로 주소로 바로 들어온 경우는 여기서 잡힌다. */\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n private applyConfig() {\n this.gristConfig = { list: { thumbnail: 'thumbnail',\n fields: ['name', 'description'],\n details: ['createdAt', 'due']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'string',\n name: 'name',\n header: i18next.t('field.wl-subject'),\n record: {\n editable: false,\n renderer: subjectCell()\n },\n filter: 'search',\n sortable: true,\n width: 375\n },\n {\n /*\n * 설명은 제목 칸 안에서 두 줄로 보인다(activity-cells 의 subjectCell). 그래서 따로 보일 칸이\n * 필요하지 않다.\n *\n * 그런데 **칸을 없애면 설명으로 검색하는 기능이 함께 사라진다.** searchText 는\n * filter: 'search' 를 선언한 컬럼마다 필터를 만들고 hidden 은 보지 않는다\n * (data-grist.ts 의 set searchText). 실측으로 확인했다 — 컬럼을 없앤 뒤 설명에만 있는\n * 낱말로 검색하면 0건이었다.\n *\n * 그래서 감춘 칸으로 남겨 검색만 남긴다.\n */\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: false },\n filter: 'search',\n hidden: true\n },\n { type: 'select',\n name: 'state',\n header: i18next.t('field.wl-state'),\n record: { editable: false,\n /*\n * 이 목록은 **인스턴스**를 보인다. 고를 수 있는 상태도 인스턴스의 것이어야 한다 — 전에는\n * 스레드 상태 posted · escalated 가 섞여 있었고 issued 가 빠져 있었다. 서버는 인스턴스에\n * 없는 이름을 거절하므로 그 둘을 고르면 오류가 났다.\n */\n options: Object.values(ActivityInstanceStatus).map(value => ({\n display: i18next.t(`label.activity-state-${value}`),\n value\n }))\n },\n width: 85\n },\n { type: 'select',\n name: 'startingType',\n label: true,\n header: i18next.t('field.wl-starting-type'),\n record: { editable: false,\n options: ActivityStartingTypes\n },\n width: 90\n },\n { type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.wl-changed-at'),\n record: { editable: false\n },\n sortable: true,\n width: 180\n },\n { type: 'image',\n name: 'thumbnail',\n header: i18next.t('field.thumbnail'),\n record: { editable: false },\n hidden: true\n }\n ],\n rows: { appendable: false,\n editable: false,\n handlers: { click: (columns, data, column, record, rowIndex) => { if (!record.id) { return\n }\n\n if (record.state === 'draft') {\n this.openActivityInstanceStart(record)\n } else {\n this.openActivityThreadView(record)\n }\n }\n }\n },\n sorters: [\n { name: 'updatedAt',\n desc: true\n }\n ]\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) {\n if (lifecycle?.resourceId !== changedBefore?.resourceId) {\n this.syncGroup(lifecycle?.resourceId)\n await this.countOther()\n }\n\n if (this.active) { this.grist?.fetch()\n }\n }\n\n /* 읽은 것에 그림이 하나도 없으면 카드마다 빈 그림 칸을 세우지 않는다(§ list-thumbnail.ts). */\n async fetchHandler(options: FetchOption) {\n const fetched = await this.fetchRows(options)\n\n this.gristConfig = listWithThumbnail(this.gristConfig, fetched?.records || [])\n\n return fetched\n }\n\n async fetchRows({ page, limit, sortings = [], filters = [] }: FetchOption) {\n\n const response = await client.query({ query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $group: String) { responses: draftList(filters: $filters, pagination: $pagination, sortings: $sortings, group: $group) { items { id\n name\n description\n priority\n state\n input\n output\n refBy\n activity { id\n startingType\n }\n activityType\n assignees { type\n value\n assignee { id\n name\n description\n controlNo\n }\n }\n approvalLine { type\n value\n participation\n notifyAfter\n approver { id\n name\n description\n controlNo\n }\n }\n threadsMin\n threadsMax\n uiType\n uiSource\n dueAt\n thumbnail\n updatedAt\n createdAt\n creator { id\n name\n }\n activityThreads {\n id\n assignee {\n id\n }\n }\n }\n total\n }\n }\n `,\n variables: { filters, group: this.group,\n pagination: { page, limit },\n sortings\n }\n })\n\n const total = response.data.responses.total || 0\n /* 보고 있는 묶음의 수는 이 조회가 알려 준다. 나머지는 countOther 가 센다. */\n if (countsOnTab(this.group)) this.counts = { ...this.counts, [this.group]: total }\n\n return { total,\n records:\n response.data.responses.items.map(item => { item['startingType'] = item.activity?.startingType\n return item\n }) || []\n }\n }\n\n /**\n * 작성 중으로 돌아온 요청은 수정 화면, 진행 중·완료는 읽기 화면으로 연다.\n *\n * 할 일 · 내 결재함처럼 **화면으로 옮겨 간다.** 전에는 업무 건 보기를 팝업으로 띄웠는데, 세 함 중\n * 이 함만 팝업이었고 그 팝업은 관리자 검색 화면의 것이라 리본도 결재 내용의 모양도 달랐다. 이제\n * 할 일의 완료가 여는 읽기 화면(activity-thread-view)을 같이 쓴다.\n *\n * 내가 올린 건의 스레드는 대개 내 것이다(post) — 그것을 연다. 남에게 맡긴 건이면 그 건의 첫\n * 스레드를 연다. 올린 사람은 그 건의 스레드를 읽을 수 있다(assert-may-read · participates).\n */\n openActivityThreadView(record) {\n const threadId = threadToView(record)\n\n if (threadId) {\n const page = this.group === 'draft' ? 'activity-thread' : 'activity-thread-view'\n navigate(`${page}/${threadId}?title=${encodeURIComponent(record.name)}&box=draft-list`)\n }\n }\n\n openActivityInstanceStart(activityInstance) { navigate(`activity-instance-start/${activityInstance.id}?title=${activityInstance.name}`)\n }\n}\n"]}
|
package/dist-client/route.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function route(page: string): "activity
|
|
1
|
+
export default function route(page: string): "activity" | "todo-list" | "approval-pending-list" | "draft-list" | "approval-done-list" | "done-list-calendar" | "pickable-list" | "starter-list" | "reporter-list" | "activity-instance-list" | "activity-catalog" | "activity-thread" | "activity-thread-view" | "activity-approval" | "activity-detail" | "activity-list" | "activity-instance-start" | "activity-instance-search" | "activity-template-list" | "activity-store" | "activity-thread-list" | "activity-approval-list" | "installable-activity-list" | "activity-stats-list" | undefined;
|