@things-factory/pdf 10.1.227 → 10.1.231

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 (71) hide show
  1. package/dist-client/index.d.ts +2 -0
  2. package/dist-client/index.js +2 -0
  3. package/dist-client/index.js.map +1 -0
  4. package/dist-client/issue-document.d.ts +44 -0
  5. package/dist-client/issue-document.js +162 -0
  6. package/dist-client/issue-document.js.map +1 -0
  7. package/dist-client/pages/issued-document/issued-document-list.d.ts +52 -0
  8. package/dist-client/pages/issued-document/issued-document-list.js +265 -0
  9. package/dist-client/pages/issued-document/issued-document-list.js.map +1 -0
  10. package/dist-client/pages/pdf-template/pdf-template-list-page.js +12 -0
  11. package/dist-client/pages/pdf-template/pdf-template-list-page.js.map +1 -1
  12. package/dist-client/route.d.ts +1 -1
  13. package/dist-client/route.js +3 -2
  14. package/dist-client/route.js.map +1 -1
  15. package/dist-client/tsconfig.tsbuildinfo +1 -1
  16. package/dist-server/controller/issued-document-kind.d.ts +60 -0
  17. package/dist-server/controller/issued-document-kind.js +48 -0
  18. package/dist-server/controller/issued-document-kind.js.map +1 -0
  19. package/dist-server/controller/pdf-release-reader.d.ts +1 -0
  20. package/dist-server/controller/pdf-release-reader.js +15 -0
  21. package/dist-server/controller/pdf-release-reader.js.map +1 -0
  22. package/dist-server/controller/pdf-release-service.d.ts +29 -4
  23. package/dist-server/controller/pdf-release-service.js +120 -9
  24. package/dist-server/controller/pdf-release-service.js.map +1 -1
  25. package/dist-server/index.d.ts +6 -1
  26. package/dist-server/index.js +13 -1
  27. package/dist-server/index.js.map +1 -1
  28. package/dist-server/role-tasks.js +3 -1
  29. package/dist-server/role-tasks.js.map +1 -1
  30. package/dist-server/service/index.d.ts +10 -1
  31. package/dist-server/service/index.js +1 -0
  32. package/dist-server/service/index.js.map +1 -1
  33. package/dist-server/service/pdf-generate/pdf-generate-resolver.d.ts +0 -2
  34. package/dist-server/service/pdf-generate/pdf-generate-resolver.js +8 -18
  35. package/dist-server/service/pdf-generate/pdf-generate-resolver.js.map +1 -1
  36. package/dist-server/service/pdf-release/index.d.ts +2 -2
  37. package/dist-server/service/pdf-release/index.js +4 -3
  38. package/dist-server/service/pdf-release/index.js.map +1 -1
  39. package/dist-server/service/pdf-release/pdf-release-query.d.ts +31 -5
  40. package/dist-server/service/pdf-release/pdf-release-query.js +213 -30
  41. package/dist-server/service/pdf-release/pdf-release-query.js.map +1 -1
  42. package/dist-server/service/pdf-release/pdf-release-type.d.ts +1 -16
  43. package/dist-server/service/pdf-release/pdf-release-type.js +4 -60
  44. package/dist-server/service/pdf-release/pdf-release-type.js.map +1 -1
  45. package/dist-server/service/pdf-release/pdf-release.d.ts +13 -1
  46. package/dist-server/service/pdf-release/pdf-release.js +67 -4
  47. package/dist-server/service/pdf-release/pdf-release.js.map +1 -1
  48. package/dist-server/service/pdf-template/pdf-template-type.d.ts +2 -0
  49. package/dist-server/service/pdf-template/pdf-template-type.js +8 -0
  50. package/dist-server/service/pdf-template/pdf-template-type.js.map +1 -1
  51. package/dist-server/service/pdf-template/pdf-template.d.ts +1 -0
  52. package/dist-server/service/pdf-template/pdf-template.js +5 -0
  53. package/dist-server/service/pdf-template/pdf-template.js.map +1 -1
  54. package/dist-server/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +6 -4
  56. package/things-factory.config.js +2 -1
  57. package/translations/en.json +30 -1
  58. package/translations/es.json +30 -1
  59. package/translations/ja.json +30 -1
  60. package/translations/ko.json +30 -1
  61. package/translations/ms.json +30 -1
  62. package/translations/zh.json +30 -1
  63. package/dist-client/pages/pdf-release/pdf-release-importer.d.ts +0 -23
  64. package/dist-client/pages/pdf-release/pdf-release-importer.js +0 -93
  65. package/dist-client/pages/pdf-release/pdf-release-importer.js.map +0 -1
  66. package/dist-client/pages/pdf-release/pdf-release-list-page.d.ts +0 -60
  67. package/dist-client/pages/pdf-release/pdf-release-list-page.js +0 -317
  68. package/dist-client/pages/pdf-release/pdf-release-list-page.js.map +0 -1
  69. package/dist-server/service/pdf-release/pdf-release-mutation.d.ts +0 -10
  70. package/dist-server/service/pdf-release/pdf-release-mutation.js +0 -156
  71. package/dist-server/service/pdf-release/pdf-release-mutation.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ export { downloadIssuedFile, issueDocument, issuedDocumentKindWord, IssueDocumentForm } from './issue-document';
