@things-factory/meta-ui 8.0.0-beta.8 → 8.0.0

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 (115) hide show
  1. package/client/bootstrap.ts +170 -0
  2. package/client/component/filter/filter-form-meta-code-select.ts +102 -0
  3. package/client/component/filter/filter-form-meta-object-select.ts +107 -0
  4. package/client/component/filter/filter-grist-meta-code-select.ts +97 -0
  5. package/client/component/filter/filter-grist-meta-object-select.ts +102 -0
  6. package/client/component/grist/editor/grist-editor-code-input.js +96 -0
  7. package/client/component/grist/editor/grist-editor-meta-code-selector.js +157 -0
  8. package/client/component/grist/editor/grist-editor-meta-object-selector.js +122 -0
  9. package/client/component/grist/renderer/grist-renderer-code-input.js +20 -0
  10. package/client/component/grist/renderer/grist-renderer-meta-code-selector.js +28 -0
  11. package/client/component/grist/renderer/grist-renderer-meta-object-selector.js +25 -0
  12. package/client/component/popup/code-input-editor-popup.js +111 -0
  13. package/client/component/popup/file-upload-popup.js +129 -0
  14. package/client/component/popup/meta-object-selector-popup.ts +356 -0
  15. package/client/component/popup/record-based-code-editor-popup.ts +141 -0
  16. package/client/dynamic-menus.ts +38 -0
  17. package/client/index.ts +18 -0
  18. package/client/load-components.ts +17 -0
  19. package/client/mixin/meta-base-mixin.js +323 -0
  20. package/client/mixin/meta-basic-grist-mixin.js +283 -0
  21. package/client/mixin/meta-button-mixin.js +116 -0
  22. package/client/mixin/meta-form-mixin.js +435 -0
  23. package/client/mixin/meta-grist-tab-mixin.js +335 -0
  24. package/client/mixin/meta-main-tab-mixin.js +267 -0
  25. package/client/mixin/meta-master-detail-mixin.js +395 -0
  26. package/client/mixin/meta-service-mixin.js +306 -0
  27. package/client/mixin/meta-tab-detail-mixin.js +283 -0
  28. package/client/mixin/meta-tab-mixin.js +190 -0
  29. package/client/pages/activity/meta-activity-define-page.js +422 -0
  30. package/client/pages/activity/meta-activity-list-page.js +262 -0
  31. package/client/pages/activity/meta-activity-viewer-element.js +35 -0
  32. package/client/pages/activity/meta-activity-writer-element.js +48 -0
  33. package/client/pages/activity/meta-activiy-mixin.js +79 -0
  34. package/client/pages/button-role/button-role-detail.js +50 -0
  35. package/client/pages/button-role/button-role-page.js +25 -0
  36. package/client/pages/doc-number/doc-number-page.js +24 -0
  37. package/client/pages/doc-number/next-doc-number-popup.js +25 -0
  38. package/client/pages/entity/config-entity.js +955 -0
  39. package/client/pages/entity/main-menu-selector.js +245 -0
  40. package/client/pages/history/history-copy-list-popup.js +145 -0
  41. package/client/pages/history/history-json-list-popup.js +159 -0
  42. package/client/pages/menu/dynamic-menu-template.js +92 -0
  43. package/client/pages/menu/dynamic-menu.ts +744 -0
  44. package/client/pages/menu/export-menu-popup.js +468 -0
  45. package/client/pages/meta-form-element.js +9 -0
  46. package/client/pages/meta-grist-element.js +12 -0
  47. package/client/pages/meta-grist-page.js +16 -0
  48. package/client/pages/meta-grist-tab-element.js +16 -0
  49. package/client/pages/meta-grist-tab-page.js +16 -0
  50. package/client/pages/meta-main-tab-element.js +12 -0
  51. package/client/pages/meta-main-tab-page.js +16 -0
  52. package/client/pages/meta-master-detail-element.js +12 -0
  53. package/client/pages/meta-master-detail-page.js +16 -0
  54. package/client/pages/meta-tab-detail-element.js +12 -0
  55. package/client/pages/meta-tab-detail-page.js +16 -0
  56. package/client/pages/meta-tab-element.js +15 -0
  57. package/client/pages/printer-device/printer-device-page.js +24 -0
  58. package/client/pages/template/doc-template-page.js +24 -0
  59. package/client/pages/template/template-file-page.js +24 -0
  60. package/client/pages/terms/config-terminology.js +214 -0
  61. package/client/pages/work-code/work-code-detail-popup.js +16 -0
  62. package/client/pages/work-code/work-code-page.js +23 -0
  63. package/client/route.ts +36 -0
  64. package/client/tsconfig.json +13 -0
  65. package/client/utils/grist-default-value.js +36 -0
  66. package/client/utils/meta-api.js +811 -0
  67. package/client/utils/meta-crypto.js +52 -0
  68. package/client/utils/meta-ui-util.js +3304 -0
  69. package/client/utils/rest-service-util.js +328 -0
  70. package/client/utils/service-util.js +1327 -0
  71. package/client/utils/terms-util.ts +119 -0
  72. package/client/utils/ui-util.js +338 -0
  73. package/client/utils/value-util.js +234 -0
  74. package/dist-client/tsconfig.tsbuildinfo +1 -1
  75. package/dist-client/utils/service-util.d.ts +2 -2
  76. package/dist-client/utils/service-util.js +4 -4
  77. package/dist-client/utils/service-util.js.map +1 -1
  78. package/dist-server/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +24 -24
  80. package/server/activity/CommonActivity.ts +68 -0
  81. package/server/index.ts +3 -0
  82. package/server/routes.ts +61 -0
  83. package/server/service/button-role/button-role-mutation.ts +105 -0
  84. package/server/service/button-role/button-role-query.ts +53 -0
  85. package/server/service/button-role/button-role-type.ts +39 -0
  86. package/server/service/button-role/button-role.ts +61 -0
  87. package/server/service/button-role/index.ts +7 -0
  88. package/server/service/dynamic-menu/dynamic-menu-query.ts +270 -0
  89. package/server/service/dynamic-menu/dynamic-menu-type.ts +74 -0
  90. package/server/service/dynamic-menu/index.ts +3 -0
  91. package/server/service/entity-event-subscriber/entity-event-subscriber.ts +80 -0
  92. package/server/service/entity-event-subscriber/index.ts +3 -0
  93. package/server/service/index.ts +41 -0
  94. package/server/service/menu-button-auth/index.ts +7 -0
  95. package/server/service/menu-button-auth/menu-button-auth-mutation.ts +133 -0
  96. package/server/service/menu-button-auth/menu-button-auth-query.ts +138 -0
  97. package/server/service/menu-button-auth/menu-button-auth-type.ts +63 -0
  98. package/server/service/menu-button-auth/menu-button-auth.ts +92 -0
  99. package/server/service/meta-activity/index.ts +5 -0
  100. package/server/service/meta-activity/meta-activity-mutation.ts +191 -0
  101. package/server/service/meta-activity/meta-activity-query.ts +43 -0
  102. package/server/service/meta-activity/meta-activity-type.ts +56 -0
  103. package/server/service/set-translations/index.ts +3 -0
  104. package/server/service/set-translations/set-translation-resolver.ts +63 -0
  105. package/server/service/work-code/index.ts +6 -0
  106. package/server/service/work-code/work-code-mutation.ts +147 -0
  107. package/server/service/work-code/work-code-query.ts +67 -0
  108. package/server/service/work-code/work-code-type.ts +60 -0
  109. package/server/service/work-code/work-code.ts +83 -0
  110. package/server/service/work-code-detail/index.ts +6 -0
  111. package/server/service/work-code-detail/work-code-detail-mutation.ts +149 -0
  112. package/server/service/work-code-detail/work-code-detail-query.ts +59 -0
  113. package/server/service/work-code-detail/work-code-detail-type.ts +50 -0
  114. package/server/service/work-code-detail/work-code-detail.ts +82 -0
  115. package/server/tsconfig.json +9 -0
