@dssp/supervision 0.0.32 → 0.0.34

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 (65) hide show
  1. package/client/pages/building-inspection/building-inspection-detail-checklist.ts +2 -1
  2. package/client/pages/building-inspection/component/inspection-event-provider.ts +1 -1
  3. package/client/pages/checklist/attachment-list-popup.ts +283 -0
  4. package/client/pages/checklist/checklist-view.ts +88 -7
  5. package/client/pages/checklist/comment-list-popup.ts +319 -0
  6. package/client/pages/checklist/file-preview-popup.ts +70 -0
  7. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js +2 -1
  8. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js.map +1 -1
  9. package/dist-client/pages/building-inspection/component/inspection-event-provider.js +1 -1
  10. package/dist-client/pages/building-inspection/component/inspection-event-provider.js.map +1 -1
  11. package/dist-client/pages/checklist/attachment-list-popup.d.ts +2 -0
  12. package/dist-client/pages/checklist/attachment-list-popup.js +290 -0
  13. package/dist-client/pages/checklist/attachment-list-popup.js.map +1 -0
  14. package/dist-client/pages/checklist/checklist-view.d.ts +2 -0
  15. package/dist-client/pages/checklist/checklist-view.js +78 -7
  16. package/dist-client/pages/checklist/checklist-view.js.map +1 -1
  17. package/dist-client/pages/checklist/comment-list-popup.d.ts +1 -0
  18. package/dist-client/pages/checklist/comment-list-popup.js +344 -0
  19. package/dist-client/pages/checklist/comment-list-popup.js.map +1 -0
  20. package/dist-client/pages/checklist/file-preview-popup.d.ts +1 -0
  21. package/dist-client/pages/checklist/file-preview-popup.js +78 -0
  22. package/dist-client/pages/checklist/file-preview-popup.js.map +1 -0
  23. package/dist-client/tsconfig.tsbuildinfo +1 -1
  24. package/dist-server/service/checklist-item/checklist-item-query.d.ts +6 -0
  25. package/dist-server/service/checklist-item/checklist-item-query.js +55 -0
  26. package/dist-server/service/checklist-item/checklist-item-query.js.map +1 -1
  27. package/dist-server/service/checklist-item/checklist-item.d.ts +2 -1
  28. package/dist-server/service/checklist-item/checklist-item.js +5 -4
  29. package/dist-server/service/checklist-item/checklist-item.js.map +1 -1
  30. package/dist-server/service/checklist-item-comment/checklist-item-comment-history.d.ts +16 -0
  31. package/dist-server/service/checklist-item-comment/checklist-item-comment-history.js +83 -0
  32. package/dist-server/service/checklist-item-comment/checklist-item-comment-history.js.map +1 -0
  33. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.d.ts +7 -0
  34. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.js +69 -0
  35. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.js.map +1 -0
  36. package/dist-server/service/checklist-item-comment/checklist-item-comment-query.d.ts +7 -0
  37. package/dist-server/service/checklist-item-comment/checklist-item-comment-query.js +49 -0
  38. package/dist-server/service/checklist-item-comment/checklist-item-comment-query.js.map +1 -0
  39. package/dist-server/service/checklist-item-comment/checklist-item-comment-type.d.ts +14 -0
  40. package/dist-server/service/checklist-item-comment/checklist-item-comment-type.js +53 -0
  41. package/dist-server/service/checklist-item-comment/checklist-item-comment-type.js.map +1 -0
  42. package/dist-server/service/checklist-item-comment/checklist-item-comment.d.ts +12 -0
  43. package/dist-server/service/checklist-item-comment/checklist-item-comment.js +57 -0
  44. package/dist-server/service/checklist-item-comment/checklist-item-comment.js.map +1 -0
  45. package/dist-server/service/checklist-item-comment/event-subscriber.d.ts +7 -0
  46. package/dist-server/service/checklist-item-comment/event-subscriber.js +21 -0
  47. package/dist-server/service/checklist-item-comment/event-subscriber.js.map +1 -0
  48. package/dist-server/service/checklist-item-comment/index.d.ts +7 -0
  49. package/dist-server/service/checklist-item-comment/index.js +12 -0
  50. package/dist-server/service/checklist-item-comment/index.js.map +1 -0
  51. package/dist-server/service/index.d.ts +2 -1
  52. package/dist-server/service/index.js +6 -1
  53. package/dist-server/service/index.js.map +1 -1
  54. package/dist-server/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +5 -5
  56. package/server/service/checklist-item/checklist-item-query.ts +34 -0
  57. package/server/service/checklist-item/checklist-item.ts +6 -3
  58. package/server/service/checklist-item-comment/checklist-item-comment-history.ts +69 -0
  59. package/server/service/checklist-item-comment/checklist-item-comment-mutation.ts +60 -0
  60. package/server/service/checklist-item-comment/checklist-item-comment-query.ts +36 -0
  61. package/server/service/checklist-item-comment/checklist-item-comment-type.ts +32 -0
  62. package/server/service/checklist-item-comment/checklist-item-comment.ts +56 -0
  63. package/server/service/checklist-item-comment/event-subscriber.ts +17 -0
  64. package/server/service/checklist-item-comment/index.ts +9 -0
  65. package/server/service/index.ts +10 -1