2
+ export type { IssuedDocument } from './issue-document';
@@ -0,0 +1,2 @@
1
+ export { downloadIssuedFile, issueDocument, issuedDocumentKindWord, IssueDocumentForm } from './issue-document';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA","sourcesContent":["export { downloadIssuedFile, issueDocument, issuedDocumentKindWord, IssueDocumentForm } from './issue-document'\nexport type { IssuedDocument } from './issue-document'\n"]}
@@ -0,0 +1,44 @@
1
+ import '@material/web/button/filled-button.js';
2
+ import { LitElement } from 'lit';
3
+ /** A kind as its owning module words it - `issued-document.<kind>` in that module's translations. */
4
+ export declare const issuedDocumentKindWord: (kind?: string | null) => string;
5
+ export type IssuedDocument = {
6
+ id: string;
7
+ number: string;
8
+ file?: {
9
+ fullpath: string;
10
+ name?: string | null;
11
+ } | null;
12
+ };
13
+ /**
14
+ * Save an issued file under its own name - `재직증명서_남종호_재직-2026-0001.pdf` - not the storage path the address
15
+ * carries. The file is fetched with the session and handed to the browser as a download.
16
+ */
17
+ export declare function downloadIssuedFile(file: {
18
+ fullpath: string;
19
+ name?: string | null;
20
+ }): Promise<void>;
21
+ /**
22
+ * Ask for what an issue needs - its purpose and where it goes, and the day it speaks of when the kind has one - then issue
23
+ * it (`issueDocument`, ADR-0176) and open the file. Resolves with the issued row, or null when the person closed it.
24
+ */
25
+ export declare function issueDocument(options: {
26
+ kind: string;
27
+ refId?: string;
28
+ asOf?: string;
29
+ withAsOf?: boolean;
30
+ }): Promise<IssuedDocument | null>;
31
+ declare const IssueDocumentForm_base: (new (...args: any[]) => LitElement) & typeof LitElement;
32
+ export declare class IssueDocumentForm extends IssueDocumentForm_base {
33
+ static styles: import("lit").CSSResult;
34
+ kind: string;
35
+ refId: string;
36
+ asOf: string;
37
+ withAsOf: boolean;
38
+ private purpose;
39
+ private submittedTo;
40
+ private busy;
41
+ render(): import("lit-html").TemplateResult<1>;
42
+ private issue;
43
+ }
44
+ export {};
@@ -0,0 +1,162 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/button/filled-button.js';
3
+ import gql from 'graphql-tag';
4
+ import { css, html, LitElement } from 'lit';
5
+ import { customElement, property, state } from 'lit/decorators.js';
6
+ import { client } from '@operato/graphql';
7
+ import { i18next, localize } from '@operato/i18n';
8
+ import { notify, openPopup } from '@operato/layout';
9
+ /** A kind as its owning module words it - `issued-document.<kind>` in that module's translations. */
10
+ export const issuedDocumentKindWord = (kind) => (kind ? i18next.t(`issued-document.${kind}`, { defaultValue: kind }) : '');
11
+ /**
12
+ * Save an issued file under its own name - `재직증명서_남종호_재직-2026-0001.pdf` - not the storage path the address
13
+ * carries. The file is fetched with the session and handed to the browser as a download.
14
+ */
15
+ export async function downloadIssuedFile(file) {
16
+ const response = await fetch(file.fullpath, { credentials: 'same-origin' });
17
+ if (!response.ok)
18
+ throw new Error(`${response.status} ${response.statusText}`);
19
+ const url = URL.createObjectURL(await response.blob());
20
+ const link = Object.assign(document.createElement('a'), { href: url, download: file.name || file.fullpath.split('/').pop() || 'document.pdf' });
21
+ document.body.appendChild(link);
22
+ link.click();
23
+ link.remove();
24
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
25
+ }
26
+ /**
27
+ * Ask for what an issue needs - its purpose and where it goes, and the day it speaks of when the kind has one - then issue
28
+ * it (`issueDocument`, ADR-0176) and open the file. Resolves with the issued row, or null when the person closed it.
29
+ */
30
+ export function issueDocument(options) {
31
+ return new Promise(resolve => {
32
+ let done = null;
33
+ const popup = openPopup(html `<issue-document-form
34
+ .kind=${options.kind}
35
+ .refId=${options.refId ?? ''}
36
+ .asOf=${options.asOf ?? ''}
37
+ .withAsOf=${!!options.withAsOf}
38
+ @issued=${(e) => ((done = e.detail), popup.close())}
39
+ ></issue-document-form>`, { backdrop: true, size: 'small', title: i18next.t('title.issue-document', { kind: issuedDocumentKindWord(options.kind) }) });
40
+ popup.onclosed = () => resolve(done);
41
+ });
42
+ }
43
+ let IssueDocumentForm = class IssueDocumentForm extends localize(i18next)(LitElement) {
44
+ constructor() {
45
+ super(...arguments);
46
+ this.kind = '';
47
+ this.refId = '';
48
+ this.asOf = '';
49
+ this.withAsOf = false;
50
+ this.purpose = '';
51
+ this.submittedTo = '';
52
+ this.busy = false;
53
+ }
54
+ static { this.styles = css `
55
+ :host {
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: var(--spacing-medium, 8px);
59
+ padding: var(--spacing-large, 12px);
60
+ background-color: var(--md-sys-color-surface);
61
+ }
62
+ label {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: var(--spacing-small, 4px);
66
+ font: var(--label-font);
67
+ color: var(--md-sys-color-on-surface);
68
+ }
69
+ input {
70
+ box-sizing: border-box;
71
+ width: 100%;
72
+ background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));
73
+ color: var(--input-field-color, var(--md-sys-color-on-surface));
74
+ border: var(--border-dim-color);
75
+ border-radius: var(--border-radius);
76
+ padding: var(--input-padding);
77
+ font: var(--input-font);
78
+ }
79
+ div[actions] {
80
+ display: flex;
81
+ justify-content: flex-end;
82
+ }
83
+ `; }
84
+ render() {
85
+ return html `
86
+ ${this.withAsOf
87
+ ? html `<label>${i18next.t('field.issue-as-of')}<input type="date" .value=${this.asOf} @input=${(e) => (this.asOf = e.target.value)} /></label>`
88
+ : ''}
89
+ <label>${i18next.t('field.issued-document-purpose')}<input .value=${this.purpose} @input=${(e) => (this.purpose = e.target.value)} /></label>
90
+ <label>${i18next.t('field.issued-document-submitted-to')}<input .value=${this.submittedTo} @input=${(e) => (this.submittedTo = e.target.value)} /></label>
91
+ <div actions>
92
+ <md-filled-button ?disabled=${this.busy} @click=${() => this.issue()}>${i18next.t('button.issue-document')}</md-filled-button>
93
+ </div>
94
+ `;
95
+ }
96
+ async issue() {
97
+ this.busy = true;
98
+ try {
99
+ const response = await client.mutate({
100
+ mutation: gql `
101
+ mutation ($kind: String!, $refId: String, $input: IssueDocumentInput) {
102
+ issueDocument(kind: $kind, refId: $refId, input: $input) {
103
+ id
104
+ number
105
+ file {
106
+ fullpath
107
+ name
108
+ }
109
+ }
110
+ }
111
+ `,
112
+ variables: { kind: this.kind, refId: this.refId || null, input: { purpose: this.purpose, submittedTo: this.submittedTo, asOf: this.withAsOf ? this.asOf || null : null } }
113
+ });
114
+ if (response.errors?.length)
115
+ throw response.errors[0];
116
+ const issued = response.data.issueDocument;
117
+ notify({ message: i18next.t('text.issued-document-issued', { number: issued.number }) });
118
+ if (issued.file?.fullpath)
119
+ await downloadIssuedFile(issued.file);
120
+ this.dispatchEvent(new CustomEvent('issued', { detail: issued }));
121
+ }
122
+ catch (error) {
123
+ notify({ level: 'error', message: error?.message ?? String(error) });
124
+ }
125
+ finally {
126
+ this.busy = false;
127
+ }
128
+ }
129
+ };
130
+ __decorate([
131
+ property(),
132
+ __metadata("design:type", Object)
133
+ ], IssueDocumentForm.prototype, "kind", void 0);
134
+ __decorate([
135
+ property(),
136
+ __metadata("design:type", Object)
137
+ ], IssueDocumentForm.prototype, "refId", void 0);
138
+ __decorate([
139
+ property(),
140
+ __metadata("design:type", Object)
141
+ ], IssueDocumentForm.prototype, "asOf", void 0);
142
+ __decorate([
143
+ property({ type: Boolean }),
144
+ __metadata("design:type", Object)
145
+ ], IssueDocumentForm.prototype, "withAsOf", void 0);
146
+ __decorate([
147
+ state(),
148
+ __metadata("design:type", Object)
149
+ ], IssueDocumentForm.prototype, "purpose", void 0);
150
+ __decorate([
151
+ state(),
152
+ __metadata("design:type", Object)
153
+ ], IssueDocumentForm.prototype, "submittedTo", void 0);
154
+ __decorate([
155
+ state(),
156
+ __metadata("design:type", Object)
157
+ ], IssueDocumentForm.prototype, "busy", void 0);
158
+ IssueDocumentForm = __decorate([
159
+ customElement('issue-document-form')
160
+ ], IssueDocumentForm);
161
+ export { IssueDocumentForm };
162
+ //# sourceMappingURL=issue-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-document.js","sourceRoot":"","sources":["../client/issue-document.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } 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'\n\n/** A kind as its owning module words it - `issued-document.<kind>` in that module's translations. */\nexport const issuedDocumentKindWord = (kind?: string | null) => (kind ? i18next.t(`issued-document.${kind}`, { defaultValue: kind }) : '')\n\nexport type IssuedDocument = { id: string; number: string; file?: { fullpath: string; name?: string | null } | null }\n\n/**\n * Save an issued file under its own name - `재직증명서_남종호_재직-2026-0001.pdf` - not the storage path the address\n * carries. The file is fetched with the session and handed to the browser as a download.\n */\nexport async function downloadIssuedFile(file: { fullpath: string; name?: string | null }): Promise<void> {\n const response = await fetch(file.fullpath, { credentials: 'same-origin' })\n if (!response.ok) throw new Error(`${response.status} ${response.statusText}`)\n const url = URL.createObjectURL(await response.blob())\n const link = Object.assign(document.createElement('a'), { href: url, download: file.name || file.fullpath.split('/').pop() || 'document.pdf' })\n document.body.appendChild(link)\n link.click()\n link.remove()\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n}\n\n/**\n * Ask for what an issue needs - its purpose and where it goes, and the day it speaks of when the kind has one - then issue\n * it (`issueDocument`, ADR-0176) and open the file. Resolves with the issued row, or null when the person closed it.\n */\nexport function issueDocument(options: { kind: string; refId?: string; asOf?: string; withAsOf?: boolean }): Promise<IssuedDocument | null> {\n return new Promise(resolve => {\n let done: IssuedDocument | null = null\n const popup = openPopup(\n html`<issue-document-form\n .kind=${options.kind}\n .refId=${options.refId ?? ''}\n .asOf=${options.asOf ?? ''}\n .withAsOf=${!!options.withAsOf}\n @issued=${(e: CustomEvent) => ((done = e.detail), popup.close())}\n ></issue-document-form>`,\n { backdrop: true, size: 'small', title: i18next.t('title.issue-document', { kind: issuedDocumentKindWord(options.kind) }) }\n )\n popup.onclosed = () => resolve(done)\n })\n}\n\n@customElement('issue-document-form')\nexport class IssueDocumentForm extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-medium, 8px);\n padding: var(--spacing-large, 12px);\n background-color: var(--md-sys-color-surface);\n }\n label {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n font: var(--label-font);\n color: var(--md-sys-color-on-surface);\n }\n input {\n box-sizing: border-box;\n width: 100%;\n background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));\n color: var(--input-field-color, var(--md-sys-color-on-surface));\n border: var(--border-dim-color);\n border-radius: var(--border-radius);\n padding: var(--input-padding);\n font: var(--input-font);\n }\n div[actions] {\n display: flex;\n justify-content: flex-end;\n }\n `\n\n @property() kind = ''\n @property() refId = ''\n @property() asOf = ''\n @property({ type: Boolean }) withAsOf = false\n @state() private purpose = ''\n @state() private submittedTo = ''\n @state() private busy = false\n\n render() {\n return html`\n ${this.withAsOf\n ? html`<label>${i18next.t('field.issue-as-of')}<input type=\"date\" .value=${this.asOf} @input=${(e: any) => (this.asOf = e.target.value)} /></label>`\n : ''}\n <label>${i18next.t('field.issued-document-purpose')}<input .value=${this.purpose} @input=${(e: any) => (this.purpose = e.target.value)} /></label>\n <label>${i18next.t('field.issued-document-submitted-to')}<input .value=${this.submittedTo} @input=${(e: any) => (this.submittedTo = e.target.value)} /></label>\n <div actions>\n <md-filled-button ?disabled=${this.busy} @click=${() => this.issue()}>${i18next.t('button.issue-document')}</md-filled-button>\n </div>\n `\n }\n\n private async issue() {\n this.busy = true\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($kind: String!, $refId: String, $input: IssueDocumentInput) {\n issueDocument(kind: $kind, refId: $refId, input: $input) {\n id\n number\n file {\n fullpath\n name\n }\n }\n }\n `,\n variables: { kind: this.kind, refId: this.refId || null, input: { purpose: this.purpose, submittedTo: this.submittedTo, asOf: this.withAsOf ? this.asOf || null : null } }\n })\n if (response.errors?.length) throw response.errors[0]\n const issued: IssuedDocument = response.data.issueDocument\n notify({ message: i18next.t('text.issued-document-issued', { number: issued.number }) })\n if (issued.file?.fullpath) await downloadIssuedFile(issued.file)\n this.dispatchEvent(new CustomEvent('issued', { detail: issued }))\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n } finally {\n this.busy = false\n }\n }\n}\n"]}
@@ -0,0 +1,52 @@
1
+ import '@material/web/icon/icon.js';
2
+ import '@operato/data-grist/ox-grist.js';
3
+ import '@operato/input/ox-select.js';
4
+ import '@operato/popup/ox-popup-list.js';
5
+ import { FetchOption } from '@operato/data-grist';
6
+ import { PageView } from '@operato/shell';
7
+ declare const IssuedDocumentList_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
8
+ /**
9
+ * 발급 대장 (ADR-0176 decision 2) - the documents issued, newest first: kind, number, whom or what each is about, what
10
+ * for and to whom, who issued it and when, and whether it was revoked. Each person sees the kinds their own rules let
11
+ * them read (the server asks each kind's module) - an employee their own certificates - and issues here what is about
12
+ * the company or about themselves. A file is saved as it was issued; a mistaken one is revoked with a reason.
13
+ */
14
+ export declare class IssuedDocumentList extends IssuedDocumentList_base {
15
+ /** 내 증명서: one's own - about oneself or issued by oneself - and the documents one issues here. Else the whole ledger. */
16
+ protected mine: boolean;
17
+ static styles: import("lit").CSSResult[];
18
+ private gristConfig;
19
+ private kinds;
20
+ private issuable;
21
+ private kind;
22
+ private selected;
23
+ private reason;
24
+ private busy;
25
+ private grist;
26
+ get context(): {
27
+ title: string;
28
+ actions: {
29
+ title: string;
30
+ icon: string;
31
+ action: () => Promise<void | null>;
32
+ }[];
33
+ search: {
34
+ handler: (search: string) => Promise<void>;
35
+ value: string;
36
+ };
37
+ };
38
+ render(): import("lit-html").TemplateResult<1>;
39
+ pageInitialized(): Promise<void>;
40
+ pageUpdated(changes: any): Promise<void>;
41
+ fetchHandler({ page, limit }: FetchOption): Promise<{
42
+ total: any;
43
+ records: any;
44
+ }>;
45
+ private select;
46
+ private revoke;
47
+ }
48
+ /** 내 정보 › 내 증명서 - the ledger's rows that are one's own, and the documents one issues for oneself. */
49
+ export declare class MyIssuedDocumentList extends IssuedDocumentList {
50
+ protected mine: boolean;
51
+ }
52
+ export {};
@@ -0,0 +1,265 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/icon/icon.js';
3
+ import '@operato/data-grist/ox-grist.js';
4
+ import '@operato/input/ox-select.js';
5
+ import '@operato/popup/ox-popup-list.js';
6
+ import gql from 'graphql-tag';
7
+ import { css, html, nothing } from 'lit';
8
+ import { customElement, query, state } from 'lit/decorators.js';
9
+ import { DataGrist } from '@operato/data-grist';
10
+ import { client } from '@operato/graphql';
11
+ import { i18next, localize } from '@operato/i18n';
12
+ import { notify } from '@operato/layout';
13
+ import { PageView } from '@operato/shell';
14
+ import { CommonGristStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
15
+ import { downloadIssuedFile, issueDocument, issuedDocumentKindWord as kindWord } from '../../issue-document';
16
+ const FIELDS = 'id kind number subjectName purpose submittedTo state revokedAt revokeReason createdAt creator { id name } file { id fullpath name }';
17
+ /**
18
+ * 발급 대장 (ADR-0176 decision 2) - the documents issued, newest first: kind, number, whom or what each is about, what
19
+ * for and to whom, who issued it and when, and whether it was revoked. Each person sees the kinds their own rules let
20
+ * them read (the server asks each kind's module) - an employee their own certificates - and issues here what is about
21
+ * the company or about themselves. A file is saved as it was issued; a mistaken one is revoked with a reason.
22
+ */
23
+ let IssuedDocumentList = class IssuedDocumentList extends localize(i18next)(PageView) {
24
+ constructor() {
25
+ super(...arguments);
26
+ /** 내 증명서: one's own - about oneself or issued by oneself - and the documents one issues here. Else the whole ledger. */
27
+ this.mine = false;
28
+ this.kinds = [];
29
+ this.issuable = [];
30
+ this.kind = '';
31
+ this.selected = null;
32
+ this.reason = '';
33
+ this.busy = false;
34
+ }
35
+ static { this.styles = [
36
+ WorkSurfacePageStyles,
37
+ ScrollbarStyles,
38
+ CommonGristStyles,
39
+ css `
40
+ :host {
41
+ display: flex;
42
+ flex-direction: column;
43
+ }
44
+ ox-grist {
45
+ flex: 1;
46
+ }
47
+ .filters {
48
+ display: flex;
49
+ gap: var(--spacing-medium, 8px);
50
+ align-items: center;
51
+ padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);
52
+ }
53
+ .revoke {
54
+ display: flex;
55
+ flex-wrap: wrap;
56
+ gap: var(--spacing-medium, 8px);
57
+ align-items: center;
58
+ padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);
59
+ border-top: var(--border-dim-color);
60
+ font: var(--label-font);
61
+ }
62
+ .revoke input {
63
+ flex: 1;
64
+ min-width: 200px;
65
+ background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));
66
+ color: var(--input-field-color, var(--md-sys-color-on-surface));
67
+ border: var(--border-dim-color);
68
+ border-radius: var(--border-radius);
69
+ padding: var(--input-padding);
70
+ font: var(--input-font);
71
+ }
72
+ .filters label {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: var(--spacing-medium, 8px);
76
+ font: var(--label-font);
77
+ }
78
+ ox-select {
79
+ min-width: 200px;
80
+ }
81
+ `
82
+ ]; }
83
+ get context() {
84
+ return {
85
+ title: i18next.t(this.mine ? 'title.my-issued-documents' : 'title.issued-document-list'),
86
+ /* Issued in 내 증명서: a document about oneself (one's 재직증명서), and one about the company itself (a 주주명부). */
87
+ actions: (this.mine ? this.issuable : []).map(one => ({
88
+ title: i18next.t('button.issue-kind', { kind: kindWord(one.kind) }),
89
+ icon: 'workspace_premium',
90
+ action: async () => (await issueDocument({ kind: one.kind, refId: one.refId ?? undefined, withAsOf: one.asOf })) && this.grist.fetch()
91
+ })),
92
+ search: { handler: (search) => ((this.grist.searchText = search), this.grist.fetch()), value: this.grist?.searchText }
93
+ };
94
+ }
95
+ render() {
96
+ const row = this.selected;
97
+ return html `
98
+ ${this.kinds.length > 1
99
+ ? html `<div class="filters">
100
+ <label
101
+ >${i18next.t('field.issued-document-kind')}
102
+ <ox-select
103
+ .value=${this.kind}
104
+ @change=${(e) => {
105
+ const next = String(e.detail ?? '');
106
+ if (next !== this.kind)
107
+ (this.kind = next), this.grist.fetch();
108
+ }}
109
+ >
110
+ <span slot="label">${this.kind ? kindWord(this.kind) : i18next.t('text.all')}</span>
111
+ <ox-popup-list align-left nowrap with-search>
112
+ <div option value="">${i18next.t('text.all')}</div>
113
+ ${this.kinds.map(kind => html `<div option value=${kind}>${kindWord(kind)}</div>`)}
114
+ </ox-popup-list>
115
+ </ox-select>
116
+ </label>
117
+ </div>`
118
+ : nothing}
119
+ <ox-grist .mode=${'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} @select-record-change=${(e) => this.select(e.detail?.records)}></ox-grist>
120
+ ${row && row.state === 'published'
121
+ ? html `<div class="revoke">
122
+ ${i18next.t('text.issued-document-revoke', { number: row.number })}
123
+ <input .value=${this.reason} placeholder=${i18next.t('field.issued-document-revoke-reason')} ?disabled=${this.busy} @input=${(e) => (this.reason = e.target.value)} />
124
+ <button danger ?disabled=${this.busy || !this.reason.trim()} @click=${() => this.revoke()}>${i18next.t('button.issued-document-revoke')}</button>
125
+ </div>`
126
+ : nothing}
127
+ `;
128
+ }
129
+ async pageInitialized() {
130
+ this.gristConfig = {
131
+ columns: [
132
+ { type: 'gutter', gutterName: 'sequence' },
133
+ { type: 'gutter', gutterName: 'row-selector', multiple: false },
134
+ {
135
+ type: 'gutter',
136
+ gutterName: 'button',
137
+ icon: 'download',
138
+ title: i18next.t('button.issued-document-open'),
139
+ handlers: {
140
+ click: (_c, _d, _col, record) => record?.file?.fullpath && downloadIssuedFile(record.file).catch((error) => notify({ level: 'error', message: error?.message ?? String(error) }))
141
+ }
142
+ },
143
+ { type: 'string', name: 'number', header: i18next.t('field.issued-document-number'), width: 140 },
144
+ { type: 'string', name: 'kind', header: i18next.t('field.issued-document-kind'), record: { renderer: (value) => kindWord(value) }, width: 140 },
145
+ { type: 'string', name: 'subjectName', header: i18next.t('field.issued-document-subject'), width: 160 },
146
+ { type: 'string', name: 'purpose', header: i18next.t('field.issued-document-purpose'), width: 160 },
147
+ { type: 'string', name: 'submittedTo', header: i18next.t('field.issued-document-submitted-to'), width: 160 },
148
+ { type: 'datetime', name: 'createdAt', header: i18next.t('field.issued-document-issued-at'), width: 160 },
149
+ { type: 'resource-object', name: 'creator', header: i18next.t('field.issued-document-issuer'), width: 110 },
150
+ {
151
+ type: 'string',
152
+ name: 'state',
153
+ header: i18next.t('field.state'),
154
+ record: { renderer: (value, _c, record) => (value === 'revoked' ? `${i18next.t('text.issued-document-revoked')} · ${record.revokeReason ?? ''}` : i18next.t('text.issued-document-published')) },
155
+ width: 200
156
+ }
157
+ ],
158
+ rows: { appendable: false, selectable: { multiple: false } }
159
+ };
160
+ const response = await client.query({ query: gql `query { issuedDocumentKinds { kind asOf issuable refId } }`, fetchPolicy: 'no-cache' });
161
+ const kinds = response.data?.issuedDocumentKinds ?? [];
162
+ this.kinds = kinds.map((one) => one.kind);
163
+ this.issuable = kinds.filter((one) => one.issuable);
164
+ this.updateContext();
165
+ }
166
+ async pageUpdated(changes) {
167
+ if (this.active && changes.active && this.grist)
168
+ this.grist.fetch();
169
+ }
170
+ async fetchHandler({ page = 1, limit = 100 }) {
171
+ const filters = [];
172
+ if (this.kind)
173
+ filters.push({ name: 'kind', operator: 'eq', value: this.kind });
174
+ if (this.grist?.searchText)
175
+ filters.push({ name: 'q', operator: 'search', value: this.grist.searchText });
176
+ const response = await client.query({
177
+ query: gql(this.mine
178
+ ? `query ($filters: [Filter!], $pagination: Pagination) { list: readableIssuedDocuments(filters: $filters, pagination: $pagination, mine: true) { items { ${FIELDS} } total } }`
179
+ : `query ($filters: [Filter!], $pagination: Pagination) { list: issuedDocuments(filters: $filters, pagination: $pagination) { items { ${FIELDS} } total } }`),
180
+ variables: { filters, pagination: { page, limit } },
181
+ fetchPolicy: 'no-cache'
182
+ });
183
+ this.select([]);
184
+ return { total: response.data?.list?.total ?? 0, records: response.data?.list?.items ?? [] };
185
+ }
186
+ select(records) {
187
+ const row = records?.[0] ?? null;
188
+ if (row?.id !== this.selected?.id)
189
+ this.reason = '';
190
+ this.selected = row;
191
+ }
192
+ async revoke() {
193
+ this.busy = true;
194
+ try {
195
+ const response = await client.mutate({
196
+ mutation: gql `
197
+ mutation ($id: String!, $reason: String!) {
198
+ revokeIssuedDocument(id: $id, reason: $reason) {
199
+ id
200
+ }
201
+ }
202
+ `,
203
+ variables: { id: this.selected.id, reason: this.reason }
204
+ });
205
+ if (response.errors?.length)
206
+ throw response.errors[0];
207
+ notify({ message: i18next.t('text.issued-document-revoked-done', { number: this.selected.number }) });
208
+ this.grist.fetch();
209
+ }
210
+ catch (error) {
211
+ notify({ level: 'error', message: error?.message ?? String(error) });
212
+ }
213
+ finally {
214
+ this.busy = false;
215
+ }
216
+ }
217
+ };
218
+ __decorate([
219
+ state(),
220
+ __metadata("design:type", Object)
221
+ ], IssuedDocumentList.prototype, "gristConfig", void 0);
222
+ __decorate([
223
+ state(),
224
+ __metadata("design:type", Array)
225
+ ], IssuedDocumentList.prototype, "kinds", void 0);
226
+ __decorate([
227
+ state(),
228
+ __metadata("design:type", Array)
229
+ ], IssuedDocumentList.prototype, "issuable", void 0);
230
+ __decorate([
231
+ state(),
232
+ __metadata("design:type", Object)
233
+ ], IssuedDocumentList.prototype, "kind", void 0);
234
+ __decorate([
235
+ state(),
236
+ __metadata("design:type", Object)
237
+ ], IssuedDocumentList.prototype, "selected", void 0);
238
+ __decorate([
239
+ state(),
240
+ __metadata("design:type", Object)
241
+ ], IssuedDocumentList.prototype, "reason", void 0);
242
+ __decorate([
243
+ state(),
244
+ __metadata("design:type", Object)
245
+ ], IssuedDocumentList.prototype, "busy", void 0);
246
+ __decorate([
247
+ query('ox-grist'),
248
+ __metadata("design:type", DataGrist)
249
+ ], IssuedDocumentList.prototype, "grist", void 0);
250
+ IssuedDocumentList = __decorate([
251
+ customElement('issued-document-list')
252
+ ], IssuedDocumentList);
253
+ export { IssuedDocumentList };
254
+ /** 내 정보 › 내 증명서 - the ledger's rows that are one's own, and the documents one issues for oneself. */
255
+ let MyIssuedDocumentList = class MyIssuedDocumentList extends IssuedDocumentList {
256
+ constructor() {
257
+ super(...arguments);
258
+ this.mine = true;
259
+ }
260
+ };
261
+ MyIssuedDocumentList = __decorate([
262
+ customElement('my-issued-document-list')
263
+ ], MyIssuedDocumentList);
264
+ export { MyIssuedDocumentList };
265
+ //# sourceMappingURL=issued-document-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issued-document-list.js","sourceRoot":"","sources":["../../../client/pages/issued-document/issued-document-list.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,iCAAiC,CAAA;AACxC,OAAO,6BAA6B,CAAA;AACpC,OAAO,iCAAiC,CAAA;AAExC,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE3F,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB,IAAI,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE5G,MAAM,MAAM,GAAG,qIAAqI,CAAA;AAEpJ;;;;;GAKG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAA5D;;QACL,wHAAwH;QAC9G,SAAI,GAAG,KAAK,CAAA;QAoDL,UAAK,GAAa,EAAE,CAAA;QACpB,aAAQ,GAA6D,EAAE,CAAA;QACvE,SAAI,GAAG,EAAE,CAAA;QACT,aAAQ,GAAQ,IAAI,CAAA;QACpB,WAAM,GAAG,EAAE,CAAA;QACX,SAAI,GAAG,KAAK,CAAA;IA2I/B,CAAC;aAlMQ,WAAM,GAAG;QACd,qBAAqB;QACrB,eAAe;QACf,iBAAiB;QACjB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0CF;KACF,AA/CY,CA+CZ;IAYD,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,4BAA4B,CAAC;YACxF,yGAAyG;YACzG,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpD,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnE,IAAI,EAAE,mBAAmB;gBACzB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;aACvI,CAAC,CAAC;YACH,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE;SAC/H,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAA;QACzB,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAA;;iBAEG,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;yBAE/B,IAAI,CAAC,IAAI;0BACR,CAAC,CAAc,EAAE,EAAE;gBAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;gBACnC,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI;oBAAE,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YAChE,CAAC;;qCAEoB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;;yCAEnD,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;oBAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA,qBAAqB,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;;;;iBAIlF;YACT,CAAC,CAAC,OAAO;wBACO,MAAM,YAAY,IAAI,CAAC,WAAW,kBAAkB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC;QACpK,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,WAAW;YAChC,CAAC,CAAC,IAAI,CAAA;cACA,OAAO,CAAC,CAAC,CAAC,6BAA6B,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;4BAClD,IAAI,CAAC,MAAM,gBAAgB,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAC,cAAc,IAAI,CAAC,IAAI,WAAW,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;uCAC5I,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;iBAClI;YACT,CAAC,CAAC,OAAO;KACZ,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,WAAW,GAAG;YACjB,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE;gBAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC/D;oBACE,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,QAAQ;oBACpB,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;oBAC/C,QAAQ,EAAE;wBACR,KAAK,EAAE,CAAC,EAAO,EAAE,EAAO,EAAE,IAAS,EAAE,MAAW,EAAE,EAAE,CAClD,MAAM,EAAE,IAAI,EAAE,QAAQ,IAAI,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;qBACxJ;iBACF;gBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBACjG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;gBACvJ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBACvG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBACnG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,oCAAoC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC5G,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBACzG,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC3G;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;oBAChC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAO,EAAE,MAAW,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,MAAM,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,EAAE;oBAClN,KAAK,EAAE,GAAG;iBACX;aACF;YACD,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;SAC7D,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAA,4DAA4D,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAA;QACxI,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,mBAAmB,IAAI,EAAE,CAAA;QACtD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC9C,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACxD,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAY;QAC5B,IAAK,IAAY,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IAC9E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,EAAe;QACvD,MAAM,OAAO,GAAU,EAAE,CAAA;QACzB,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QAC/E,IAAI,IAAI,CAAC,KAAK,EAAE,UAAU;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAA;QACzG,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CACR,IAAI,CAAC,IAAI;gBACP,CAAC,CAAC,0JAA0J,MAAM,cAAc;gBAChL,CAAC,CAAC,sIAAsI,MAAM,cAAc,CAC/J;YACD,SAAS,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;YACnD,WAAW,EAAE,UAAU;SACxB,CAAC,CAAA;QACF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACf,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE,CAAA;IAC9F,CAAC;IAEO,MAAM,CAAC,OAA0B;QACvC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAA;QAChC,IAAI,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,QAAQ,EAAE,EAAE;YAAE,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QACnD,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAA;IACrB,CAAC;IAEO,KAAK,CAAC,MAAM;QAClB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;SAMZ;gBACD,SAAS,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;aACzD,CAAC,CAAA;YACF,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACrD,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;YACrG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACtE,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,IAAI,GAAG,KAAK,CAAA;QACnB,CAAC;IACH,CAAC;;AAhJgB;IAAhB,KAAK,EAAE;;uDAAyB;AAChB;IAAhB,KAAK,EAAE;;iDAA6B;AACpB;IAAhB,KAAK,EAAE;;oDAAgF;AACvE;IAAhB,KAAK,EAAE;;gDAAkB;AACT;IAAhB,KAAK,EAAE;;oDAA6B;AACpB;IAAhB,KAAK,EAAE;;kDAAoB;AACX;IAAhB,KAAK,EAAE;;gDAAqB;AAEF;IAA1B,KAAK,CAAC,UAAU,CAAC;8BAAiB,SAAS;iDAAA;AA7DjC,kBAAkB;IAD9B,aAAa,CAAC,sBAAsB,CAAC;GACzB,kBAAkB,CAsM9B;;AAED,qGAAqG;AAE9F,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,kBAAkB;IAArD;;QACK,SAAI,GAAG,IAAI,CAAA;IACvB,CAAC;CAAA,CAAA;AAFY,oBAAoB;IADhC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,oBAAoB,CAEhC","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/data-grist/ox-grist.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\n\nimport { downloadIssuedFile, issueDocument, issuedDocumentKindWord as kindWord } from '../../issue-document'\n\nconst FIELDS = 'id kind number subjectName purpose submittedTo state revokedAt revokeReason createdAt creator { id name } file { id fullpath name }'\n\n/**\n * 발급 대장 (ADR-0176 decision 2) - the documents issued, newest first: kind, number, whom or what each is about, what\n * for and to whom, who issued it and when, and whether it was revoked. Each person sees the kinds their own rules let\n * them read (the server asks each kind's module) - an employee their own certificates - and issues here what is about\n * the company or about themselves. A file is saved as it was issued; a mistaken one is revoked with a reason.\n */\n@customElement('issued-document-list')\nexport class IssuedDocumentList extends localize(i18next)(PageView) {\n /** 내 증명서: one's own - about oneself or issued by oneself - and the documents one issues here. Else the whole ledger. */\n protected mine = false\n\n static styles = [\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n }\n ox-grist {\n flex: 1;\n }\n .filters {\n display: flex;\n gap: var(--spacing-medium, 8px);\n align-items: center;\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n }\n .revoke {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-medium, 8px);\n align-items: center;\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-top: var(--border-dim-color);\n font: var(--label-font);\n }\n .revoke input {\n flex: 1;\n min-width: 200px;\n background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));\n color: var(--input-field-color, var(--md-sys-color-on-surface));\n border: var(--border-dim-color);\n border-radius: var(--border-radius);\n padding: var(--input-padding);\n font: var(--input-font);\n }\n .filters label {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n font: var(--label-font);\n }\n ox-select {\n min-width: 200px;\n }\n `\n ]\n\n @state() private gristConfig: any\n @state() private kinds: string[] = []\n @state() private issuable: { kind: string; asOf: boolean; refId?: string | null }[] = []\n @state() private kind = ''\n @state() private selected: any = null\n @state() private reason = ''\n @state() private busy = false\n\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t(this.mine ? 'title.my-issued-documents' : 'title.issued-document-list'),\n /* Issued in 내 증명서: a document about oneself (one's 재직증명서), and one about the company itself (a 주주명부). */\n actions: (this.mine ? this.issuable : []).map(one => ({\n title: i18next.t('button.issue-kind', { kind: kindWord(one.kind) }),\n icon: 'workspace_premium',\n action: async () => (await issueDocument({ kind: one.kind, refId: one.refId ?? undefined, withAsOf: one.asOf })) && this.grist.fetch()\n })),\n search: { handler: (search: string) => ((this.grist.searchText = search), this.grist.fetch()), value: this.grist?.searchText }\n }\n }\n\n render() {\n const row = this.selected\n return html`\n ${this.kinds.length > 1\n ? html`<div class=\"filters\">\n <label\n >${i18next.t('field.issued-document-kind')}\n <ox-select\n .value=${this.kind}\n @change=${(e: CustomEvent) => {\n const next = String(e.detail ?? '')\n if (next !== this.kind) (this.kind = next), this.grist.fetch()\n }}\n >\n <span slot=\"label\">${this.kind ? kindWord(this.kind) : i18next.t('text.all')}</span>\n <ox-popup-list align-left nowrap with-search>\n <div option value=\"\">${i18next.t('text.all')}</div>\n ${this.kinds.map(kind => html`<div option value=${kind}>${kindWord(kind)}</div>`)}\n </ox-popup-list>\n </ox-select>\n </label>\n </div>`\n : nothing}\n <ox-grist .mode=${'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} @select-record-change=${(e: any) => this.select(e.detail?.records)}></ox-grist>\n ${row && row.state === 'published'\n ? html`<div class=\"revoke\">\n ${i18next.t('text.issued-document-revoke', { number: row.number })}\n <input .value=${this.reason} placeholder=${i18next.t('field.issued-document-revoke-reason')} ?disabled=${this.busy} @input=${(e: any) => (this.reason = e.target.value)} />\n <button danger ?disabled=${this.busy || !this.reason.trim()} @click=${() => this.revoke()}>${i18next.t('button.issued-document-revoke')}</button>\n </div>`\n : nothing}\n `\n }\n\n async pageInitialized() {\n this.gristConfig = {\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: false },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'download',\n title: i18next.t('button.issued-document-open'),\n handlers: {\n click: (_c: any, _d: any, _col: any, record: any) =>\n record?.file?.fullpath && downloadIssuedFile(record.file).catch((error: any) => notify({ level: 'error', message: error?.message ?? String(error) }))\n }\n },\n { type: 'string', name: 'number', header: i18next.t('field.issued-document-number'), width: 140 },\n { type: 'string', name: 'kind', header: i18next.t('field.issued-document-kind'), record: { renderer: (value: string) => kindWord(value) }, width: 140 },\n { type: 'string', name: 'subjectName', header: i18next.t('field.issued-document-subject'), width: 160 },\n { type: 'string', name: 'purpose', header: i18next.t('field.issued-document-purpose'), width: 160 },\n { type: 'string', name: 'submittedTo', header: i18next.t('field.issued-document-submitted-to'), width: 160 },\n { type: 'datetime', name: 'createdAt', header: i18next.t('field.issued-document-issued-at'), width: 160 },\n { type: 'resource-object', name: 'creator', header: i18next.t('field.issued-document-issuer'), width: 110 },\n {\n type: 'string',\n name: 'state',\n header: i18next.t('field.state'),\n record: { renderer: (value: string, _c: any, record: any) => (value === 'revoked' ? `${i18next.t('text.issued-document-revoked')} · ${record.revokeReason ?? ''}` : i18next.t('text.issued-document-published')) },\n width: 200\n }\n ],\n rows: { appendable: false, selectable: { multiple: false } }\n }\n const response = await client.query({ query: gql`query { issuedDocumentKinds { kind asOf issuable refId } }`, fetchPolicy: 'no-cache' })\n const kinds = response.data?.issuedDocumentKinds ?? []\n this.kinds = kinds.map((one: any) => one.kind)\n this.issuable = kinds.filter((one: any) => one.issuable)\n this.updateContext()\n }\n\n async pageUpdated(changes: any) {\n if ((this as any).active && changes.active && this.grist) this.grist.fetch()\n }\n\n async fetchHandler({ page = 1, limit = 100 }: FetchOption) {\n const filters: any[] = []\n if (this.kind) filters.push({ name: 'kind', operator: 'eq', value: this.kind })\n if (this.grist?.searchText) filters.push({ name: 'q', operator: 'search', value: this.grist.searchText })\n const response = await client.query({\n query: gql(\n this.mine\n ? `query ($filters: [Filter!], $pagination: Pagination) { list: readableIssuedDocuments(filters: $filters, pagination: $pagination, mine: true) { items { ${FIELDS} } total } }`\n : `query ($filters: [Filter!], $pagination: Pagination) { list: issuedDocuments(filters: $filters, pagination: $pagination) { items { ${FIELDS} } total } }`\n ),\n variables: { filters, pagination: { page, limit } },\n fetchPolicy: 'no-cache'\n })\n this.select([])\n return { total: response.data?.list?.total ?? 0, records: response.data?.list?.items ?? [] }\n }\n\n private select(records: any[] | undefined) {\n const row = records?.[0] ?? null\n if (row?.id !== this.selected?.id) this.reason = ''\n this.selected = row\n }\n\n private async revoke() {\n this.busy = true\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $reason: String!) {\n revokeIssuedDocument(id: $id, reason: $reason) {\n id\n }\n }\n `,\n variables: { id: this.selected.id, reason: this.reason }\n })\n if (response.errors?.length) throw response.errors[0]\n notify({ message: i18next.t('text.issued-document-revoked-done', { number: this.selected.number }) })\n this.grist.fetch()\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n } finally {\n this.busy = false\n }\n }\n}\n\n/** 내 정보 › 내 증명서 - the ledger's rows that are one's own, and the documents one issues for oneself. */\n@customElement('my-issued-document-list')\nexport class MyIssuedDocumentList extends IssuedDocumentList {\n protected mine = true\n}\n"]}
@@ -94,6 +94,7 @@ let PDFTemplateListPage = class PDFTemplateListPage extends localize(i18next)(Sc
94
94
  `;
95
95
  }
96
96
  async pageInitialized(lifecycle) {
97
+ const kinds = ((await client.query({ query: gql `query { issuedDocumentKinds { kind } }` })).data?.issuedDocumentKinds ?? []).map((one) => one.kind);
97
98
  this.gristConfig = { list: { fields: ['name', 'description'],
98
99
  details: ['active', 'updatedAt']
99
100
  },
@@ -129,6 +130,16 @@ let PDFTemplateListPage = class PDFTemplateListPage extends localize(i18next)(Sc
129
130
  sortable: true,
130
131
  width: 60
131
132
  },
133
+ /* The issued document kind this template prints for the domain, in place of the kind's template in code (ADR-0176). */
134
+ { type: 'select',
135
+ name: 'kind',
136
+ label: true,
137
+ header: i18next.t('field.issued-document-kind'),
138
+ record: { editable: true,
139
+ options: ['', ...kinds],
140
+ renderer: (value) => (value ? i18next.t(`issued-document.${value}`, { defaultValue: value }) : '')
141
+ },
142
+ width: 160 },
132
143
  { type: 'string',
133
144
  name: 'state',
134
145
  label: true,
@@ -241,6 +252,7 @@ let PDFTemplateListPage = class PDFTemplateListPage extends localize(i18next)(Sc
241
252
  description
242
253
  active
243
254
  state
255
+ kind
244
256
  content_template
245
257
  header_template
246
258
  footer_template