@@ -0,0 +1,157 @@
1
+ import { html } from 'lit'
2
+
3
+ import { OxGristEditor } from '@operato/data-grist'
4
+ import { openPopup } from '@operato/layout'
5
+ import { TermsUtil } from '../../../utils/terms-util';
6
+
7
+ import '../../popup/meta-object-selector-popup'
8
+
9
+ export class GristEditorMetaCodeSelector extends OxGristEditor {
10
+ static get properties() {
11
+ return {
12
+ value: Object,
13
+ column: Object,
14
+ record: Object,
15
+ rowIndex: Number,
16
+ field: Object,
17
+ popup: Object
18
+ }
19
+ }
20
+
21
+ get editorTemplate() {
22
+ let text = '';
23
+
24
+ if(!this.column.record || !this.column.record.options){
25
+ text = '';
26
+ } else if (!this.column.record.options.dispField){
27
+ text = this.value;
28
+ } else {
29
+ let codes = this.column.record.options.codes || [];
30
+
31
+ if(this.value && this.value.length > 0){
32
+ let codeDisp = codes.filter(x=> x.value === this.value);
33
+
34
+ if(codeDisp && codeDisp.length > 0){
35
+ text = codeDisp[0].display;
36
+ } else {
37
+ text = '';
38
+ }
39
+ }
40
+ }
41
+
42
+ return html`
43
+ ${!text
44
+ ? html`<span tabindex="0"></span>`
45
+ : html` <span tabindex="0" style="flex:1">${text}</span> `}
46
+ `
47
+ }
48
+
49
+ async firstUpdated() {
50
+ super.firstUpdated()
51
+ }
52
+
53
+ _onclick(e) {
54
+ e.stopPropagation()
55
+ this.openSelector()
56
+ }
57
+
58
+ _onkeydown(e) {
59
+ const key = e.key
60
+ if (key == 'Enter') {
61
+ e.stopPropagation()
62
+ this.openSelector()
63
+ }
64
+ }
65
+
66
+ openSelector() {
67
+ if (this.popup) {
68
+ delete this.popup
69
+ }
70
+
71
+ var {
72
+ selectorName = TermsUtil.tTitle('select_item')
73
+ } = this.column.record.options || {}
74
+
75
+ const confirmCallback = (selected) => {
76
+ let codeField = this.column.record.options.codeField;
77
+ let dispField = this.column.record.options.dispField;
78
+ let fieldMap = this.column.record.options.fieldMap || {};
79
+
80
+ if(!this.column.record.options.codes) {
81
+ this.column.record.options.codes = [];
82
+ }
83
+
84
+ if(selected){
85
+ let checkCodeList = this.column.record.options.codes.filter(x=> x.value == selected[codeField]);
86
+ if(!checkCodeList || checkCodeList.length == 0){
87
+ let disp = selected[codeField];
88
+
89
+ if(dispField){
90
+ let fields = dispField.split(",");
91
+ disp = selected[fields[0]];
92
+
93
+ if(fields.length > 1){
94
+ disp+= `(${fields.splice(1).map(field => { return selected[field]}).join(",")})`
95
+ }
96
+ }
97
+
98
+ this.column.record.options.codes.push({
99
+ value: selected[codeField],
100
+ display: disp
101
+ })
102
+ }
103
+ }
104
+
105
+ this.dispatchEvent(
106
+ new CustomEvent('field-change', {
107
+ bubbles: true,
108
+ composed: true,
109
+ detail: {
110
+ before: this.value,
111
+ after: selected
112
+ ? selected[codeField]
113
+ : null,
114
+ record: this.record,
115
+ column: this.column,
116
+ row: this.row
117
+ }
118
+ })
119
+ )
120
+
121
+
122
+ Object.keys(fieldMap).forEach(key =>{
123
+ this.dispatchEvent(
124
+ new CustomEvent('field-change', {
125
+ bubbles: true,
126
+ composed: true,
127
+ detail: {
128
+ before: this.record[fieldMap[key]],
129
+ after: selected
130
+ ? selected[key]
131
+ : null,
132
+ record: this.record,
133
+ column: {name: fieldMap[key]},
134
+ row: this.row
135
+ }
136
+ })
137
+ )
138
+ })
139
+ }
140
+
141
+ var template = html`
142
+ <meta-object-selector-popup
143
+ .value=${this.value}
144
+ .options=${this.column.record.options}
145
+ .confirmCallback=${confirmCallback.bind(this)}
146
+ ></meta-object-selector-popup>
147
+ `
148
+
149
+ this.popup = openPopup(template, {
150
+ backdrop: true,
151
+ size: 'large',
152
+ title: TermsUtil.tMenu(selectorName)
153
+ })
154
+ }
155
+ }
156
+
157
+ customElements.define('grist-editor-meta-code-selector', GristEditorMetaCodeSelector)
@@ -0,0 +1,122 @@
1
+ import { html } from 'lit'
2
+
3
+ import { OxGristEditor } from '@operato/data-grist'
4
+ import { openPopup } from '@operato/layout'
5
+ import { TermsUtil } from '../../../utils/terms-util';
6
+
7
+ import '../../popup/meta-object-selector-popup'
8
+
9
+ export class GristEditorMetaObjectSelector extends OxGristEditor {
10
+ static get properties() {
11
+ return {
12
+ value: Object,
13
+ column: Object,
14
+ record: Object,
15
+ rowIndex: Number,
16
+ field: Object,
17
+ popup: Object
18
+ }
19
+ }
20
+
21
+ get editorTemplate() {
22
+ let text = '';
23
+
24
+ if(this.value && this.column.record.options){
25
+
26
+ let fields = this.column.record.options.nameField.split(",");
27
+ text = this.value[fields[0]];
28
+
29
+ if(fields.length > 1){
30
+ text+= `(${fields.splice(1).map(field => { return this.value[field]}).join(",")})`
31
+ }
32
+ }
33
+
34
+ return html`
35
+ ${!this.value
36
+ ? html`<span tabindex="0">${text}</span>`
37
+ : html` <span tabindex="0" style="flex:1">${text}</span> `}
38
+ `
39
+ }
40
+
41
+ async firstUpdated() {
42
+ super.firstUpdated()
43
+ }
44
+
45
+ _onclick(e) {
46
+ e.stopPropagation()
47
+ this.openSelector()
48
+ }
49
+
50
+ _onkeydown(e) {
51
+ const key = e.key
52
+ if (key == 'Enter') {
53
+ e.stopPropagation()
54
+ this.openSelector()
55
+ }
56
+ }
57
+
58
+ openSelector() {
59
+ if (this.popup) {
60
+ delete this.popup
61
+ }
62
+
63
+ var {
64
+ selectorName = TermsUtil.tTitle('select_item')
65
+ } = this.column.record.options || {}
66
+
67
+ const confirmCallback = (selected) => {
68
+ let fieldMap = this.column.record.options.fieldMap || {};
69
+
70
+ this.dispatchEvent(
71
+ new CustomEvent('field-change', {
72
+ bubbles: true,
73
+ composed: true,
74
+ detail: {
75
+ before: this.value,
76
+ after: selected
77
+ ? selected
78
+ : null,
79
+ record: this.record,
80
+ column: this.column,
81
+ row: this.row
82
+ }
83
+ })
84
+ )
85
+
86
+ Object.keys(fieldMap).forEach(key =>{
87
+ this.dispatchEvent(
88
+ new CustomEvent('field-change', {
89
+ bubbles: true,
90
+ composed: true,
91
+ detail: {
92
+ before: this.record[fieldMap[key]],
93
+ after: selected
94
+ ? selected[key]
95
+ : null,
96
+ record: this.record,
97
+ column: {name: fieldMap[key]},
98
+ row: this.row
99
+ }
100
+ })
101
+ )
102
+ })
103
+ }
104
+
105
+ var template = html`
106
+ <meta-object-selector-popup
107
+ .value=${this.value}
108
+ .options=${this.column.record.options}
109
+ .record=${this.record}
110
+ .confirmCallback=${confirmCallback.bind(this)}
111
+ ></meta-object-selector-popup>
112
+ `
113
+
114
+ this.popup = openPopup(template, {
115
+ backdrop: true,
116
+ size: 'large',
117
+ title: TermsUtil.tMenu(selectorName)
118
+ })
119
+ }
120
+ }
121
+
122
+ customElements.define('grist-editor-meta-object-selector', GristEditorMetaObjectSelector)
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 그리드 Resource-column 타입 셀렉터
3
+ * @auth yang
4
+ */
5
+ import { html } from 'lit'
6
+
7
+ export const GristRendererCodeInput = (value, column, record, rowIndex, field) => {
8
+ let text = ''
9
+
10
+ if (value) {
11
+ if (typeof value === 'object') {
12
+ text = JSON.stringify(value, 0, 2)
13
+ } else {
14
+ text = value
15
+ }
16
+ text = text.length > 20 ? `${text.substring(0, 20)}...` : text
17
+ }
18
+
19
+ return html`<span style="flex:1" data-reactive-tooltip>${text}</span>`
20
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 그리드 Resource-column 타입 셀렉터
3
+ * @auth yang
4
+ */
5
+ import { html } from 'lit'
6
+
7
+ export const GristRendererMetaCodeSelector = (value, column, record, rowIndex, field) => {
8
+ let text = ''
9
+
10
+ if (!column.record || !column.record.options) {
11
+ text = ''
12
+ } else if (!column.record.options.dispField) {
13
+ text = value
14
+ } else {
15
+ if (!column.record.options.codes) column.record.options.codes = []
16
+
17
+ if (value && value.length > 0) {
18
+ let codeDisp = column.record.options.codes.filter(x => x.value === value)
19
+
20
+ if (codeDisp && codeDisp.length > 0) {
21
+ text = codeDisp[0].display
22
+ } else {
23
+ text = value
24
+ }
25
+ }
26
+ }
27
+ return html`<span data-reactive-tooltip>${text}</span>`
28
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 그리드 Resource-column 타입 셀렉터
3
+ * @auth yang
4
+ */
5
+ import { html } from 'lit'
6
+
7
+ export const GristRendererMetaObjectSelector = (value, column, record, rowIndex, field) => {
8
+ let text = ''
9
+
10
+ if (value && column.record.options?.nameField) {
11
+ let fields = column.record.options.nameField.split(',')
12
+ text = value[fields[0]]
13
+
14
+ if (fields.length > 1) {
15
+ text += `(${fields
16
+ .splice(1)
17
+ .map(field => {
18
+ return value[field]
19
+ })
20
+ .join(',')})`
21
+ }
22
+ }
23
+
24
+ return html`<span data-reactive-tooltip>${text}</span>`
25
+ }
@@ -0,0 +1,111 @@
1
+ import '@material/web/icon/icon.js'
2
+
3
+ import { css, html, LitElement } from 'lit'
4
+ import { CommonHeaderStyles } from '@operato/styles'
5
+ import { TermsUtil } from '../../utils/terms-util'
6
+ import { MetaApi } from '../../utils/meta-api'
7
+ import '@operato/input/ox-input-code.js'
8
+ import { closePopup } from '@operato/popup'
9
+
10
+ /**
11
+ * 코드 편집기 팝업
12
+ */
13
+ export class CodeInputEditorPopup extends LitElement {
14
+ static styles = [
15
+ CommonHeaderStyles,
16
+ css`
17
+ :host {
18
+ display: flex;
19
+ flex-direction: column;
20
+
21
+ background-color: var(--md-sys-color-surface);
22
+
23
+ width: var(--overlay-center-normal-width, 50%);
24
+ height: var(--overlay-center-normal-height, 50%);
25
+ }
26
+
27
+ ox-input-code {
28
+ margin: 10px;
29
+ overflow-y: auto;
30
+ flex: 1;
31
+ }
32
+ `
33
+ ]
34
+
35
+ async connectedCallback() {
36
+ if (typeof this.value === 'object') {
37
+ this.codeVlaue = JSON.stringify(this.value, 0, 2)
38
+ } else {
39
+ this.codeVlaue = this.value
40
+ }
41
+
42
+ await super.connectedCallback()
43
+ }
44
+
45
+ async firstUpdated() {
46
+ await super.firstUpdated()
47
+ }
48
+
49
+ render() {
50
+ return html`
51
+ <ox-input-code mode="javascript" value=${this.codeVlaue}></ox-input-code>
52
+
53
+ <div class="footer">
54
+ <button @click=${this.clickEmpty.bind(this)}>
55
+ <md-icon>check_box_outline_blank</md-icon>${TermsUtil.tButton('empty')}
56
+ </button>
57
+ <div filler></div>
58
+ <button @click=${this.clickCancel.bind(this)}><md-icon>cancel</md-icon>${TermsUtil.tButton('cancel')}</button>
59
+ <button @click=${this.clickConfirm.bind(this)} done>
60
+ <md-icon>done</md-icon>${TermsUtil.tButton('confirm')}
61
+ </button>
62
+ </div>
63
+ `
64
+ }
65
+
66
+ get codeEditor() {
67
+ return this.shadowRoot.querySelector('ox-input-code')
68
+ }
69
+
70
+ /**
71
+ * @description 비우기
72
+ ***************************
73
+ * @returns
74
+ */
75
+ async clickEmpty(e) {
76
+ this.confirmCallback && this.confirmCallback(null)
77
+ closePopup(this)
78
+ }
79
+ /**
80
+ * @description 취소
81
+ ***************************
82
+ * @returns
83
+ */
84
+ async clickCancel(e) {
85
+ closePopup(this)
86
+ }
87
+ /**
88
+ * @description 확인
89
+ ***************************
90
+ * @returns
91
+ */
92
+ async clickConfirm(e) {
93
+ if (this.codeVlaue === this.codeEditor.value) {
94
+ MetaApi.showToast('info', TermsUtil.tText('NOTHING_CHANGED'))
95
+ return
96
+ }
97
+ this.changedValue(this.codeEditor.value)
98
+ }
99
+
100
+ /**
101
+ * @description 확정
102
+ ***************************
103
+ * @param {*} record
104
+ */
105
+ async changedValue(value) {
106
+ this.confirmCallback && this.confirmCallback(value)
107
+ closePopup(this)
108
+ }
109
+ }
110
+
111
+ customElements.define('code-input-editor-popup', CodeInputEditorPopup)
@@ -0,0 +1,129 @@
1
+ import '@material/web/icon/icon.js'
2
+
3
+ import { client, gqlContext } from '@things-factory/shell'
4
+ import { css, html, LitElement } from 'lit'
5
+ import { SingleColumnFormStyles } from '@things-factory/form-ui'
6
+ import { CommonHeaderStyles } from '@operato/styles'
7
+ import gql from 'graphql-tag'
8
+ import { TermsUtil } from '../../utils/terms-util'
9
+ import { ServiceUtil } from '../../utils/service-util'
10
+ import { MetaApi } from '../../utils/meta-api'
11
+
12
+ class FileUploadPopup extends LitElement {
13
+ static get styles() {
14
+ return [
15
+ CommonHeaderStyles,
16
+ SingleColumnFormStyles,
17
+ css`
18
+ :host {
19
+ padding: 10px;
20
+ display: flex;
21
+ flex-direction: column;
22
+ overflow-x: overlay;
23
+ background-color: var(--md-sys-color-background);
24
+ }
25
+
26
+ .input-container {
27
+ display: flex;
28
+ }
29
+ `
30
+ ]
31
+ }
32
+
33
+ static get properties() {
34
+ return {
35
+ templateTypes: Array
36
+ }
37
+ }
38
+
39
+ async connectedCallback() {
40
+ super.connectedCallback()
41
+ this.templateTypes = await ServiceUtil.codeItems('TEMPLATE_TYPES')
42
+ }
43
+
44
+ render() {
45
+ return html`
46
+ <div>
47
+ <form id="input-form" class="single-column-form">
48
+ <fieldset>
49
+ <legend>${TermsUtil.tLabel('file_upload')}</legend>
50
+ <label>${TermsUtil.tLabel('file_upload')}</label>
51
+ <file-uploader custom-input id="uploadTemplate" name="attachments"></file-uploader>
52
+
53
+ <label>${TermsUtil.tLabel('category')}</label>
54
+ <select name="category" required>
55
+ <option value="">${TermsUtil.tText('please_select_upload_category')}</option>
56
+ ${(this.templateTypes || []).map(templateType => {
57
+ const { name, description } = templateType
58
+ return html` <option value="${name}">${name} ${description ? ` (${description})` : ''}</option> `
59
+ })}
60
+ </select>
61
+
62
+ <label>${TermsUtil.tLabel('description')}</label>
63
+ <input name="description" />
64
+ </fieldset>
65
+ </form>
66
+ </div>
67
+
68
+ <div class="footer">
69
+ <div filler></div>
70
+ <button @click=${this._createAttachment} done>
71
+ <md-icon>attach_file_add</md-icon>${TermsUtil.tButton('create')}
72
+ </button>
73
+ </div>
74
+ `
75
+ }
76
+
77
+ get _template() {
78
+ return this.renderRoot.querySelector('#uploadTemplate')
79
+ }
80
+
81
+ async _createAttachment() {
82
+ try {
83
+ const attachment = this._getAttachmentInfo()
84
+ const response = await client.mutate({
85
+ mutation: gql`
86
+ mutation ($attachment: NewAttachment!) {
87
+ createAttachment(attachment: $attachment) {
88
+ id
89
+ name
90
+ path
91
+ }
92
+ }
93
+ `,
94
+ variables: {
95
+ attachment
96
+ },
97
+ context: {
98
+ ...gqlContext(),
99
+ hasUpload: true
100
+ }
101
+ })
102
+
103
+ if (!response.errors) {
104
+ history.back()
105
+ this.dispatchEvent(new CustomEvent('template-uploaded', { bubbles: true, composed: true, cancelable: true }))
106
+ }
107
+ } catch (e) {
108
+ MetaApi.showAlertPopup('label.error', e.message, 'error', 'confirm')
109
+ }
110
+ }
111
+
112
+ _getAttachmentInfo() {
113
+ if (this.renderRoot.querySelector('form').checkValidity()) {
114
+ return {
115
+ file: this._template.files[0],
116
+ category: this._getInputByName('category').value,
117
+ description: this._getInputByName('description').value
118
+ }
119
+ } else {
120
+ throw new Error(TermsUtil.tText('text.attachment_info_not_valid'))
121
+ }
122
+ }
123
+
124
+ _getInputByName(name) {
125
+ return this.renderRoot.querySelector(`select[name=${name}], input[name=${name}]`)
126
+ }
127
+ }
128
+
129
+ window.customElements.define('file-upload-popup', FileUploadPopup)