@things-factory/compliance 10.1.256 → 10.1.257

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist-client/components/compliance-case-form.d.ts +11 -6
  2. package/dist-client/components/compliance-case-form.js +67 -88
  3. package/dist-client/components/compliance-case-form.js.map +1 -1
  4. package/dist-client/components/compliance-case-sheet.d.ts +14 -12
  5. package/dist-client/components/compliance-case-sheet.js +92 -133
  6. package/dist-client/components/compliance-case-sheet.js.map +1 -1
  7. package/dist-client/components/compliance-my-inventions.d.ts +3 -4
  8. package/dist-client/components/compliance-my-inventions.js +10 -30
  9. package/dist-client/components/compliance-my-inventions.js.map +1 -1
  10. package/dist-client/components/compliance-my-privacy-requests.d.ts +6 -6
  11. package/dist-client/components/compliance-my-privacy-requests.js +30 -66
  12. package/dist-client/components/compliance-my-privacy-requests.js.map +1 -1
  13. package/dist-client/components/compliance-my-reports.d.ts +3 -4
  14. package/dist-client/components/compliance-my-reports.js +19 -40
  15. package/dist-client/components/compliance-my-reports.js.map +1 -1
  16. package/dist-client/components/invention-report-form.d.ts +5 -4
  17. package/dist-client/components/invention-report-form.js +24 -45
  18. package/dist-client/components/invention-report-form.js.map +1 -1
  19. package/dist-client/components/my-trainings.d.ts +3 -5
  20. package/dist-client/components/my-trainings.js +20 -49
  21. package/dist-client/components/my-trainings.js.map +1 -1
  22. package/dist-client/components/seal-use-form.d.ts +9 -6
  23. package/dist-client/components/seal-use-form.js +60 -81
  24. package/dist-client/components/seal-use-form.js.map +1 -1
  25. package/dist-client/components/training-attendance-form.d.ts +6 -4
  26. package/dist-client/components/training-attendance-form.js +30 -50
  27. package/dist-client/components/training-attendance-form.js.map +1 -1
  28. package/dist-client/pages/regulation-detail.d.ts +15 -6
  29. package/dist-client/pages/regulation-detail.js +169 -142
  30. package/dist-client/pages/regulation-detail.js.map +1 -1
  31. package/dist-client/pages/regulations.d.ts +7 -5
  32. package/dist-client/pages/regulations.js +38 -56
  33. package/dist-client/pages/regulations.js.map +1 -1
  34. package/dist-client/regulation/regulation-guide.js +2 -1
  35. package/dist-client/regulation/regulation-guide.js.map +1 -1
  36. package/dist-client/tsconfig.tsbuildinfo +1 -1
  37. package/dist-client/words.js +2 -2
  38. package/dist-client/words.js.map +1 -1
  39. package/dist-server/service/compliance-case/compliance-case-query.js +1 -1
  40. package/dist-server/service/compliance-case/compliance-case-query.js.map +1 -1
  41. package/dist-server/service/compliance-case/compliance-case-rules.d.ts +1 -3
  42. package/dist-server/service/compliance-case/compliance-case-rules.js +2 -4
  43. package/dist-server/service/compliance-case/compliance-case-rules.js.map +1 -1
  44. package/dist-server/service/compliance-case/compliance-case-service.d.ts +3 -3
  45. package/dist-server/service/compliance-case/compliance-case-service.js +4 -6
  46. package/dist-server/service/compliance-case/compliance-case-service.js.map +1 -1
  47. package/dist-server/service/compliance-case/compliance-case-type.js +1 -1
  48. package/dist-server/service/compliance-case/compliance-case-type.js.map +1 -1
  49. package/dist-server/service/compliance-case/compliance-case.js +1 -1
  50. package/dist-server/service/compliance-case/compliance-case.js.map +1 -1
  51. package/dist-server/service/regulation/regulation-rules.d.ts +3 -3
  52. package/dist-server/service/regulation/regulation-rules.js +17 -17
  53. package/dist-server/service/regulation/regulation-rules.js.map +1 -1
  54. package/dist-server/service/regulation/regulation.d.ts +1 -1
  55. package/dist-server/service/regulation/regulation.js +1 -1
  56. package/dist-server/service/regulation/regulation.js.map +1 -1
  57. package/dist-server/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +17 -17
  59. package/translations/en.json +27 -14
  60. package/translations/es.json +27 -14
  61. package/translations/ja.json +27 -14
  62. package/translations/ko.json +27 -14
  63. package/translations/ms.json +27 -14
  64. package/translations/zh.json +27 -14
@@ -1,9 +1,9 @@
1
- import { __decorate, __metadata } from "tslib";
1
+ import { __decorate } from "tslib";
2
2
  import '@material/web/button/text-button.js';
3
3
  import gql from 'graphql-tag';
4
4
  import { css, html, LitElement, nothing } from 'lit';
5
- import { customElement, state } from 'lit/decorators.js';
6
- import { client } from '@operato/graphql';
5
+ import { customElement } from 'lit/decorators.js';
6
+ import { QueryController } from '@operato/graphql';
7
7
  import { i18next, localize } from '@operato/i18n';
8
8
  import { trainingWord } from '../training-words.js';
9
9
  import { failureOf } from '../words.js';