@@ -141,7 +141,8 @@ export class BuildingInspectionDetailChecklist extends PageView {
141
141
  inspctionCriteria
142
142
  constructionConfirmStatus
143
143
  supervisoryConfirmStatus
144
- comment
144
+ checklistItemCommentCount
145
+ checklistItemAttachmentCount
145
146
  }
146
147
  }
147
148
  buildingLevel {
@@ -43,7 +43,7 @@ export class InspectionEventProvider implements EventProvider {
43
43
  const calendarData = this.getCalendarTemplate(response.data?.buildingInspectionDateSummaryOfLevelAndPeriod)
44
44
 
45
45
  calendar.forEach(({ date }) => {
46
- const formattedDate = date.toISOString().split('T')[0]
46
+ const formattedDate = date.toLocaleDateString('en-CA') // 'en-CA'는 'YYYY-MM-DD' 형식으로 반환됩니다.
47
47
  const template = calendarData[formattedDate]
48
48
 
49
49
  if (!template) return
@@ -0,0 +1,283 @@
1
+ import '@material/web/icon/icon.js'
2
+ import gql from 'graphql-tag'
3
+ import { client } from '@operato/graphql'
4
+ import { css, html, LitElement } from 'lit'
5
+ import { customElement, property, query, state } from 'lit/decorators.js'
6
+ import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'
7
+ import { notify } from '@operato/layout'
8
+ import { store, User } from '@operato/shell'
9
+ import { connect } from 'pwa-helpers/connect-mixin.js'
10
+ import { OxPrompt } from '@operato/popup/ox-prompt.js'
11
+ import { openPopup } from '@operato/layout'
12
+ import './file-preview-popup'
13
+
14
+ @customElement('attachment-list-popup')
15
+ class AttachmentListPopup extends connect(store)(LitElement) {
16
+ static styles = [
17
+ ButtonContainerStyles,
18
+ ScrollbarStyles,
19
+ css`
20
+ :host {
21
+ display: flex;
22
+ flex-direction: column;
23
+ padding: 15px 20px;
24
+ background-color: var(--md-sys-color-surface);
25
+ }
26
+
27
+ div[body] {
28
+ height: 100%;
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: 12px;
32
+ }
33
+
34
+ div[attachment-container] {
35
+ overflow-y: auto;
36
+ gap: 10px;
37
+ display: flex;
38
+ flex-direction: column;
39
+ flex: 1;
40
+
41
+ div[attachment-row] {
42
+ display: flex;
43
+ flex-direction: column;
44
+
45
+ div[creator-container] {
46
+ display: flex;
47
+ justify-content: space-between;
48
+
49
+ span[creator] {
50
+ font-weight: 600;
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 3px;
54
+ }
55
+ span[createdAt] {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 3px;
59
+
60
+ md-icon[delete] {
61
+ cursor: pointer;
62
+ }
63
+
64
+ a[button-download] {
65
+ display: flex;
66
+ color: #000;
67
+ }
68
+ }
69
+ }
70
+
71
+ a[attachment] {
72
+ margin-left: 20px;
73
+ text-decoration: none;
74
+ color: #000;
75
+ }
76
+ }
77
+ }
78
+
79
+ h3 {
80
+ position: relative;
81
+ color: rgb(5, 149, 229);
82
+ font-size: 17px;
83
+ font-weight: 700;
84
+ background-color: var(--md-sys-color-surface);
85
+ margin-top: 0px;
86
+ margin-bottom: 5px;
87
+ }
88
+
89
+ div[button-container] {
90
+ display: flex;
91
+ justify-content: flex-end;
92
+ gap: 10px;
93
+ }
94
+ `
95
+ ]
96
+
97
+ @property({ type: String }) checklistItemId: string = ''
98
+
99
+ @state() item: any = { count: 0 }
100
+ @state() checklistItemAttachments: any = []
101
+ @state() checklistItemAttachmentCount: number = 0
102
+ @state() user: User = {}
103
+ @query('div[attachment-container]') attachmentContainer!: HTMLDivElement
104
+
105
+ render() {
106
+ return html`
107
+ <div body>
108
+ <h3>제품검사에 대한 파일: ${this.checklistItemAttachmentCount || 0}건</h3>
109
+
110
+ <div attachment-container>
111
+ ${this.checklistItemAttachments.reverse().map(attachment => {
112
+ return html`
113
+ <div attachment-row>
114
+ <div creator-container>
115
+ <span creator><md-icon slot="icon">account_circle</md-icon> ${attachment.creator.name}</span>
116
+ <span createdAt>
117
+ <md-icon slot="icon">schedule</md-icon> ${this._formatDate(attachment.createdAt)}
118
+ ${attachment.creator.email === this.user.email
119
+ ? html` <md-icon delete slot="icon" @click=${() => this._deleteAttachment(attachment.id)}>delete</md-icon>`
120
+ : ''}
121
+ <a button-download href=${attachment.fullpath} download=${attachment.name}>
122
+ <md-icon slot="icon">download</md-icon></a
123
+ >
124
+ </span>
125
+ </div>
126
+ <a attachment @click=${() => this._onClickPreview(attachment.fullpath)}>${attachment.name}</a>
127
+ </div>
128
+ `
129
+ })}
130
+ </div>
131
+
132
+ <ox-input-file accept="*/*" multiple="true" hide-filelist @change=${this.onCreateAttachment.bind(this)}></ox-input-file>
133
+
134
+ <div button-container>
135
+ <md-elevated-button @click=${this._close}> <md-icon slot="icon">cancel</md-icon>취소 </md-elevated-button>
136
+ </div>
137
+ </div>
138
+ `
139
+ }
140
+
141
+ async firstUpdated() {
142
+ this.user = (store.getState() as any).auth?.user
143
+
144
+ await this._loadAttachments()
145
+ }
146
+
147
+ private async _loadAttachments() {
148
+ const response = await client.query({
149
+ query: gql`
150
+ query ChecklistItem($id: String!) {
151
+ checklistItem(id: $id) {
152
+ id
153
+ checklistItemAttachmentCount
154
+ checklistItemAttachments {
155
+ id
156
+ name
157
+ fullpath
158
+ creator {
159
+ id
160
+ name
161
+ email
162
+ }
163
+ createdAt
164
+ }
165
+ }
166
+ }
167
+ `,
168
+ variables: {
169
+ id: this.checklistItemId
170
+ }
171
+ })
172
+
173
+ if (response.errors) return
174
+
175
+ this.checklistItemAttachments = response.data.checklistItem.checklistItemAttachments || []
176
+ this.checklistItemAttachmentCount = response.data.checklistItem.checklistItemAttachmentCount
177
+ }
178
+
179
+ private async _deleteAttachment(attachmentId: string) {
180
+ if (
181
+ await OxPrompt.open({
182
+ title: '첨부 자료를 삭제',
183
+ text: '첨부 자료를 삭제 하시겠습니까?',
184
+ confirmButton: { text: '삭제' },
185
+ cancelButton: { text: '취소' }
186
+ })
187
+ ) {
188
+ const response = await client.mutate({
189
+ mutation: gql`
190
+ mutation DeleteAttachment($deleteAttachmentId: String!) {
191
+ deleteAttachment(id: $deleteAttachmentId)
192
+ }
193
+ `,
194
+ variables: {
195
+ deleteAttachmentId: attachmentId
196
+ }
197
+ })
198
+
199
+ if (!response.errors) {
200
+ this.checklistItemAttachments = [...this.checklistItemAttachments.filter(attachment => attachment.id != attachmentId)]
201
+ notify({ message: '첨부 자료를 삭제하였습니다.', level: 'info' })
202
+ } else {
203
+ notify({ message: response.errors?.[0]?.message || '첨부 자료 삭제에 실패하였습니다.', level: 'error' })
204
+ }
205
+
206
+ this._dispatchEvent()
207
+ }
208
+ }
209
+
210
+ private _close() {
211
+ history.back()
212
+ }
213
+
214
+ // 파일 변경 시 파일을 저장할 핸들러
215
+ private async onCreateAttachment(e: CustomEvent) {
216
+ const files = e.detail
217
+
218
+ await this._createAttachments(files)
219
+
220
+ this._dispatchEvent()
221
+ }
222
+
223
+ async _createAttachments(files: File[]) {
224
+ const checklistItemId = this.checklistItemId
225
+
226
+ const response = await client.mutate({
227
+ mutation: gql`
228
+ mutation ($attachments: [NewAttachment!]!) {
229
+ createAttachments(attachments: $attachments) {
230
+ id
231
+ name
232
+ fullpath
233
+ creator {
234
+ id
235
+ name
236
+ email
237
+ }
238
+ createdAt
239
+ }
240
+ }
241
+ `,
242
+ variables: {
243
+ attachments: files.map(file => {
244
+ return { file, refBy: checklistItemId, refType: 'ChecklistItem' }
245
+ })
246
+ },
247
+ context: {
248
+ hasUpload: true
249
+ }
250
+ })
251
+
252
+ const attachments = response.data.createAttachments
253
+
254
+ this.checklistItemAttachments = [...this.checklistItemAttachments, ...attachments]
255
+ this.checklistItemAttachmentCount = this.checklistItemAttachmentCount + attachments.length
256
+ }
257
+
258
+ private _formatDate(date) {
259
+ const _date = new Date(date.toLocaleString('en-US', { timeZone: 'Asia/Seoul' }))
260
+
261
+ const year = _date.getFullYear()
262
+ const month = String(_date.getMonth() + 1).padStart(2, '0')
263
+ const day = String(_date.getDate()).padStart(2, '0')
264
+ const hours = String(_date.getHours()).padStart(2, '0')
265
+ const minutes = String(_date.getMinutes()).padStart(2, '0')
266
+ const seconds = String(_date.getSeconds()).padStart(2, '0')
267
+
268
+ return `${year}.${month}.${day} ${hours}:${minutes}:${seconds}`
269
+ }
270
+
271
+ // 첨부 자료 변경 이벤트 디스패치
272
+ _dispatchEvent() {
273
+ this.dispatchEvent(new CustomEvent('change-attachment', { detail: { checklistItemId: this.checklistItemId } }))
274
+ }
275
+
276
+ private _onClickPreview(filepath: string) {
277
+ openPopup(html` <file-preview-popup .filepath=${filepath}></file-preview-popup> `, {
278
+ backdrop: true,
279
+ size: 'large',
280
+ title: '미리보기'
281
+ })
282
+ }
283
+ }
@@ -1,4 +1,6 @@
1
1
  import '@material/web/icon/icon.js'
2
+ import gql from 'graphql-tag'
3
+ import { client } from '@operato/graphql'
2
4
  import { css, html, LitElement } from 'lit'
3
5
  import { customElement, property } from 'lit/decorators.js'
4
6
  import { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'
@@ -8,9 +10,11 @@ import {
8
10
  BUILDING_INSPECTION_STATUS_DISPLAY
9
11
  } from '../building-inspection/building-inspection-list'
10
12
  import '@operato/input/ox-input-signature.js'
11
- // import { BuildingComplex } from '@dssp/building-complex'
12
13
  import { store } from '@operato/shell'
13
14
  import { connect } from 'pwa-helpers/connect-mixin.js'
15
+ import { openPopup } from '@operato/layout'
16
+ import './comment-list-popup'
17
+ import './attachment-list-popup'
14
18
 
15
19
  export const enum ChecklistMode {
16
20
  VIEWER = 'VIEWER',
@@ -56,6 +60,7 @@ class ChecklistView extends connect(store)(LitElement) {
56
60
  th {
57
61
  border: 1px #999999 solid;
58
62
  padding-inline: 8px;
63
+ vertical-align: middle;
59
64
  }
60
65
  th {
61
66
  background-color: #efefef;
@@ -65,12 +70,8 @@ class ChecklistView extends connect(store)(LitElement) {
65
70
  height: 35px;
66
71
  &[radio] {
67
72
  text-align: center;
68
- vertical-align: middle;
69
73
  width: 55px;
70
74
  }
71
- &[attachment] {
72
- width: 90px;
73
- }
74
75
  }
75
76
  }
76
77
 
@@ -117,6 +118,23 @@ class ChecklistView extends connect(store)(LitElement) {
117
118
  text-align: center;
118
119
  word-break: keep-all;
119
120
  }
121
+
122
+ &[attachment] {
123
+ text-align: center;
124
+ cursor: pointer;
125
+
126
+ * {
127
+ vertical-align: middle;
128
+ }
129
+ }
130
+ &[comment] {
131
+ cursor: pointer;
132
+ text-align: center;
133
+
134
+ * {
135
+ vertical-align: middle;
136
+ }
137
+ }
120
138
  }
121
139
  }
122
140
 
@@ -331,8 +349,14 @@ class ChecklistView extends connect(store)(LitElement) {
331
349
  @change=${this._onChangeConfirmStatus}
332
350
  ></md-radio>
333
351
  </td>
334
- <td attachment></td>
335
- <td></td>
352
+ <td attachment @click=${() => this._onClickAttachment(item.id)}>
353
+ <md-icon slot="icon">attach_file</md-icon>
354
+ <span>${item?.checklistItemAttachmentCount || ''}</span>
355
+ </td>
356
+ <td comment @click=${() => this._onClickComment(item.id)}>
357
+ <md-icon slot="icon">chat</md-icon>
358
+ <span>${item?.checklistItemCommentCount || ''}</span>
359
+ </td>
336
360
  </tr>`
337
361
  })}
338
362
  </tbody>
@@ -486,4 +510,61 @@ class ChecklistView extends connect(store)(LitElement) {
486
510
  }
487
511
  })
488
512
  }
513
+
514
+ private _onClickComment(checklistItemId: string) {
515
+ openPopup(
516
+ html`
517
+ <comment-list-popup
518
+ .checklistItemId=${checklistItemId}
519
+ @change-comment=${this._refreshItem.bind(this)}
520
+ ></comment-list-popup>
521
+ `,
522
+ {
523
+ backdrop: true,
524
+ size: 'medium',
525
+ title: '조치 사항'
526
+ }
527
+ )
528
+ }
529
+
530
+ private _onClickAttachment(checklistItemId: string) {
531
+ openPopup(
532
+ html`
533
+ <attachment-list-popup
534
+ .checklistItemId=${checklistItemId}
535
+ @change-attachment=${this._refreshItem.bind(this)}
536
+ ></attachment-list-popup>
537
+ `,
538
+ {
539
+ backdrop: true,
540
+ size: 'medium',
541
+ title: '첨부 자료'
542
+ }
543
+ )
544
+ }
545
+
546
+ private async _refreshItem(e) {
547
+ const { checklistItemId } = e.detail
548
+ const response = await client.query({
549
+ query: gql`
550
+ query ChecklistItem($checklistItemId: String!) {
551
+ checklistItem(id: $checklistItemId) {
552
+ id
553
+ checklistItemCommentCount
554
+ checklistItemAttachmentCount
555
+ }
556
+ }
557
+ `,
558
+ variables: {
559
+ checklistItemId: checklistItemId
560
+ }
561
+ })
562
+
563
+ const checklistItem = response.data?.checklistItem || []
564
+ this.checklist.checklistItems = this.checklist.checklistItems.map(item => {
565
+ return item.id != checklistItemId ? item : { ...item, ...checklistItem }
566
+ })
567
+
568
+ this.requestUpdate()
569
+ }
489
570
  }