@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.
- package/dist-client/components/compliance-case-form.d.ts +11 -6
- package/dist-client/components/compliance-case-form.js +67 -88
- package/dist-client/components/compliance-case-form.js.map +1 -1
- package/dist-client/components/compliance-case-sheet.d.ts +14 -12
- package/dist-client/components/compliance-case-sheet.js +92 -133
- package/dist-client/components/compliance-case-sheet.js.map +1 -1
- package/dist-client/components/compliance-my-inventions.d.ts +3 -4
- package/dist-client/components/compliance-my-inventions.js +10 -30
- package/dist-client/components/compliance-my-inventions.js.map +1 -1
- package/dist-client/components/compliance-my-privacy-requests.d.ts +6 -6
- package/dist-client/components/compliance-my-privacy-requests.js +30 -66
- package/dist-client/components/compliance-my-privacy-requests.js.map +1 -1
- package/dist-client/components/compliance-my-reports.d.ts +3 -4
- package/dist-client/components/compliance-my-reports.js +19 -40
- package/dist-client/components/compliance-my-reports.js.map +1 -1
- package/dist-client/components/invention-report-form.d.ts +5 -4
- package/dist-client/components/invention-report-form.js +24 -45
- package/dist-client/components/invention-report-form.js.map +1 -1
- package/dist-client/components/my-trainings.d.ts +3 -5
- package/dist-client/components/my-trainings.js +20 -49
- package/dist-client/components/my-trainings.js.map +1 -1
- package/dist-client/components/seal-use-form.d.ts +9 -6
- package/dist-client/components/seal-use-form.js +60 -81
- package/dist-client/components/seal-use-form.js.map +1 -1
- package/dist-client/components/training-attendance-form.d.ts +6 -4
- package/dist-client/components/training-attendance-form.js +30 -50
- package/dist-client/components/training-attendance-form.js.map +1 -1
- package/dist-client/pages/regulation-detail.d.ts +15 -6
- package/dist-client/pages/regulation-detail.js +169 -142
- package/dist-client/pages/regulation-detail.js.map +1 -1
- package/dist-client/pages/regulations.d.ts +7 -5
- package/dist-client/pages/regulations.js +38 -56
- package/dist-client/pages/regulations.js.map +1 -1
- package/dist-client/regulation/regulation-guide.js +2 -1
- package/dist-client/regulation/regulation-guide.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/words.js +2 -2
- package/dist-client/words.js.map +1 -1
- package/dist-server/service/compliance-case/compliance-case-query.js +1 -1
- package/dist-server/service/compliance-case/compliance-case-query.js.map +1 -1
- package/dist-server/service/compliance-case/compliance-case-rules.d.ts +1 -3
- package/dist-server/service/compliance-case/compliance-case-rules.js +2 -4
- package/dist-server/service/compliance-case/compliance-case-rules.js.map +1 -1
- package/dist-server/service/compliance-case/compliance-case-service.d.ts +3 -3
- package/dist-server/service/compliance-case/compliance-case-service.js +4 -6
- package/dist-server/service/compliance-case/compliance-case-service.js.map +1 -1
- package/dist-server/service/compliance-case/compliance-case-type.js +1 -1
- package/dist-server/service/compliance-case/compliance-case-type.js.map +1 -1
- package/dist-server/service/compliance-case/compliance-case.js +1 -1
- package/dist-server/service/compliance-case/compliance-case.js.map +1 -1
- package/dist-server/service/regulation/regulation-rules.d.ts +3 -3
- package/dist-server/service/regulation/regulation-rules.js +17 -17
- package/dist-server/service/regulation/regulation-rules.js.map +1 -1
- package/dist-server/service/regulation/regulation.d.ts +1 -1
- package/dist-server/service/regulation/regulation.js +1 -1
- package/dist-server/service/regulation/regulation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/translations/en.json +27 -14
- package/translations/es.json +27 -14
- package/translations/ja.json +27 -14
- package/translations/ko.json +27 -14
- package/translations/ms.json +27 -14
- package/translations/zh.json +27 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"training-attendance-form.js","sourceRoot":"","sources":["../../client/components/training-attendance-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/icon/icon.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 } 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 } from '../words.js'\n\ntype Choice = { value: string; display: string }\n\n/** Opens the form for a session; resolves true when the attendance was recorded. */\nexport function openTrainingAttendanceForm(session: { id: string; name: string; startsOn: string; endsOn?: string | null }): Promise<boolean> {\n return new Promise(resolve => {\n let done = false\n const handle: any = openPopup(\n html`<training-attendance-form .session=${session} @close=${() => handle.close()} @recorded=${() => ((done = true), handle.close())}></training-attendance-form>`,\n { backdrop: true, size: 'medium', title: i18next.t('title.training-attendance', { name: session.name }) }\n )\n handle.onclosed = () => resolve(done)\n })\n}\n\n/**\n * 출석 기록 (ADR-0187 decision 17) - the people who attended a session, recorded at once as completed. Someone done\n * already for the kind and year is left as they are.\n */\n@customElement('training-attendance-form')\nexport class TrainingAttendanceForm extends localize(i18next)(LitElement) {\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-select {\n width: 100%;\n }\n .chosen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n }\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 4px 2px 8px;\n border-radius: 999px;\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n .chip button {\n border: 0;\n background: none;\n cursor: pointer;\n color: inherit;\n display: inline-flex;\n padding: 0;\n }\n .chip md-icon {\n --md-icon-size: 16px;\n }\n `\n ]\n\n @property({ type: Object }) session!: { id: string; name: string; startsOn: string; endsOn?: string | null }\n\n @state() private people: Choice[] = []\n @state() private chosen: string[] = []\n @state() private completedOn = ''\n @state() private working = false\n @state() private message = ''\n\n async connectedCallback() {\n super.connectedCallback()\n this.completedOn = this.session.endsOn || this.session.startsOn\n const response = await client.query({\n query: gql`\n query {\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 this.people = (response.data?.employees?.items ?? []).map((one: any) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }))\n }\n\n render() {\n const left = this.people.filter(one => !this.chosen.includes(one.value))\n return html`\n <div class=\"body\">\n <div guide><p>${i18next.t('text.training-attendance-guide')}</p></div>\n\n <label class=\"field\">\n <span>${i18next.t('field.training-completed-on')}</span>\n <input type=\"date\" .value=${this.completedOn} min=${this.session.startsOn} @input=${(e: any) => (this.completedOn = e.target.value)} />\n </label>\n\n <div class=\"field\">\n <span>${i18next.t('field.training-attendees')} (${this.chosen.length})</span>\n <div class=\"chosen\">\n ${this.chosen.map(\n id => html`<span class=\"chip\"\n >${this.people.find(one => one.value === id)?.display ?? id}\n <button aria-label=${i18next.t('button.delete')} @click=${() => (this.chosen = this.chosen.filter(one => one !== id))}><md-icon>close</md-icon></button></span\n >`\n )}\n </div>\n <ox-select value=\"\" @change=${(e: CustomEvent) => e.detail && (this.chosen = [...this.chosen, String(e.detail)])}>\n <span slot=\"label\">${i18next.t('text.training-attendee-add')}</span>\n <ox-popup-list align-left nowrap with-search>${left.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>\n <span invalid>${this.message}</span>\n </div>\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.training-attendance-record')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private async record() {\n this.message = ''\n this.working = true\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($sessionId: String!, $employeeIds: [String!]!, $completedOn: String) {\n recordTrainingAttendance(sessionId: $sessionId, employeeIds: $employeeIds, completedOn: $completedOn) { id }\n }\n `,\n variables: { sessionId: this.session.id, employeeIds: this.chosen, completedOn: this.completedOn || null }\n })\n if ((response as any).errors?.length) throw response\n notify({ message: i18next.t('text.training-attendance-recorded', { count: response.data.recordTrainingAttendance.length }) })\n this.dispatchEvent(new CustomEvent('recorded'))\n } catch (error) {\n this.message = failureOf(error)\n } finally {\n this.working = false\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"training-attendance-form.js","sourceRoot":"","sources":["../../client/components/training-attendance-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/icon/icon.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 } 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 } from '../words.js'\n\ntype Choice = { value: string; display: string }\n\n/** Opens the form for a session; resolves true when the attendance was recorded. */\nexport function openTrainingAttendanceForm(session: { id: string; name: string; startsOn: string; endsOn?: string | null }): Promise<boolean> {\n return new Promise(resolve => {\n let done = false\n const handle: any = openPopup(\n html`<training-attendance-form .session=${session} @close=${() => handle.close()} @recorded=${() => ((done = true), handle.close())}></training-attendance-form>`,\n { backdrop: true, size: 'medium', title: i18next.t('title.training-attendance', { name: session.name }) }\n )\n handle.onclosed = () => resolve(done)\n })\n}\n\n/**\n * 출석 기록 (ADR-0187 decision 17) - the people who attended a session, recorded at once as completed. Someone done\n * already for the kind and year is left as they are.\n */\n@customElement('training-attendance-form')\nexport class TrainingAttendanceForm extends localize(i18next)(LitElement) {\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-select {\n width: 100%;\n }\n .chosen {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n }\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 4px 2px 8px;\n border-radius: 999px;\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n .chip button {\n border: 0;\n background: none;\n cursor: pointer;\n color: inherit;\n display: inline-flex;\n padding: 0;\n }\n .chip md-icon {\n --md-icon-size: 16px;\n }\n `\n ]\n\n @property({ type: Object }) session!: { id: string; name: string; startsOn: string; endsOn?: string | null }\n\n @state() private chosen: string[] = []\n @state() private completedOn = ''\n\n /* The employees who may have attended (ADR-0190). */\n private employees = new QueryController(\n this,\n gql`\n query {\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 attendees, beside the form. */\n private recording = new MutationController(\n this,\n gql`\n mutation ($sessionId: String!, $employeeIds: [String!]!, $completedOn: String) {\n recordTrainingAttendance(sessionId: $sessionId, employeeIds: $employeeIds, completedOn: $completedOn) { id }\n }\n `,\n { showsError: true }\n )\n\n connectedCallback() {\n super.connectedCallback()\n this.completedOn = this.session.endsOn || this.session.startsOn\n }\n\n private get people(): Choice[] {\n return (this.employees.data?.employees?.items ?? []).map((one: any) => ({ value: one.id, display: one.controlNo ? `${one.name} · ${one.controlNo}` : one.name }))\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 left = this.people.filter(one => !this.chosen.includes(one.value))\n return html`\n <div class=\"body\">\n <div guide><p>${i18next.t('text.training-attendance-guide')}</p></div>\n\n <label class=\"field\">\n <span>${i18next.t('field.training-completed-on')}</span>\n <input type=\"date\" .value=${this.completedOn} min=${this.session.startsOn} @input=${(e: any) => (this.completedOn = e.target.value)} />\n </label>\n\n <div class=\"field\">\n <span>${i18next.t('field.training-attendees')} (${this.chosen.length})</span>\n <div class=\"chosen\">\n ${this.chosen.map(\n id => html`<span class=\"chip\"\n >${this.people.find(one => one.value === id)?.display ?? id}\n <button aria-label=${i18next.t('button.delete')} @click=${() => (this.chosen = this.chosen.filter(one => one !== id))}><md-icon>close</md-icon></button></span\n >`\n )}\n </div>\n <ox-select value=\"\" @change=${(e: CustomEvent) => e.detail && (this.chosen = [...this.chosen, String(e.detail)])}>\n <span slot=\"label\">${i18next.t('text.training-attendee-add')}</span>\n <ox-popup-list align-left nowrap with-search>${left.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>\n <span invalid>${this.message}</span>\n </div>\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.training-attendance-record')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private async record() {\n const done = await this.recording.run({ sessionId: this.session.id, employeeIds: this.chosen, completedOn: this.completedOn || null })\n if (!done) return\n notify({ message: i18next.t('text.training-attendance-recorded', { count: done.recordTrainingAttendance.length }) })\n this.dispatchEvent(new CustomEvent('recorded'))\n }\n}\n"]}
|
|
@@ -11,14 +11,17 @@ declare const RegulationDetail_base: (new (...args: any[]) => import("lit").LitE
|
|
|
11
11
|
*/
|
|
12
12
|
export declare class RegulationDetail extends RegulationDetail_base {
|
|
13
13
|
static styles: import("lit").CSSResult[];
|
|
14
|
-
private
|
|
15
|
-
private failure;
|
|
14
|
+
private ruleId;
|
|
16
15
|
private chosen;
|
|
17
|
-
private draft;
|
|
18
|
-
private employees;
|
|
19
|
-
private procedure;
|
|
20
16
|
private files;
|
|
21
17
|
private originals;
|
|
18
|
+
private rule;
|
|
19
|
+
private draft;
|
|
20
|
+
private procedure;
|
|
21
|
+
private saves;
|
|
22
|
+
private change;
|
|
23
|
+
private get view();
|
|
24
|
+
private get busy();
|
|
22
25
|
get context(): {
|
|
23
26
|
title: any;
|
|
24
27
|
frame: string;
|
|
@@ -30,15 +33,21 @@ export declare class RegulationDetail extends RegulationDetail_base {
|
|
|
30
33
|
private renderInForce;
|
|
31
34
|
private renderProcedureForm;
|
|
32
35
|
pageUpdated(changes: any, lifecycle: any): Promise<void>;
|
|
33
|
-
private fetch;
|
|
34
36
|
private choose;
|
|
37
|
+
get addressDirty(): boolean;
|
|
38
|
+
get addressDiscardText(): string;
|
|
39
|
+
discardAddressEdits(change?: any): void;
|
|
40
|
+
private mayLeave;
|
|
41
|
+
private switchTo;
|
|
35
42
|
private call;
|
|
36
43
|
private patchOf;
|
|
44
|
+
private saveDraft;
|
|
37
45
|
private saveVersion;
|
|
38
46
|
private submit;
|
|
39
47
|
private registerInForce;
|
|
40
48
|
private withdraw;
|
|
41
49
|
private newVersion;
|
|
50
|
+
/** The revision asked about is the one deleted: if the screen shows another once confirmed, nothing is deleted. */
|
|
42
51
|
private deleteVersion;
|
|
43
52
|
private recordProcedure;
|
|
44
53
|
private deleteProcedure;
|
|
@@ -5,14 +5,14 @@ import '@operato/list-state/ox-page-state.js';
|
|
|
5
5
|
import gql from 'graphql-tag';
|
|
6
6
|
import { css, html, nothing } from 'lit';
|
|
7
7
|
import { customElement, state } from 'lit/decorators.js';
|
|
8
|
-
import {
|
|
8
|
+
import { MutationController, QueryController, uploadContext } from '@operato/graphql';
|
|
9
9
|
import { i18next, localize } from '@operato/i18n';
|
|
10
10
|
import { notify } from '@operato/layout';
|
|
11
11
|
import { OxPrompt } from '@operato/popup/ox-prompt.js';
|
|
12
|
-
import { navigate, PageView } from '@operato/shell';
|
|
12
|
+
import { navigate, PageView, DraftController } from '@operato/shell';
|
|
13
13
|
import { CommonButtonStyles, DocumentPageStyles, FormFieldStyles, ScrollbarStyles } from '@operato/styles';
|
|
14
14
|
import { VERSION_VIEW } from '../regulation/regulation-fragments.js';
|
|
15
|
-
import { failureOf,
|
|
15
|
+
import { failureOf, PROCEDURE_METHODS, wordOf } from '../words.js';
|
|
16
16
|
/**
|
|
17
17
|
* 규정 한 건 (ADR-0187 decisions 2-6) - its versions, and of the one chosen: its text, the day it takes effect, what
|
|
18
18
|
* changed, whether it is against the workers, the procedure with its papers, its approval and whether the employees were
|
|
@@ -22,14 +22,47 @@ import { failureOf, PROCEDURE_KINDS, PROCEDURE_METHODS, wordOf } from '../words.
|
|
|
22
22
|
let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView) {
|
|
23
23
|
constructor() {
|
|
24
24
|
super(...arguments);
|
|
25
|
-
this.
|
|
26
|
-
this.failure = '';
|
|
25
|
+
this.ruleId = '';
|
|
27
26
|
this.chosen = '';
|
|
28
|
-
this.draft = {};
|
|
29
|
-
this.employees = null;
|
|
30
|
-
this.procedure = { kind: 'OPINION', day: '', method: '', workersCount: '', consentCount: '', notes: '' };
|
|
31
27
|
this.files = [];
|
|
32
28
|
this.originals = [];
|
|
29
|
+
/* The rule and its versions, read for the rule the address names (ADR-0190). */
|
|
30
|
+
this.rule = new QueryController(this, gql `
|
|
31
|
+
query ($id: String) {
|
|
32
|
+
companyRegulation(id: $id) {
|
|
33
|
+
regulation { id code name kind topics }
|
|
34
|
+
versions {
|
|
35
|
+
...RegulationVersionViewFields
|
|
36
|
+
procedures { id kind day method workersCount consentCount notes files }
|
|
37
|
+
originals
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
${VERSION_VIEW}
|
|
42
|
+
`, { variables: () => (this.ruleId ? { id: this.ruleId } : undefined) });
|
|
43
|
+
/* What is typed belongs to the version it was typed on: the text edits over the version read, and the procedure being
|
|
44
|
+
recorded. Another version drops both, so none of it lands there. */
|
|
45
|
+
this.draft = new DraftController(this, { read: () => this.current?.version, key: () => this.current?.version.id });
|
|
46
|
+
this.procedure = new DraftController(this, { read: () => ({ day: '', notes: '' }), key: () => this.current?.version.id });
|
|
47
|
+
/* Every change reads the rule again once it is done. */
|
|
48
|
+
this.saves = {
|
|
49
|
+
draft: this.change(gql `mutation ($id: String!, $patch: RegulationVersionPatch!) { updateRegulationVersion(id: $id, patch: $patch) { id } }`),
|
|
50
|
+
submit: this.change(gql `mutation ($id: String!) { submitRegulationVersion(id: $id) { id status } }`),
|
|
51
|
+
inForce: this.change(gql `
|
|
52
|
+
mutation ($id: String!, $files: [Upload!]!) {
|
|
53
|
+
registerRegulationInForce(id: $id, files: $files) { id status }
|
|
54
|
+
}
|
|
55
|
+
`),
|
|
56
|
+
withdraw: this.change(gql `mutation ($id: String!) { withdrawRegulationVersion(id: $id) { id } }`),
|
|
57
|
+
newVersion: this.change(gql `mutation ($id: String!) { newRegulationVersion(regulationId: $id) { id } }`),
|
|
58
|
+
deleteVersion: this.change(gql `mutation ($id: String!) { deleteRegulationVersion(id: $id) }`),
|
|
59
|
+
procedure: this.change(gql `
|
|
60
|
+
mutation ($procedure: NewRegulationProcedure!, $files: [Upload!]) {
|
|
61
|
+
recordRegulationProcedure(procedure: $procedure, files: $files) { id }
|
|
62
|
+
}
|
|
63
|
+
`),
|
|
64
|
+
deleteProcedure: this.change(gql `mutation ($id: String!) { deleteRegulationProcedure(id: $id) }`)
|
|
65
|
+
};
|
|
33
66
|
}
|
|
34
67
|
static { this.styles = [
|
|
35
68
|
DocumentPageStyles,
|
|
@@ -84,6 +117,17 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
84
117
|
}
|
|
85
118
|
`
|
|
86
119
|
]; }
|
|
120
|
+
change(mutation) {
|
|
121
|
+
return new MutationController(this, mutation, { refetch: () => [this.rule] });
|
|
122
|
+
}
|
|
123
|
+
get view() {
|
|
124
|
+
return this.rule.data?.companyRegulation ?? null;
|
|
125
|
+
}
|
|
126
|
+
/* A save, a submission or a procedure on its way: nothing is typed, switched or sent again until it is back, so what
|
|
127
|
+
is sent is what the screen shows and no answer lands on input typed after it. */
|
|
128
|
+
get busy() {
|
|
129
|
+
return Object.values(this.saves).some(save => save.pending);
|
|
130
|
+
}
|
|
87
131
|
get context() {
|
|
88
132
|
const version = this.current?.version;
|
|
89
133
|
const actions = [];
|
|
@@ -103,8 +147,8 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
103
147
|
return versions.find((one) => one.version.id === this.chosen) ?? versions[0];
|
|
104
148
|
}
|
|
105
149
|
render() {
|
|
106
|
-
if (this.
|
|
107
|
-
return html `<ox-page-state state="error" .message=${this.
|
|
150
|
+
if (this.rule.error)
|
|
151
|
+
return html `<ox-page-state state="error" .message=${failureOf(this.rule.error)}></ox-page-state>`;
|
|
108
152
|
if (!this.view)
|
|
109
153
|
return html `<ox-page-state state="loading"></ox-page-state>`;
|
|
110
154
|
const current = this.current;
|
|
@@ -116,9 +160,10 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
116
160
|
<div class="page-section-actions"><button @click=${() => navigate('regulation-list')}>${i18next.t('button.regulation-all')}</button></div>
|
|
117
161
|
</header>
|
|
118
162
|
<ox-input-select-buttons
|
|
163
|
+
?disabled=${this.busy}
|
|
119
164
|
.value=${current.version.id}
|
|
120
165
|
.options=${this.view.versions.map((one) => ({ value: one.version.id, display: `${i18next.t('text.regulation-version-of', { version: one.version.version })} · ${wordOf('regulation-period', one.period)}` }))}
|
|
121
|
-
@change=${(e) => e.detail && this.
|
|
166
|
+
@change=${(e) => e.detail && this.switchTo(e.detail)}
|
|
122
167
|
></ox-input-select-buttons>
|
|
123
168
|
</section>
|
|
124
169
|
${current ? this.renderVersion(current) : nothing}
|
|
@@ -127,11 +172,12 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
127
172
|
renderVersion(view) {
|
|
128
173
|
const { version } = view;
|
|
129
174
|
const writing = version.status === 'DRAFT';
|
|
130
|
-
const
|
|
131
|
-
const
|
|
175
|
+
const locked = !writing || this.busy;
|
|
176
|
+
const value = (name) => this.draft.value(name) ?? '';
|
|
177
|
+
const set = (name, given) => !this.busy && this.draft.set(name, given);
|
|
132
178
|
const words = { ADDED: i18next.t('text.regulation-change-added'), CHANGED: i18next.t('text.regulation-change-changed'), REMOVED: i18next.t('text.regulation-change-removed') };
|
|
133
179
|
const filing = this.view.regulation.kind === 'WORK_RULES' || this.view.regulation.kind === 'WORK_RULES_ANNEX';
|
|
134
|
-
const kinds = version.status === 'ADOPTED' ? ['FILING'] : writing ?
|
|
180
|
+
const kinds = !filing ? [] : version.status === 'ADOPTED' ? ['FILING'] : writing ? [value('unfavourable') === true ? 'CONSENT' : 'OPINION'] : [];
|
|
135
181
|
return html `<section class="page-section">
|
|
136
182
|
<header class="page-section-header"><h3>${i18next.t('text.regulation-version-of', { version: version.version })} · ${wordOf('regulation-period', view.period)}</h3></header>
|
|
137
183
|
${version.adoptionNote ? html `<p class="page-section-note note">${version.adoptionNote}</p>` : nothing}
|
|
@@ -140,29 +186,29 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
140
186
|
<div class="form">
|
|
141
187
|
<label class="field">
|
|
142
188
|
<span>${i18next.t('field.regulation-effective-on')}</span>
|
|
143
|
-
<input type="date" ?disabled=${
|
|
189
|
+
<input type="date" ?disabled=${locked} .value=${value('effectiveOn')} @input=${(e) => set('effectiveOn', e.target.value)} />
|
|
144
190
|
<span>${i18next.t('text.regulation-effective-hint')}</span>
|
|
145
191
|
</label>
|
|
146
|
-
|
|
192
|
+
${filing ? html `<div class="field">
|
|
147
193
|
<span>${i18next.t('field.regulation-unfavourable')}</span>
|
|
148
194
|
<ox-input-select-buttons
|
|
149
|
-
?disabled=${
|
|
195
|
+
?disabled=${locked}
|
|
150
196
|
.value=${value('unfavourable') === '' ? '' : String(value('unfavourable'))}
|
|
151
197
|
.options=${[{ value: 'true', display: i18next.t('text.regulation-unfavourable-yes') }, { value: 'false', display: i18next.t('text.regulation-unfavourable-no') }]}
|
|
152
198
|
@change=${(e) => writing && e.detail && set('unfavourable', e.detail === 'true')}
|
|
153
199
|
></ox-input-select-buttons>
|
|
154
200
|
<span>${i18next.t('text.regulation-unfavourable-hint')}</span>
|
|
155
|
-
</div
|
|
201
|
+
</div>` : nothing}
|
|
156
202
|
<label class="field">
|
|
157
203
|
<span>${i18next.t('field.regulation-change-summary')}</span>
|
|
158
|
-
<input ?disabled=${
|
|
204
|
+
<input ?disabled=${locked} .value=${value('changeSummary')} @input=${(e) => set('changeSummary', e.target.value)} />
|
|
159
205
|
</label>
|
|
160
206
|
</div>
|
|
161
207
|
</section>
|
|
162
208
|
<section class="page-section">
|
|
163
209
|
<header class="page-section-header"><h3>${i18next.t('field.regulation-body')}</h3></header>
|
|
164
210
|
<p class="page-section-note muted">${i18next.t('text.regulation-body-hint')}</p>
|
|
165
|
-
<textarea class="body" ?disabled=${
|
|
211
|
+
<textarea class="body" ?disabled=${locked} .value=${value('body')} @input=${(e) => set('body', e.target.value)}></textarea>
|
|
166
212
|
</section>
|
|
167
213
|
${view.changes.length
|
|
168
214
|
? html `<section class="page-section">
|
|
@@ -172,21 +218,21 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
172
218
|
</table>
|
|
173
219
|
</section>`
|
|
174
220
|
: nothing}
|
|
175
|
-
|
|
221
|
+
${filing || view.procedures?.length ? html `<section class="page-section">
|
|
176
222
|
<header class="page-section-header"><h3>${i18next.t('text.regulation-procedures')}</h3></header>
|
|
177
223
|
<p class="page-section-note muted">${i18next.t(filing ? 'text.regulation-procedures-hint' : 'text.regulation-procedures-none-asked')}</p>
|
|
178
224
|
<table>
|
|
179
225
|
${(view.procedures ?? []).map((one) => html `<tr>
|
|
180
226
|
<td>${wordOf('regulation-procedure-kind', one.kind)}</td>
|
|
181
227
|
<td>${one.day}</td>
|
|
182
|
-
<td>${one.method ? wordOf('regulation-procedure-method', one.method) : ''}</td>
|
|
183
|
-
<td>${one.kind === 'CONSENT' ? i18next.t('text.regulation-consent-count', { consented: one.consentCount, workers: one.workersCount }) : ''}</td>
|
|
228
|
+
<td>${one.method && Object.values(PROCEDURE_METHODS).some(methods => methods.includes(one.method)) ? wordOf('regulation-procedure-method', one.method) : ''}</td>
|
|
229
|
+
<td>${one.kind === 'CONSENT' && one.workersCount != null && one.consentCount != null ? i18next.t('text.regulation-consent-count', { consented: one.consentCount, workers: one.workersCount }) : ''}</td>
|
|
184
230
|
<td>${i18next.t('text.regulation-files', { count: one.files })}</td>
|
|
185
|
-
<td>${writing ? html `<button class="danger" @click=${() => this.deleteProcedure(one.id)}>${i18next.t('button.delete')}</button>` : nothing}</td>
|
|
231
|
+
<td>${writing ? html `<button class="danger" ?disabled=${this.busy} @click=${() => this.deleteProcedure(one.id)}>${i18next.t('button.delete')}</button>` : nothing}</td>
|
|
186
232
|
</tr>`)}
|
|
187
233
|
</table>
|
|
188
234
|
${kinds.length ? this.renderProcedureForm(kinds) : nothing}
|
|
189
|
-
</section
|
|
235
|
+
</section>` : nothing}
|
|
190
236
|
${writing && !this.view.versions.some((one) => one.version.status !== 'DRAFT') ? this.renderInForce() : nothing}`;
|
|
191
237
|
}
|
|
192
238
|
/* A rule in force before the system - its first version registered from its own day with its original (ADR-0187 amendment 2). */
|
|
@@ -197,115 +243,112 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
197
243
|
<div class="procedure-form">
|
|
198
244
|
<div class="field">
|
|
199
245
|
<span>${i18next.t('field.regulation-original')}</span>
|
|
200
|
-
<ox-input-file multiple .value=${this.originals} @change=${(e) => (this.originals = e.detail ?? [])}></ox-input-file>
|
|
246
|
+
<ox-input-file multiple ?disabled=${this.busy} .value=${this.originals} @change=${(e) => !this.busy && (this.originals = e.detail ?? [])}></ox-input-file>
|
|
201
247
|
</div>
|
|
202
|
-
<button @click=${() => this.registerInForce()}>${i18next.t('button.regulation-register-in-force')}</button>
|
|
248
|
+
<button ?disabled=${this.busy} @click=${() => this.registerInForce()}>${i18next.t('button.regulation-register-in-force')}</button>
|
|
203
249
|
</div>
|
|
204
250
|
</section>`;
|
|
205
251
|
}
|
|
206
252
|
renderProcedureForm(kinds) {
|
|
207
|
-
const kind = kinds
|
|
208
|
-
const set = (name, given) =>
|
|
253
|
+
const kind = kinds[0];
|
|
254
|
+
const set = (name, given) => !this.busy && this.procedure.set(name, given);
|
|
209
255
|
return html `<div class="procedure-form">
|
|
210
256
|
<div class="field">
|
|
211
257
|
<span>${i18next.t('field.regulation-procedure-kind')}</span>
|
|
212
|
-
<
|
|
258
|
+
<span>${wordOf('regulation-procedure-kind', kind)}</span>
|
|
213
259
|
</div>
|
|
214
|
-
<label class="field"><span>${i18next.t('field.regulation-procedure-day')}</span><input type="date" .value=${this.procedure.day} @input=${(e) => set('day', e.target.value)} /></label>
|
|
215
|
-
<
|
|
216
|
-
<span>${i18next.t('field.regulation-procedure-method')}</span>
|
|
217
|
-
<ox-input-select-buttons .value=${this.procedure.method} .options=${PROCEDURE_METHODS[kind].map(code => ({ value: code, display: wordOf('regulation-procedure-method', code) }))} @change=${(e) => set('method', e.detail ?? '')}></ox-input-select-buttons>
|
|
218
|
-
</div>
|
|
219
|
-
${kind === 'CONSENT'
|
|
220
|
-
? html `<label class="field">
|
|
221
|
-
<span>${i18next.t('field.regulation-workers-count')}</span>
|
|
222
|
-
<input type="number" min="1" .value=${this.procedure.workersCount} @input=${(e) => set('workersCount', e.target.value)} />
|
|
223
|
-
${this.employees !== null ? html `<span>${i18next.t('text.regulation-active-employees', { count: this.employees })}</span>` : nothing}
|
|
224
|
-
</label>
|
|
225
|
-
<label class="field"><span>${i18next.t('field.regulation-consent-count')}</span><input type="number" min="0" .value=${this.procedure.consentCount} @input=${(e) => set('consentCount', e.target.value)} /></label>`
|
|
226
|
-
: nothing}
|
|
227
|
-
<label class="field"><span>${i18next.t('field.regulation-procedure-notes')}</span><input .value=${this.procedure.notes} @input=${(e) => set('notes', e.target.value)} /></label>
|
|
260
|
+
<label class="field"><span>${i18next.t('field.regulation-procedure-day')}</span><input type="date" ?disabled=${this.busy} .value=${this.procedure.value('day')} @input=${(e) => set('day', e.target.value)} /></label>
|
|
261
|
+
<label class="field"><span>${i18next.t('field.regulation-procedure-notes')}</span><input ?disabled=${this.busy} .value=${this.procedure.value('notes')} @input=${(e) => set('notes', e.target.value)} /></label>
|
|
228
262
|
<div class="field">
|
|
229
263
|
<span>${i18next.t('field.regulation-procedure-files')}</span>
|
|
230
|
-
<ox-input-file multiple .value=${this.files} @change=${(e) => (this.files = e.detail ?? [])}></ox-input-file>
|
|
264
|
+
<ox-input-file multiple ?disabled=${this.busy} .value=${this.files} @change=${(e) => !this.busy && (this.files = e.detail ?? [])}></ox-input-file>
|
|
231
265
|
</div>
|
|
232
|
-
<button @click=${() => this.recordProcedure(kind)}>${i18next.t('button.regulation-procedure-record')}</button>
|
|
266
|
+
<button ?disabled=${this.busy} @click=${() => this.recordProcedure(kind)}>${i18next.t('button.regulation-procedure-record')}</button>
|
|
233
267
|
</div>`;
|
|
234
268
|
}
|
|
235
269
|
async pageUpdated(changes, lifecycle) {
|
|
236
270
|
if (!this.active)
|
|
237
271
|
return;
|
|
238
272
|
const params = new URLSearchParams(location.search);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
query ($id: String) {
|
|
249
|
-
companyRegulation(id: $id) {
|
|
250
|
-
regulation { id code name kind topics }
|
|
251
|
-
versions {
|
|
252
|
-
...RegulationVersionViewFields
|
|
253
|
-
procedures { id kind day method workersCount consentCount notes files }
|
|
254
|
-
originals
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
activeEmployeeCount
|
|
258
|
-
}
|
|
259
|
-
${VERSION_VIEW}
|
|
260
|
-
`,
|
|
261
|
-
variables: { id },
|
|
262
|
-
fetchPolicy: 'no-cache'
|
|
263
|
-
});
|
|
264
|
-
if (response.errors?.length)
|
|
265
|
-
throw response;
|
|
266
|
-
this.view = response.data.companyRegulation;
|
|
267
|
-
this.employees = response.data.activeEmployeeCount;
|
|
268
|
-
this.failure = '';
|
|
269
|
-
this.updateContext();
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
this.failure = failureOf(error);
|
|
273
|
-
}
|
|
273
|
+
const id = params.get('id') ?? lifecycle?.params?.id;
|
|
274
|
+
const version = params.get('version');
|
|
275
|
+
/* Another rule, or another version asked by the address: the shell asked about what was typed (addressDirty) and
|
|
276
|
+
dropped it before the address changed; this page only moves to it. */
|
|
277
|
+
const another = !!this.view && !!id && id !== this.view.regulation.id;
|
|
278
|
+
if (another || (version && version !== this.chosen))
|
|
279
|
+
this.choose(version ?? '');
|
|
280
|
+
if (id)
|
|
281
|
+
this.ruleId = id;
|
|
274
282
|
}
|
|
283
|
+
/* The files picked belong to the version they were picked on, as the drafts do: switching drops them. */
|
|
275
284
|
choose(id) {
|
|
276
285
|
this.chosen = id;
|
|
277
|
-
this.
|
|
286
|
+
this.files = [];
|
|
287
|
+
this.originals = [];
|
|
278
288
|
this.updateContext();
|
|
279
289
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
/*
|
|
291
|
+
* PageView reads the drafts; the files picked are the page's own unsaved state too. The shell asks about them before
|
|
292
|
+
* any move - 「규정 목록」, the menu, another rule's address, closing the tab - and drops them once the move is agreed.
|
|
293
|
+
*/
|
|
294
|
+
get addressDirty() {
|
|
295
|
+
return super.addressDirty || this.files.length > 0 || this.originals.length > 0;
|
|
296
|
+
}
|
|
297
|
+
get addressDiscardText() {
|
|
298
|
+
return i18next.t('text.regulation-leave-unsaved');
|
|
299
|
+
}
|
|
300
|
+
discardAddressEdits(change) {
|
|
301
|
+
super.discardAddressEdits(change);
|
|
302
|
+
this.choose(this.chosen);
|
|
303
|
+
}
|
|
304
|
+
/* A version switch stays on the page, so the page asks the shell's question itself. */
|
|
305
|
+
async mayLeave() {
|
|
306
|
+
return await this.canDeactivate();
|
|
307
|
+
}
|
|
308
|
+
async switchTo(id) {
|
|
309
|
+
if (this.busy || id === this.current?.version.id) {
|
|
310
|
+
const buttons = this.renderRoot.querySelector('ox-input-select-buttons');
|
|
311
|
+
if (buttons)
|
|
312
|
+
buttons.value = this.current?.version.id;
|
|
313
|
+
return;
|
|
293
314
|
}
|
|
315
|
+
if (await this.mayLeave())
|
|
316
|
+
return this.choose(id);
|
|
317
|
+
/* Staying: the buttons already show the version clicked - put them back on the one still open. */
|
|
318
|
+
const buttons = this.renderRoot.querySelector('ox-input-select-buttons');
|
|
319
|
+
if (buttons)
|
|
320
|
+
buttons.value = this.current?.version.id;
|
|
294
321
|
}
|
|
295
|
-
|
|
296
|
-
|
|
322
|
+
async call(save, variables, done = 'text.regulation-saved', context) {
|
|
323
|
+
if (this.busy)
|
|
324
|
+
return undefined;
|
|
325
|
+
const data = await save.run(variables, { context });
|
|
326
|
+
if (data)
|
|
327
|
+
notify({ message: i18next.t(done) });
|
|
328
|
+
return data;
|
|
329
|
+
}
|
|
330
|
+
patchOf(sent) {
|
|
331
|
+
const patch = { ...sent };
|
|
297
332
|
if (patch.effectiveOn === '')
|
|
298
333
|
patch.effectiveOn = null;
|
|
299
334
|
return patch;
|
|
300
335
|
}
|
|
336
|
+
/* Saves the text edits of the version chosen - the one door that clears them. */
|
|
337
|
+
async saveDraft(done = 'text.regulation-saved') {
|
|
338
|
+
const on = this.current.version.id;
|
|
339
|
+
return await this.draft.submit(sent => this.call(this.saves.draft, { id: on, patch: this.patchOf(sent) }, done));
|
|
340
|
+
}
|
|
301
341
|
async saveVersion() {
|
|
302
|
-
if (!
|
|
342
|
+
if (!this.draft.dirty)
|
|
303
343
|
return;
|
|
304
|
-
await this.
|
|
344
|
+
await this.saveDraft();
|
|
305
345
|
}
|
|
306
346
|
async submit() {
|
|
307
347
|
const id = this.current.version.id;
|
|
308
|
-
if (
|
|
348
|
+
if (this.draft.dirty && !(await this.saveDraft()))
|
|
349
|
+
return;
|
|
350
|
+
/* Only what the screen shows is put up: anything not saved yet stops the submission. */
|
|
351
|
+
if (this.draft.dirty || this.current?.version.id !== id)
|
|
309
352
|
return;
|
|
310
353
|
const confirmed = await OxPrompt.open({
|
|
311
354
|
title: i18next.t('button.regulation-submit'),
|
|
@@ -314,12 +357,15 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
314
357
|
cancelButton: { text: i18next.t('button.cancel') }
|
|
315
358
|
});
|
|
316
359
|
if (confirmed)
|
|
317
|
-
await this.call(
|
|
360
|
+
await this.call(this.saves.submit, { id }, 'text.regulation-submitted');
|
|
318
361
|
}
|
|
319
362
|
async registerInForce() {
|
|
320
363
|
const id = this.current.version.id;
|
|
321
|
-
if (
|
|
364
|
+
if (this.draft.dirty && !(await this.saveDraft()))
|
|
322
365
|
return;
|
|
366
|
+
if (this.draft.dirty || this.current?.version.id !== id)
|
|
367
|
+
return;
|
|
368
|
+
const originals = this.originals;
|
|
323
369
|
const confirmed = await OxPrompt.open({
|
|
324
370
|
title: i18next.t('button.regulation-register-in-force'),
|
|
325
371
|
text: i18next.t('text.regulation-in-force-confirm', { version: this.current.version.version, day: this.current.version.effectiveOn ?? '' }),
|
|
@@ -328,75 +374,56 @@ let RegulationDetail = class RegulationDetail extends localize(i18next)(PageView
|
|
|
328
374
|
});
|
|
329
375
|
if (!confirmed)
|
|
330
376
|
return;
|
|
331
|
-
const done = await this.call(
|
|
332
|
-
|
|
333
|
-
registerRegulationInForce(id: $id, files: $files) { id status }
|
|
334
|
-
}
|
|
335
|
-
`, { id, files: this.originals }, 'text.regulation-registered-in-force', this.originals.length ? uploadContext(() => { }) : undefined);
|
|
336
|
-
if (done)
|
|
377
|
+
const done = await this.call(this.saves.inForce, { id, files: originals }, 'text.regulation-registered-in-force', originals.length ? uploadContext(() => { }) : undefined);
|
|
378
|
+
if (done && this.originals === originals)
|
|
337
379
|
this.originals = [];
|
|
338
380
|
}
|
|
339
381
|
async withdraw() {
|
|
340
|
-
await this.call(
|
|
382
|
+
await this.call(this.saves.withdraw, { id: this.current.version.id });
|
|
341
383
|
}
|
|
342
384
|
async newVersion() {
|
|
343
|
-
const data = await this.call(
|
|
385
|
+
const data = await this.call(this.saves.newVersion, { id: this.view.regulation.id });
|
|
344
386
|
if (data)
|
|
345
387
|
this.choose(data.newRegulationVersion.id);
|
|
346
388
|
}
|
|
389
|
+
/** The revision asked about is the one deleted: if the screen shows another once confirmed, nothing is deleted. */
|
|
347
390
|
async deleteVersion() {
|
|
391
|
+
const id = this.current?.version.id;
|
|
392
|
+
if (!id)
|
|
393
|
+
return;
|
|
348
394
|
const confirmed = await OxPrompt.open({
|
|
349
395
|
title: i18next.t('button.regulation-version-delete'),
|
|
350
396
|
text: i18next.t('text.regulation-version-delete-confirm'),
|
|
351
397
|
confirmButton: { text: i18next.t('button.delete'), destructive: true },
|
|
352
398
|
cancelButton: { text: i18next.t('button.cancel') }
|
|
353
399
|
});
|
|
354
|
-
if (confirmed
|
|
355
|
-
|
|
400
|
+
if (!confirmed || this.current?.version.id !== id)
|
|
401
|
+
return;
|
|
402
|
+
if (await this.call(this.saves.deleteVersion, { id }))
|
|
403
|
+
this.choose('');
|
|
356
404
|
}
|
|
357
405
|
async recordProcedure(kind) {
|
|
358
|
-
const
|
|
359
|
-
const done = await this.call(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
files: this.files
|
|
366
|
-
}, 'text.regulation-saved', this.files.length ? uploadContext(() => { }) : undefined);
|
|
367
|
-
if (done) {
|
|
368
|
-
this.procedure = { kind: 'OPINION', day: '', method: '', workersCount: '', consentCount: '', notes: '' };
|
|
406
|
+
const files = this.files;
|
|
407
|
+
const done = await this.procedure.submit(sent => this.call(this.saves.procedure, {
|
|
408
|
+
procedure: { versionId: this.current.version.id, kind, day: sent.day ?? '', notes: sent.notes || null },
|
|
409
|
+
files
|
|
410
|
+
}, 'text.regulation-saved', files.length ? uploadContext(() => { }) : undefined));
|
|
411
|
+
/* Only what was sent is done - a file picked since stays. */
|
|
412
|
+
if (done && this.files === files)
|
|
369
413
|
this.files = [];
|
|
370
|
-
}
|
|
371
414
|
}
|
|
372
415
|
async deleteProcedure(id) {
|
|
373
|
-
await this.call(
|
|
416
|
+
await this.call(this.saves.deleteProcedure, { id });
|
|
374
417
|
}
|
|
375
418
|
};
|
|
376
419
|
__decorate([
|
|
377
420
|
state(),
|
|
378
421
|
__metadata("design:type", Object)
|
|
379
|
-
], RegulationDetail.prototype, "
|
|
380
|
-
__decorate([
|
|
381
|
-
state(),
|
|
382
|
-
__metadata("design:type", Object)
|
|
383
|
-
], RegulationDetail.prototype, "failure", void 0);
|
|
422
|
+
], RegulationDetail.prototype, "ruleId", void 0);
|
|
384
423
|
__decorate([
|
|
385
424
|
state(),
|
|
386
425
|
__metadata("design:type", Object)
|
|
387
426
|
], RegulationDetail.prototype, "chosen", void 0);
|
|
388
|
-
__decorate([
|
|
389
|
-
state(),
|
|
390
|
-
__metadata("design:type", Object)
|
|
391
|
-
], RegulationDetail.prototype, "draft", void 0);
|
|
392
|
-
__decorate([
|
|
393
|
-
state(),
|
|
394
|
-
__metadata("design:type", Object)
|
|
395
|
-
], RegulationDetail.prototype, "employees", void 0);
|
|
396
|
-
__decorate([
|
|
397
|
-
state(),
|
|
398
|
-
__metadata("design:type", Object)
|
|
399
|
-
], RegulationDetail.prototype, "procedure", void 0);
|
|
400
427
|
__decorate([
|
|
401
428
|
state(),
|
|
402
429
|
__metadata("design:type", Array)
|