@@ -15,9 +15,16 @@ import { openTrainingCertificateForm } from './training-certificate-form.js';
15
15
  let ComplianceMyTrainings = class ComplianceMyTrainings extends localize(i18next)(LitElement) {
16
16
  constructor() {
17
17
  super(...arguments);
18
- this.rows = [];
19
- this.loaded = false;
20
- this.message = '';
18
+ /* The trainings the person owes, with the sessions they may take (ADR-0190). */
19
+ this.mine = new QueryController(this, gql `
20
+ query {
21
+ myTrainings {
22
+ kind year dueOn state
23
+ completion { id status completedOn returnReason }
24
+ sessions { id name method startsOn endsOn }
25
+ }
26
+ }
27
+ `);
21
28
  }
22
29
  static { this.styles = css `
23
30
  :host {
@@ -53,14 +60,16 @@ let ComplianceMyTrainings = class ComplianceMyTrainings extends localize(i18next
53
60
  margin: 0;
54
61
  }
55
62
  `; }
56
- connectedCallback() {
57
- super.connectedCallback();
58
- this.fetch();
63
+ get rows() {
64
+ return this.mine.data?.myTrainings ?? [];
65
+ }
66
+ get message() {
67
+ return this.mine.error ? failureOf(this.mine.error) : '';
59
68
  }
60
69
  render() {
61
70
  if (this.message)
62
71
  return html `<p muted>${this.message}</p>`;
63
- if (!this.loaded)
72
+ if (!this.mine.data)
64
73
  return nothing;
65
74
  if (!this.rows.length)
66
75
  return html `<p muted>${i18next.t('text.training-mine-empty')}</p>`;
@@ -99,49 +108,11 @@ let ComplianceMyTrainings = class ComplianceMyTrainings extends localize(i18next
99
108
  </tbody>
100
109
  </table>`;
101
110
  }
102
- async fetch() {
103
- try {
104
- const response = await client.query({
105
- query: gql `
106
- query {
107
- myTrainings {
108
- kind year dueOn state
109
- completion { id status completedOn returnReason }
110
- sessions { id name method startsOn endsOn }
111
- }
112
- }
113
- `,
114
- fetchPolicy: 'network-only'
115
- });
116
- if (response.errors?.length)
117
- throw response;
118
- this.rows = response.data.myTrainings;
119
- this.message = '';
120
- }
121
- catch (error) {
122
- this.message = failureOf(error);
123
- }
124
- finally {
125
- this.loaded = true;
126
- }
127
- }
128
111
  async upload(row) {
129
112
  if (await openTrainingCertificateForm({ kind: row.kind, year: row.year, sessions: row.sessions }))
130
- this.fetch();
113
+ this.mine.refetch();
131
114
  }
132
115
  };
133
- __decorate([
134
- state(),
135
- __metadata("design:type", Array)
136
- ], ComplianceMyTrainings.prototype, "rows", void 0);
137
- __decorate([
138
- state(),
139
- __metadata("design:type", Object)
140
- ], ComplianceMyTrainings.prototype, "loaded", void 0);
141
- __decorate([
142
- state(),
143
- __metadata("design:type", Object)
144
- ], ComplianceMyTrainings.prototype, "message", void 0);
145
116
  ComplianceMyTrainings = __decorate([
146
117
  customElement('compliance-my-trainings')
147
118
  ], ComplianceMyTrainings);
@@ -1 +1 @@
1
- {"version":3,"file":"my-trainings.js","sourceRoot":"","sources":["../../client/components/my-trainings.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\n\nimport { trainingWord } from '../training-words.js'\nimport { failureOf } from '../words.js'\nimport { openTrainingCertificateForm } from './training-certificate-form.js'\n\n/**\n * 내 의무 교육 (ADR-0187 decisions 10, 17, 18) - this year's trainings the person must take: by when, whether done, the\n * sessions of it, and the certificate of one taken elsewhere. Only a certificate the manager confirmed is done.\n */\n@customElement('compliance-my-trainings')\nexport class ComplianceMyTrainings extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: block;\n color: var(--ui-ink);\n font-size: var(--ui-t-body, 13px);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th,\n td {\n text-align: left;\n vertical-align: top;\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n border-bottom: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));\n }\n th {\n color: var(--ui-muted);\n font-weight: normal;\n }\n [state='DONE'] {\n color: var(--ui-ok, var(--md-sys-color-primary));\n }\n [state='NOT_DONE'] {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n [muted] {\n color: var(--ui-muted);\n }\n p {\n margin: 0;\n }\n `\n\n @state() private rows: any[] = []\n @state() private loaded = false\n @state() private message = ''\n\n connectedCallback() {\n super.connectedCallback()\n this.fetch()\n }\n\n render() {\n if (this.message) return html`<p muted>${this.message}</p>`\n if (!this.loaded) return nothing\n if (!this.rows.length) return html`<p muted>${i18next.t('text.training-mine-empty')}</p>`\n return html`<table>\n <thead>\n <tr>\n <th>${i18next.t('field.training-kind')}</th>\n <th>${i18next.t('field.training-due-on')}</th>\n <th>${i18next.t('field.training-state')}</th>\n <th>${i18next.t('field.training-session')}</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map(\n row => html`<tr>\n <td>${trainingWord('kind', row.kind)}</td>\n <td>${row.dueOn}</td>\n <td>\n <p state=${row.state}>${trainingWord('state', row.state)}</p>\n ${row.completion?.status === 'CONFIRMED' ? html`<p muted>${row.completion.completedOn}</p>` : nothing}\n ${row.state === 'NOT_DONE' && row.completion?.status === 'RETURNED'\n ? html`<p muted>${i18next.t('text.training-returned', { reason: row.completion.returnReason ?? '' })}</p>`\n : nothing}\n </td>\n <td>\n ${row.sessions.length\n ? row.sessions.map(\n (one: any) =>\n html`<p>${one.name} · ${one.endsOn && one.endsOn !== one.startsOn ? `${one.startsOn} ~ ${one.endsOn}` : one.startsOn} · ${trainingWord('method', one.method)}</p>`\n )\n : html`<p muted>${i18next.t('text.training-no-session-yet')}</p>`}\n </td>\n <td>\n ${row.state === 'NOT_DONE'\n ? html`<md-text-button @click=${() => this.upload(row)}>${i18next.t('button.training-certificate-upload')}</md-text-button>`\n : nothing}\n </td>\n </tr>`\n )}\n </tbody>\n </table>`\n }\n\n private async fetch() {\n try {\n const response = await client.query({\n query: gql`\n query {\n myTrainings {\n kind year dueOn state\n completion { id status completedOn returnReason }\n sessions { id name method startsOn endsOn }\n }\n }\n `,\n fetchPolicy: 'network-only'\n })\n if ((response as any).errors?.length) throw response\n this.rows = response.data.myTrainings\n this.message = ''\n } catch (error) {\n this.message = failureOf(error)\n } finally {\n this.loaded = true\n }\n }\n\n private async upload(row: any) {\n if (await openTrainingCertificateForm({ kind: row.kind, year: row.year, sessions: row.sessions })) this.fetch()\n }\n}\n"]}
1
+ {"version":3,"file":"my-trainings.js","sourceRoot":"","sources":["../../client/components/my-trainings.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\nimport { QueryController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\n\nimport { trainingWord } from '../training-words.js'\nimport { failureOf } from '../words.js'\nimport { openTrainingCertificateForm } from './training-certificate-form.js'\n\n/**\n * 내 의무 교육 (ADR-0187 decisions 10, 17, 18) - this year's trainings the person must take: by when, whether done, the\n * sessions of it, and the certificate of one taken elsewhere. Only a certificate the manager confirmed is done.\n */\n@customElement('compliance-my-trainings')\nexport class ComplianceMyTrainings extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: block;\n color: var(--ui-ink);\n font-size: var(--ui-t-body, 13px);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th,\n td {\n text-align: left;\n vertical-align: top;\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n border-bottom: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));\n }\n th {\n color: var(--ui-muted);\n font-weight: normal;\n }\n [state='DONE'] {\n color: var(--ui-ok, var(--md-sys-color-primary));\n }\n [state='NOT_DONE'] {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n [muted] {\n color: var(--ui-muted);\n }\n p {\n margin: 0;\n }\n `\n\n /* The trainings the person owes, with the sessions they may take (ADR-0190). */\n private mine = new QueryController(\n this,\n gql`\n query {\n myTrainings {\n kind year dueOn state\n completion { id status completedOn returnReason }\n sessions { id name method startsOn endsOn }\n }\n }\n `\n )\n\n private get rows(): any[] {\n return this.mine.data?.myTrainings ?? []\n }\n\n private get message() {\n return this.mine.error ? failureOf(this.mine.error) : ''\n }\n\n render() {\n if (this.message) return html`<p muted>${this.message}</p>`\n if (!this.mine.data) return nothing\n if (!this.rows.length) return html`<p muted>${i18next.t('text.training-mine-empty')}</p>`\n return html`<table>\n <thead>\n <tr>\n <th>${i18next.t('field.training-kind')}</th>\n <th>${i18next.t('field.training-due-on')}</th>\n <th>${i18next.t('field.training-state')}</th>\n <th>${i18next.t('field.training-session')}</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map(\n row => html`<tr>\n <td>${trainingWord('kind', row.kind)}</td>\n <td>${row.dueOn}</td>\n <td>\n <p state=${row.state}>${trainingWord('state', row.state)}</p>\n ${row.completion?.status === 'CONFIRMED' ? html`<p muted>${row.completion.completedOn}</p>` : nothing}\n ${row.state === 'NOT_DONE' && row.completion?.status === 'RETURNED'\n ? html`<p muted>${i18next.t('text.training-returned', { reason: row.completion.returnReason ?? '' })}</p>`\n : nothing}\n </td>\n <td>\n ${row.sessions.length\n ? row.sessions.map(\n (one: any) =>\n html`<p>${one.name} · ${one.endsOn && one.endsOn !== one.startsOn ? `${one.startsOn} ~ ${one.endsOn}` : one.startsOn} · ${trainingWord('method', one.method)}</p>`\n )\n : html`<p muted>${i18next.t('text.training-no-session-yet')}</p>`}\n </td>\n <td>\n ${row.state === 'NOT_DONE'\n ? html`<md-text-button @click=${() => this.upload(row)}>${i18next.t('button.training-certificate-upload')}</md-text-button>`\n : nothing}\n </td>\n </tr>`\n )}\n </tbody>\n </table>`\n }\n\n private async upload(row: any) {\n if (await openTrainingCertificateForm({ kind: row.kind, year: row.year, sessions: row.sessions })) this.mine.refetch()\n }\n}\n"]}
@@ -24,7 +24,7 @@ export declare class SealUseForm extends SealUseForm_base {
24
24
  static styles: import("lit").CSSResult[];
25
25
  prefill: SealUsePrefill;
26
26
  private kind;
27
- private sealId;
27
+ private chosenSeal?;
28
28
  private requesterId;
29
29
  private usedOn;
30
30
  private document;
@@ -34,11 +34,14 @@ export declare class SealUseForm extends SealUseForm_base {
34
34
  private copies;
35
35
  private usableUntil;
36
36
  private notes;
37
- private seals;
38
- private people;
39
- private working;
40
- private message;
41
- connectedCallback(): Promise<void>;
37
+ private choices;
38
+ private recording;
39
+ connectedCallback(): void;
40
+ private get seals();
41
+ private get people();
42
+ private get sealId();
43
+ private get working();
44
+ private get message();
42
45
  render(): import("lit-html").TemplateResult<1>;
43
46
  /** One value among many - the framework popup list with its search box on top. */
44
47
  private chooser;
@@ -8,7 +8,7 @@ import '@operato/popup/ox-popup-list.js';
8
8
  import gql from 'graphql-tag';
9
9
  import { css, html, LitElement, nothing } from 'lit';
10
10
  import { customElement, property, state } from 'lit/decorators.js';
11
- import { client } from '@operato/graphql';
11
+ import { MutationController, QueryController } from '@operato/graphql';
12
12
  import { i18next, localize } from '@operato/i18n';
13
13
  import { notify, openPopup } from '@operato/layout';
14
14
  import { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles';
@@ -34,7 +34,6 @@ let SealUseForm = class SealUseForm extends localize(i18next)(LitElement) {
34
34
  super(...arguments);
35
35
  this.prefill = {};
36
36
  this.kind = 'STAMP';
37
- this.sealId = '';
38
37
  this.requesterId = '';
39
38
  this.usedOn = today();
40
39
  this.document = '';
@@ -44,10 +43,23 @@ let SealUseForm = class SealUseForm extends localize(i18next)(LitElement) {
44
43
  this.copies = '1';
45
44
  this.usableUntil = '';
46
45
  this.notes = '';
47
- this.seals = [];
48
- this.people = [];
49
- this.working = false;
50
- this.message = '';
46
+ /* The seals in use and the employees who may ask for one (ADR-0190). */
47
+ this.choices = new QueryController(this, gql `
48
+ query {
49
+ companySeals(filters: [{ name: "disposedOn", operator: "is_null" }], pagination: { page: 1, limit: 100 }) {
50
+ items { id kind name }
51
+ }
52
+ employees(filters: [{ name: "retiredOn", operator: "is_null" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: "name" }]) {
53
+ items { id name controlNo }
54
+ }
55
+ }
56
+ `);
57
+ /* Its failure is drawn under the notes, beside the form. */
58
+ this.recording = new MutationController(this, gql `
59
+ mutation ($use: NewSealUse!) {
60
+ recordSealUse(use: $use) { id status }
61
+ }
62
+ `, { showsError: true });
51
63
  }
52
64
  /* The house shape of a popup (page-standard sections 7, 8): only the body scrolls, fields are labels above native
53
65
  inputs, the one button row is `ox-popup-actions`. */
@@ -77,30 +89,30 @@ let SealUseForm = class SealUseForm extends localize(i18next)(LitElement) {
77
89
  }
78
90
  `
79
91
  ]; }
80
- async connectedCallback() {
92
+ connectedCallback() {
81
93
  super.connectedCallback();
82
94
  const { kind, document, purpose, submittedTo } = this.prefill ?? {};
83
95
  Object.assign(this, { kind: kind ?? this.kind, document: document ?? '', purpose: purpose ?? '', submittedTo: submittedTo ?? '' });
84
- const response = await client.query({
85
- query: gql `
86
- query {
87
- companySeals(filters: [{ name: "disposedOn", operator: "is_null" }], pagination: { page: 1, limit: 100 }) {
88
- items { id kind name }
89
- }
90
- employees(filters: [{ name: "retiredOn", operator: "is_null" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: "name" }]) {
91
- items { id name controlNo }
92
- }
93
- }
94
- `,
95
- fetchPolicy: 'no-cache'
96
- });
96
+ }
97
+ get seals() {
97
98
  /* The kind is said beside a name that does not say it already - 「사용인감 1호」, not 「법인인감 (법인인감)」. */
98
99
  const named = (one) => (one.name.includes(wordOf('company-seal-kind', one.kind)) ? one.name : `${one.name} (${wordOf('company-seal-kind', one.kind)})`);
99
- this.seals = (response.data?.companySeals?.items ?? []).map((one) => ({ value: one.id, display: named(one), kind: one.kind }));
100
- this.people = (response.data?.employees?.items ?? []).map((one) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }));
100
+ return (this.choices.data?.companySeals?.items ?? []).map((one) => ({ value: one.id, display: named(one), kind: one.kind }));
101
+ }
102
+ get people() {
103
+ return (this.choices.data?.employees?.items ?? []).map((one) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }));
104
+ }
105
+ get sealId() {
106
+ if (this.chosenSeal !== undefined)
107
+ return this.chosenSeal;
101
108
  const wanted = this.prefill?.sealKind;
102
- if (wanted)
103
- this.sealId = this.seals.find(one => one.kind === wanted)?.value ?? '';
109
+ return (wanted && this.seals.find(one => one.kind === wanted)?.value) || '';
110
+ }
111
+ get working() {
112
+ return this.recording.pending;
113
+ }
114
+ get message() {
115
+ return this.recording.error ? failureOf(this.recording.error) : '';
104
116
  }
105
117
  render() {
106
118
  const certificate = this.kind === 'CERTIFICATE';
@@ -119,7 +131,7 @@ let SealUseForm = class SealUseForm extends localize(i18next)(LitElement) {
119
131
 
120
132
  <label class="field">
121
133
  <span>${i18next.t('field.seal-use-seal')}</span>
122
- ${this.chooser(seals, this.sealId, value => (this.sealId = value))}
134
+ ${this.chooser(seals, this.sealId, value => (this.chosenSeal = value))}
123
135
  </label>
124
136
 
125
137
  <label class="field">
@@ -189,44 +201,27 @@ let SealUseForm = class SealUseForm extends localize(i18next)(LitElement) {
189
201
  </ox-select>`;
190
202
  }
191
203
  async record() {
192
- this.message = '';
193
- this.working = true;
194
- try {
195
- const certificate = this.kind === 'CERTIFICATE';
196
- const response = await client.mutate({
197
- mutation: gql `
198
- mutation ($use: NewSealUse!) {
199
- recordSealUse(use: $use) { id status }
200
- }
201
- `,
202
- variables: {
203
- use: {
204
- kind: this.kind,
205
- sealId: this.sealId,
206
- requesterId: this.requesterId || null,
207
- usedOn: this.usedOn,
208
- document: certificate ? null : this.document,
209
- purpose: this.purpose,
210
- submittedTo: this.submittedTo,
211
- returnDueOn: this.kind === 'TAKE_OUT' ? this.returnDueOn || null : null,
212
- copies: certificate ? Number(this.copies) || null : null,
213
- usableUntil: certificate ? this.usableUntil || null : null,
214
- notes: this.notes
215
- }
216
- }
217
- });
218
- if (response.errors?.length)
219
- throw response;
220
- const written = response.data.recordSealUse;
221
- notify({ message: i18next.t(written.status === 'SUBMITTED' ? 'text.seal-use-submitted' : 'text.seal-use-recorded') });
222
- this.dispatchEvent(new CustomEvent('recorded', { detail: written }));
223
- }
224
- catch (error) {
225
- this.message = failureOf(error);
226
- }
227
- finally {
228
- this.working = false;
229
- }
204
+ const certificate = this.kind === 'CERTIFICATE';
205
+ const done = await this.recording.run({
206
+ use: {
207
+ kind: this.kind,
208
+ sealId: this.sealId,
209
+ requesterId: this.requesterId || null,
210
+ usedOn: this.usedOn,
211
+ document: certificate ? null : this.document,
212
+ purpose: this.purpose,
213
+ submittedTo: this.submittedTo,
214
+ returnDueOn: this.kind === 'TAKE_OUT' ? this.returnDueOn || null : null,
215
+ copies: certificate ? Number(this.copies) || null : null,
216
+ usableUntil: certificate ? this.usableUntil || null : null,
217
+ notes: this.notes
218
+ }
219
+ });
220
+ if (!done)
221
+ return;
222
+ const written = done.recordSealUse;
223
+ notify({ message: i18next.t(written.status === 'SUBMITTED' ? 'text.seal-use-submitted' : 'text.seal-use-recorded') });
224
+ this.dispatchEvent(new CustomEvent('recorded', { detail: written }));
230
225
  }
231
226
  };
232
227
  __decorate([
@@ -239,8 +234,8 @@ __decorate([
239
234
  ], SealUseForm.prototype, "kind", void 0);
240
235
  __decorate([
241
236
  state(),
242
- __metadata("design:type", Object)
243
- ], SealUseForm.prototype, "sealId", void 0);
237
+ __metadata("design:type", String)
238
+ ], SealUseForm.prototype, "chosenSeal", void 0);
244
239
  __decorate([
245
240
  state(),
246
241
  __metadata("design:type", Object)
@@ -277,22 +272,6 @@ __decorate([
277
272
  state(),
278
273
  __metadata("design:type", Object)
279
274
  ], SealUseForm.prototype, "notes", void 0);
280
- __decorate([
281
- state(),
282
- __metadata("design:type", Array)
283
- ], SealUseForm.prototype, "seals", void 0);
284
- __decorate([
285
- state(),
286
- __metadata("design:type", Array)
287
- ], SealUseForm.prototype, "people", void 0);
288
- __decorate([
289
- state(),
290
- __metadata("design:type", Object)
291
- ], SealUseForm.prototype, "working", void 0);
292
- __decorate([
293
- state(),
294
- __metadata("design:type", Object)
295
- ], SealUseForm.prototype, "message", void 0);
296
275
  SealUseForm = __decorate([
297
276
  customElement('seal-use-form')
298
277
  ], SealUseForm);
@@ -1 +1 @@
1
- {"version":3,"file":"seal-use-form.js","sourceRoot":"","sources":["../../client/components/seal-use-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@operato/input/ox-input-select-buttons.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-actions.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles'\n\nimport { failureOf, USE_KINDS, wordOf } from '../words.js'\n\n/** What the form is opened with - a 사용인감계 just issued asks for the corporate seal's stamp on it. */\nexport interface SealUsePrefill {\n kind?: string\n sealKind?: string\n document?: string\n purpose?: string\n submittedTo?: string\n}\n\ntype Choice = { value: string; display: string; kind?: string }\n\n/** Opens the form; resolves with the written use, or null when the person closed it. */\nexport function openSealUseForm(prefill: SealUsePrefill = {}): Promise<any | null> {\n return new Promise(resolve => {\n let done: any = null\n const handle: any = openPopup(\n html`<seal-use-form .prefill=${prefill} @close=${() => handle.close()} @recorded=${(e: CustomEvent) => ((done = e.detail), handle.close())}></seal-use-form>`,\n { backdrop: true, size: 'medium', title: i18next.t('title.seal-use-record') }\n )\n handle.onclosed = () => resolve(done)\n })\n}\n\nconst today = () => {\n const now = new Date()\n return new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 10)\n}\n\n/**\n * 날인 기록 쓰기 (ADR-0188 decision 2) - which seal, what was done with it, who asked, for which paper and where it goes.\n * The server decides whether it goes up for approval; the guide says when.\n */\n@customElement('seal-use-form')\nexport class SealUseForm extends localize(i18next)(LitElement) {\n /* The house shape of a popup (page-standard sections 7, 8): only the body scrolls, fields are labels above native\n inputs, the one button row is `ox-popup-actions`. */\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n PopupFieldStyles,\n css`\n [invalid] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--ui-t-small, 11.5px);\n }\n [invalid]:empty {\n display: none;\n }\n [guide] p {\n margin: 0;\n color: var(--ui-muted);\n line-height: var(--popup-line-height);\n }\n ox-input-select-buttons {\n align-self: flex-start;\n }\n ox-select {\n width: 100%;\n }\n `\n ]\n\n @property({ type: Object }) prefill: SealUsePrefill = {}\n\n @state() private kind = 'STAMP'\n @state() private sealId = ''\n @state() private requesterId = ''\n @state() private usedOn = today()\n @state() private document = ''\n @state() private purpose = ''\n @state() private submittedTo = ''\n @state() private returnDueOn = ''\n @state() private copies = '1'\n @state() private usableUntil = ''\n @state() private notes = ''\n @state() private seals: Choice[] = []\n @state() private people: Choice[] = []\n @state() private working = false\n @state() private message = ''\n\n async connectedCallback() {\n super.connectedCallback()\n const { kind, document, purpose, submittedTo } = this.prefill ?? {}\n Object.assign(this, { kind: kind ?? this.kind, document: document ?? '', purpose: purpose ?? '', submittedTo: submittedTo ?? '' })\n const response = await client.query({\n query: gql`\n query {\n companySeals(filters: [{ name: \"disposedOn\", operator: \"is_null\" }], pagination: { page: 1, limit: 100 }) {\n items { id kind name }\n }\n employees(filters: [{ name: \"retiredOn\", operator: \"is_null\" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: \"name\" }]) {\n items { id name controlNo }\n }\n }\n `,\n fetchPolicy: 'no-cache'\n })\n /* The kind is said beside a name that does not say it already - 「사용인감 1호」, not 「법인인감 (법인인감)」. */\n const named = (one: any) => (one.name.includes(wordOf('company-seal-kind', one.kind)) ? one.name : `${one.name} (${wordOf('company-seal-kind', one.kind)})`)\n this.seals = (response.data?.companySeals?.items ?? []).map((one: any) => ({ value: one.id, display: named(one), kind: one.kind }))\n this.people = (response.data?.employees?.items ?? []).map((one: any) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }))\n const wanted = this.prefill?.sealKind\n if (wanted) this.sealId = this.seals.find(one => one.kind === wanted)?.value ?? ''\n }\n\n render() {\n const certificate = this.kind === 'CERTIFICATE'\n const seals = certificate ? this.seals.filter(one => one.kind === 'CORPORATE') : this.seals\n return html`\n <div class=\"body\">\n <div guide><p>${i18next.t('text.seal-use-approval-guide')}</p></div>\n\n <div class=\"field\">\n <ox-input-select-buttons\n .value=${this.kind}\n .options=${USE_KINDS.map(code => ({ display: wordOf('seal-use-kind', code), value: code }))}\n @change=${(e: CustomEvent) => e.detail && (this.kind = e.detail)}\n ></ox-input-select-buttons>\n </div>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-seal')}</span>\n ${this.chooser(seals, this.sealId, value => (this.sealId = value))}\n </label>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-requester')}</span>\n ${this.chooser(this.people, this.requesterId, value => (this.requesterId = value))}\n </label>\n\n <label class=\"field\">\n <span>${i18next.t(`field.seal-use-used-on-${this.kind.toLowerCase().replace('_', '-')}`)}</span>\n <input type=\"date\" .value=${this.usedOn} @input=${(e: any) => (this.usedOn = e.target.value)} />\n </label>\n\n ${certificate\n ? nothing\n : html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-document')}</span>\n <input .value=${this.document} @input=${(e: any) => (this.document = e.target.value)} />\n </label>`}\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-purpose')}</span>\n <input .value=${this.purpose} @input=${(e: any) => (this.purpose = e.target.value)} />\n </label>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-submitted-to')}</span>\n <input .value=${this.submittedTo} @input=${(e: any) => (this.submittedTo = e.target.value)} />\n </label>\n\n ${this.kind === 'TAKE_OUT'\n ? html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-return-due-on')}</span>\n <input type=\"date\" .value=${this.returnDueOn} @input=${(e: any) => (this.returnDueOn = e.target.value)} />\n </label>`\n : nothing}\n ${certificate\n ? html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-copies')}</span>\n <input type=\"number\" min=\"1\" .value=${this.copies} @input=${(e: any) => (this.copies = e.target.value)} />\n </label>\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-usable-until')}</span>\n <input type=\"date\" .value=${this.usableUntil} @input=${(e: any) => (this.usableUntil = e.target.value)} />\n <span>${i18next.t('text.seal-use-usable-until-hint')}</span>\n </label>`\n : nothing}\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-notes')}</span>\n <input .value=${this.notes} @input=${(e: any) => (this.notes = e.target.value)} />\n <span invalid>${this.message}</span>\n </label>\n </div>\n\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${() => this.dispatchEvent(new CustomEvent('close'))}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${this.working} @click=${() => this.record()}>${i18next.t('button.seal-use-record')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n /** One value among many - the framework popup list with its search box on top. */\n private chooser(options: Choice[], value: string, change: (value: string) => void) {\n const shown = options.find(one => one.value === value)?.display ?? '—'\n return html`<ox-select .value=${value} @change=${(e: CustomEvent) => String(e.detail ?? '') !== value && change(String(e.detail ?? ''))}>\n <span slot=\"label\">${shown}</span>\n <ox-popup-list align-left nowrap with-search>${options.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>`\n }\n\n private async record() {\n this.message = ''\n this.working = true\n try {\n const certificate = this.kind === 'CERTIFICATE'\n const response = await client.mutate({\n mutation: gql`\n mutation ($use: NewSealUse!) {\n recordSealUse(use: $use) { id status }\n }\n `,\n variables: {\n use: {\n kind: this.kind,\n sealId: this.sealId,\n requesterId: this.requesterId || null,\n usedOn: this.usedOn,\n document: certificate ? null : this.document,\n purpose: this.purpose,\n submittedTo: this.submittedTo,\n returnDueOn: this.kind === 'TAKE_OUT' ? this.returnDueOn || null : null,\n copies: certificate ? Number(this.copies) || null : null,\n usableUntil: certificate ? this.usableUntil || null : null,\n notes: this.notes\n }\n }\n })\n if ((response as any).errors?.length) throw response\n const written = response.data.recordSealUse\n notify({ message: i18next.t(written.status === 'SUBMITTED' ? 'text.seal-use-submitted' : 'text.seal-use-recorded') })\n this.dispatchEvent(new CustomEvent('recorded', { detail: written }))\n } catch (error) {\n this.message = failureOf(error)\n } finally {\n this.working = false\n }\n }\n}\n"]}
1
+ {"version":3,"file":"seal-use-form.js","sourceRoot":"","sources":["../../client/components/seal-use-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@operato/input/ox-input-select-buttons.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-actions.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { MutationController, QueryController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles'\n\nimport { failureOf, USE_KINDS, wordOf } from '../words.js'\n\n/** What the form is opened with - a 사용인감계 just issued asks for the corporate seal's stamp on it. */\nexport interface SealUsePrefill {\n kind?: string\n sealKind?: string\n document?: string\n purpose?: string\n submittedTo?: string\n}\n\ntype Choice = { value: string; display: string; kind?: string }\n\n/** Opens the form; resolves with the written use, or null when the person closed it. */\nexport function openSealUseForm(prefill: SealUsePrefill = {}): Promise<any | null> {\n return new Promise(resolve => {\n let done: any = null\n const handle: any = openPopup(\n html`<seal-use-form .prefill=${prefill} @close=${() => handle.close()} @recorded=${(e: CustomEvent) => ((done = e.detail), handle.close())}></seal-use-form>`,\n { backdrop: true, size: 'medium', title: i18next.t('title.seal-use-record') }\n )\n handle.onclosed = () => resolve(done)\n })\n}\n\nconst today = () => {\n const now = new Date()\n return new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 10)\n}\n\n/**\n * 날인 기록 쓰기 (ADR-0188 decision 2) - which seal, what was done with it, who asked, for which paper and where it goes.\n * The server decides whether it goes up for approval; the guide says when.\n */\n@customElement('seal-use-form')\nexport class SealUseForm extends localize(i18next)(LitElement) {\n /* The house shape of a popup (page-standard sections 7, 8): only the body scrolls, fields are labels above native\n inputs, the one button row is `ox-popup-actions`. */\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n PopupFieldStyles,\n css`\n [invalid] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--ui-t-small, 11.5px);\n }\n [invalid]:empty {\n display: none;\n }\n [guide] p {\n margin: 0;\n color: var(--ui-muted);\n line-height: var(--popup-line-height);\n }\n ox-input-select-buttons {\n align-self: flex-start;\n }\n ox-select {\n width: 100%;\n }\n `\n ]\n\n @property({ type: Object }) prefill: SealUsePrefill = {}\n\n @state() private kind = 'STAMP'\n /* The seal chosen - undefined until one is, while the one the prefill names stands. */\n @state() private chosenSeal?: string\n @state() private requesterId = ''\n @state() private usedOn = today()\n @state() private document = ''\n @state() private purpose = ''\n @state() private submittedTo = ''\n @state() private returnDueOn = ''\n @state() private copies = '1'\n @state() private usableUntil = ''\n @state() private notes = ''\n /* The seals in use and the employees who may ask for one (ADR-0190). */\n private choices = new QueryController(\n this,\n gql`\n query {\n companySeals(filters: [{ name: \"disposedOn\", operator: \"is_null\" }], pagination: { page: 1, limit: 100 }) {\n items { id kind name }\n }\n employees(filters: [{ name: \"retiredOn\", operator: \"is_null\" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: \"name\" }]) {\n items { id name controlNo }\n }\n }\n `\n )\n\n /* Its failure is drawn under the notes, beside the form. */\n private recording = new MutationController(\n this,\n gql`\n mutation ($use: NewSealUse!) {\n recordSealUse(use: $use) { id status }\n }\n `,\n { showsError: true }\n )\n\n connectedCallback() {\n super.connectedCallback()\n const { kind, document, purpose, submittedTo } = this.prefill ?? {}\n Object.assign(this, { kind: kind ?? this.kind, document: document ?? '', purpose: purpose ?? '', submittedTo: submittedTo ?? '' })\n }\n\n private get seals(): Choice[] {\n /* The kind is said beside a name that does not say it already - 「사용인감 1호」, not 「법인인감 (법인인감)」. */\n const named = (one: any) => (one.name.includes(wordOf('company-seal-kind', one.kind)) ? one.name : `${one.name} (${wordOf('company-seal-kind', one.kind)})`)\n return (this.choices.data?.companySeals?.items ?? []).map((one: any) => ({ value: one.id, display: named(one), kind: one.kind }))\n }\n\n private get people(): Choice[] {\n return (this.choices.data?.employees?.items ?? []).map((one: any) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }))\n }\n\n private get sealId(): string {\n if (this.chosenSeal !== undefined) return this.chosenSeal\n const wanted = this.prefill?.sealKind\n return (wanted && this.seals.find(one => one.kind === wanted)?.value) || ''\n }\n\n private get working() {\n return this.recording.pending\n }\n\n private get message() {\n return this.recording.error ? failureOf(this.recording.error) : ''\n }\n\n render() {\n const certificate = this.kind === 'CERTIFICATE'\n const seals = certificate ? this.seals.filter(one => one.kind === 'CORPORATE') : this.seals\n return html`\n <div class=\"body\">\n <div guide><p>${i18next.t('text.seal-use-approval-guide')}</p></div>\n\n <div class=\"field\">\n <ox-input-select-buttons\n .value=${this.kind}\n .options=${USE_KINDS.map(code => ({ display: wordOf('seal-use-kind', code), value: code }))}\n @change=${(e: CustomEvent) => e.detail && (this.kind = e.detail)}\n ></ox-input-select-buttons>\n </div>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-seal')}</span>\n ${this.chooser(seals, this.sealId, value => (this.chosenSeal = value))}\n </label>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-requester')}</span>\n ${this.chooser(this.people, this.requesterId, value => (this.requesterId = value))}\n </label>\n\n <label class=\"field\">\n <span>${i18next.t(`field.seal-use-used-on-${this.kind.toLowerCase().replace('_', '-')}`)}</span>\n <input type=\"date\" .value=${this.usedOn} @input=${(e: any) => (this.usedOn = e.target.value)} />\n </label>\n\n ${certificate\n ? nothing\n : html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-document')}</span>\n <input .value=${this.document} @input=${(e: any) => (this.document = e.target.value)} />\n </label>`}\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-purpose')}</span>\n <input .value=${this.purpose} @input=${(e: any) => (this.purpose = e.target.value)} />\n </label>\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-submitted-to')}</span>\n <input .value=${this.submittedTo} @input=${(e: any) => (this.submittedTo = e.target.value)} />\n </label>\n\n ${this.kind === 'TAKE_OUT'\n ? html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-return-due-on')}</span>\n <input type=\"date\" .value=${this.returnDueOn} @input=${(e: any) => (this.returnDueOn = e.target.value)} />\n </label>`\n : nothing}\n ${certificate\n ? html`<label class=\"field\">\n <span>${i18next.t('field.seal-use-copies')}</span>\n <input type=\"number\" min=\"1\" .value=${this.copies} @input=${(e: any) => (this.copies = e.target.value)} />\n </label>\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-usable-until')}</span>\n <input type=\"date\" .value=${this.usableUntil} @input=${(e: any) => (this.usableUntil = e.target.value)} />\n <span>${i18next.t('text.seal-use-usable-until-hint')}</span>\n </label>`\n : nothing}\n\n <label class=\"field\">\n <span>${i18next.t('field.seal-use-notes')}</span>\n <input .value=${this.notes} @input=${(e: any) => (this.notes = e.target.value)} />\n <span invalid>${this.message}</span>\n </label>\n </div>\n\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${() => this.dispatchEvent(new CustomEvent('close'))}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${this.working} @click=${() => this.record()}>${i18next.t('button.seal-use-record')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n /** One value among many - the framework popup list with its search box on top. */\n private chooser(options: Choice[], value: string, change: (value: string) => void) {\n const shown = options.find(one => one.value === value)?.display ?? '—'\n return html`<ox-select .value=${value} @change=${(e: CustomEvent) => String(e.detail ?? '') !== value && change(String(e.detail ?? ''))}>\n <span slot=\"label\">${shown}</span>\n <ox-popup-list align-left nowrap with-search>${options.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>`\n }\n\n private async record() {\n const certificate = this.kind === 'CERTIFICATE'\n const done = await this.recording.run({\n use: {\n kind: this.kind,\n sealId: this.sealId,\n requesterId: this.requesterId || null,\n usedOn: this.usedOn,\n document: certificate ? null : this.document,\n purpose: this.purpose,\n submittedTo: this.submittedTo,\n returnDueOn: this.kind === 'TAKE_OUT' ? this.returnDueOn || null : null,\n copies: certificate ? Number(this.copies) || null : null,\n usableUntil: certificate ? this.usableUntil || null : null,\n notes: this.notes\n }\n })\n if (!done) return\n const written = done.recordSealUse\n notify({ message: i18next.t(written.status === 'SUBMITTED' ? 'text.seal-use-submitted' : 'text.seal-use-recorded') })\n this.dispatchEvent(new CustomEvent('recorded', { detail: written }))\n }\n}\n"]}
@@ -25,12 +25,14 @@ export declare class TrainingAttendanceForm extends TrainingAttendanceForm_base
25
25
  startsOn: string;
26
26
  endsOn?: string | null;
27
27
  };
28
- private people;
29
28
  private chosen;
30
29
  private completedOn;
31
- private working;
32
- private message;
33
- connectedCallback(): Promise<void>;
30
+ private employees;
31
+ private recording;
32
+ connectedCallback(): void;
33
+ private get people();
34
+ private get working();
35
+ private get message();
34
36
  render(): import("lit-html").TemplateResult<1>;
35
37
  private record;
36
38
  }
@@ -8,7 +8,7 @@ import '@operato/popup/ox-popup-list.js';
8
8
  import gql from 'graphql-tag';
9
9
  import { css, html, LitElement } from 'lit';
10
10
  import { customElement, property, state } from 'lit/decorators.js';
11
- import { client } from '@operato/graphql';
11
+ import { MutationController, QueryController } from '@operato/graphql';
12
12
  import { i18next, localize } from '@operato/i18n';
13
13
  import { notify, openPopup } from '@operato/layout';
14
14
  import { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles';
@@ -28,11 +28,22 @@ export function openTrainingAttendanceForm(session) {
28
28
  let TrainingAttendanceForm = class TrainingAttendanceForm extends localize(i18next)(LitElement) {
29
29
  constructor() {
30
30
  super(...arguments);
31
- this.people = [];
32
31
  this.chosen = [];
33
32
  this.completedOn = '';
34
- this.working = false;
35
- this.message = '';
33
+ /* The employees who may have attended (ADR-0190). */
34
+ this.employees = new QueryController(this, gql `
35
+ query {
36
+ employees(filters: [{ name: "retiredOn", operator: "is_null" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: "name" }]) {
37
+ items { id name controlNo }
38
+ }
39
+ }
40
+ `);
41
+ /* Its failure is drawn under the attendees, beside the form. */
42
+ this.recording = new MutationController(this, gql `
43
+ mutation ($sessionId: String!, $employeeIds: [String!]!, $completedOn: String) {
44
+ recordTrainingAttendance(sessionId: $sessionId, employeeIds: $employeeIds, completedOn: $completedOn) { id }
45
+ }
46
+ `, { showsError: true });
36
47
  }
37
48
  static { this.styles = [
38
49
  CommonPopupStyles,
@@ -82,20 +93,18 @@ let TrainingAttendanceForm = class TrainingAttendanceForm extends localize(i18ne
82
93
  }
83
94
  `
84
95
  ]; }
85
- async connectedCallback() {
96
+ connectedCallback() {
86
97
  super.connectedCallback();
87
98
  this.completedOn = this.session.endsOn || this.session.startsOn;
88
- const response = await client.query({
89
- query: gql `
90
- query {
91
- employees(filters: [{ name: "retiredOn", operator: "is_null" }], pagination: { page: 1, limit: 500 }, sortings: [{ name: "name" }]) {
92
- items { id name controlNo }
93
- }
94
- }
95
- `,
96
- fetchPolicy: 'no-cache'
97
- });
98
- this.people = (response.data?.employees?.items ?? []).map((one) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }));
99
+ }
100
+ get people() {
101
+ return (this.employees.data?.employees?.items ?? []).map((one) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }));
102
+ }
103
+ get working() {
104
+ return this.recording.pending;
105
+ }
106
+ get message() {
107
+ return this.recording.error ? failureOf(this.recording.error) : '';
99
108
  }
100
109
  render() {
101
110
  const left = this.people.filter(one => !this.chosen.includes(one.value));
@@ -131,38 +140,17 @@ let TrainingAttendanceForm = class TrainingAttendanceForm extends localize(i18ne
131
140
  `;
132
141
  }
133
142
  async record() {
134
- this.message = '';
135
- this.working = true;
136
- try {
137
- const response = await client.mutate({
138
- mutation: gql `
139
- mutation ($sessionId: String!, $employeeIds: [String!]!, $completedOn: String) {
140
- recordTrainingAttendance(sessionId: $sessionId, employeeIds: $employeeIds, completedOn: $completedOn) { id }
141
- }
142
- `,
143
- variables: { sessionId: this.session.id, employeeIds: this.chosen, completedOn: this.completedOn || null }
144
- });
145
- if (response.errors?.length)
146
- throw response;
147
- notify({ message: i18next.t('text.training-attendance-recorded', { count: response.data.recordTrainingAttendance.length }) });
148
- this.dispatchEvent(new CustomEvent('recorded'));
149
- }
150
- catch (error) {
151
- this.message = failureOf(error);
152
- }
153
- finally {
154
- this.working = false;
155
- }
143
+ const done = await this.recording.run({ sessionId: this.session.id, employeeIds: this.chosen, completedOn: this.completedOn || null });
144
+ if (!done)
145
+ return;
146
+ notify({ message: i18next.t('text.training-attendance-recorded', { count: done.recordTrainingAttendance.length }) });
147
+ this.dispatchEvent(new CustomEvent('recorded'));
156
148
  }
157
149
  };
158
150
  __decorate([
159
151
  property({ type: Object }),
160
152
  __metadata("design:type", Object)
161
153
  ], TrainingAttendanceForm.prototype, "session", void 0);
162
- __decorate([
163
- state(),
164
- __metadata("design:type", Array)
165
- ], TrainingAttendanceForm.prototype, "people", void 0);
166
154
  __decorate([
167
155
  state(),
168
156
  __metadata("design:type", Array)
@@ -171,14 +159,6 @@ __decorate([
171
159
  state(),
172
160
  __metadata("design:type", Object)
173
161
  ], TrainingAttendanceForm.prototype, "completedOn", void 0);
174
- __decorate([
175
- state(),
176
- __metadata("design:type", Object)
177
- ], TrainingAttendanceForm.prototype, "working", void 0);
178
- __decorate([
179
- state(),
180
- __metadata("design:type", Object)
181
- ], TrainingAttendanceForm.prototype, "message", void 0);
182
162
  TrainingAttendanceForm = __decorate([
183
163
  customElement('training-attendance-form')
184
164
  ], TrainingAttendanceForm);