@dssp/project 0.0.36 → 1.0.0-alpha.1

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 (100) hide show
  1. package/dist-client/pages/project/project-schedule.js +31 -22
  2. package/dist-client/pages/project/project-schedule.js.map +1 -1
  3. package/dist-client/tsconfig.tsbuildinfo +1 -1
  4. package/dist-server/tsconfig.tsbuildinfo +1 -1
  5. package/package.json +11 -11
  6. package/client/bootstrap.ts +0 -0
  7. package/client/index.ts +0 -0
  8. package/client/pages/lib/select2-component.ts +0 -175
  9. package/client/pages/lib/waether.ts +0 -159
  10. package/client/pages/project/component/project-update-header.ts +0 -88
  11. package/client/pages/project/popup/popup-plan-upload.ts +0 -138
  12. package/client/pages/project/popup/popup-project-create.ts +0 -147
  13. package/client/pages/project/popup/popup-schedule-upload.ts +0 -102
  14. package/client/pages/project/project-completed-list.ts +0 -281
  15. package/client/pages/project/project-detail.ts +0 -738
  16. package/client/pages/project/project-list.ts +0 -418
  17. package/client/pages/project/project-plan-management.ts +0 -476
  18. package/client/pages/project/project-schedule-list.ts +0 -294
  19. package/client/pages/project/project-schedule.ts +0 -393
  20. package/client/pages/project/project-setting-list.ts +0 -393
  21. package/client/pages/project/project-update.ts +0 -876
  22. package/client/pages/resource/construction-detail-type-popup.ts +0 -201
  23. package/client/pages/resource/construction-type-management.ts +0 -212
  24. package/client/pages/resource/inspection-drawing-type-management.ts +0 -245
  25. package/client/pages/resource/inspection-part-popup.ts +0 -201
  26. package/client/pages/resource/resource-importer.ts +0 -97
  27. package/client/pages/resource/resource-list-page.ts +0 -356
  28. package/client/pages/resource/worker-type-management.ts +0 -192
  29. package/client/pages/task/task-importer.ts +0 -94
  30. package/client/pages/task/task-list-page.ts +0 -340
  31. package/client/pages/task-resource/task-resource-importer.ts +0 -97
  32. package/client/pages/task-resource/task-resource-list-page.ts +0 -356
  33. package/client/route.ts +0 -55
  34. package/client/tsconfig.json +0 -11
  35. package/server/controllers/export-tasks.ts +0 -40
  36. package/server/controllers/import-task.ts +0 -134
  37. package/server/controllers/index.ts +0 -0
  38. package/server/controllers/parse-excel.ts +0 -86
  39. package/server/controllers/types.ts +0 -20
  40. package/server/index.ts +0 -4
  41. package/server/middlewares/index.ts +0 -3
  42. package/server/migrations/1723861466413-seed-roles.ts +0 -128
  43. package/server/migrations/1723861466414-seed-codes.ts +0 -157
  44. package/server/migrations/1723861476419-seed-resources.ts +0 -62
  45. package/server/migrations/1723861478420-seed-/bsample-project.ts +0 -87
  46. package/server/migrations/1723861478421-seed-/bsample-tasks.ts +0 -194
  47. package/server/migrations/index.ts +0 -9
  48. package/server/routes.ts +0 -108
  49. package/server/service/construction-detail-type/construction-detail-type-mutation.ts +0 -57
  50. package/server/service/construction-detail-type/construction-detail-type-query.ts +0 -31
  51. package/server/service/construction-detail-type/construction-detail-type-type.ts +0 -26
  52. package/server/service/construction-detail-type/construction-detail-type.ts +0 -52
  53. package/server/service/construction-detail-type/index.ts +0 -6
  54. package/server/service/construction-type/construction-type-mutation.ts +0 -66
  55. package/server/service/construction-type/construction-type-query.ts +0 -56
  56. package/server/service/construction-type/construction-type-type.ts +0 -26
  57. package/server/service/construction-type/construction-type.ts +0 -74
  58. package/server/service/construction-type/index.ts +0 -6
  59. package/server/service/index.ts +0 -56
  60. package/server/service/inspection-drawing-type/index.ts +0 -6
  61. package/server/service/inspection-drawing-type/inspection-drawing-type-mutation.ts +0 -69
  62. package/server/service/inspection-drawing-type/inspection-drawing-type-query.ts +0 -55
  63. package/server/service/inspection-drawing-type/inspection-drawing-type-type.ts +0 -23
  64. package/server/service/inspection-drawing-type/inspection-drawing-type.ts +0 -68
  65. package/server/service/inspection-part/index.ts +0 -6
  66. package/server/service/inspection-part/inspection-part-mutation.ts +0 -52
  67. package/server/service/inspection-part/inspection-part-query.ts +0 -41
  68. package/server/service/inspection-part/inspection-part-type.ts +0 -26
  69. package/server/service/inspection-part/inspection-part.ts +0 -51
  70. package/server/service/manager/index.ts +0 -6
  71. package/server/service/manager/manager-mutation.ts +0 -42
  72. package/server/service/manager/manager-query.ts +0 -28
  73. package/server/service/manager/manager-type.ts +0 -40
  74. package/server/service/manager/manager.ts +0 -29
  75. package/server/service/project/index.ts +0 -6
  76. package/server/service/project/project-mutation.ts +0 -255
  77. package/server/service/project/project-query.ts +0 -105
  78. package/server/service/project/project-type.ts +0 -72
  79. package/server/service/project/project.ts +0 -134
  80. package/server/service/resource/index.ts +0 -7
  81. package/server/service/resource/resource-mutation.ts +0 -137
  82. package/server/service/resource/resource-query.ts +0 -50
  83. package/server/service/resource/resource-type.ts +0 -41
  84. package/server/service/resource/resource.ts +0 -82
  85. package/server/service/task/index.ts +0 -6
  86. package/server/service/task/task-mutation.ts +0 -135
  87. package/server/service/task/task-query.ts +0 -169
  88. package/server/service/task/task-type.ts +0 -75
  89. package/server/service/task/task.ts +0 -130
  90. package/server/service/task-resource/index.ts +0 -7
  91. package/server/service/task-resource/task-resource-mutation.ts +0 -140
  92. package/server/service/task-resource/task-resource-query.ts +0 -36
  93. package/server/service/task-resource/task-resource-type.ts +0 -41
  94. package/server/service/task-resource/task-resource.ts +0 -51
  95. package/server/service/worker-type/index.ts +0 -6
  96. package/server/service/worker-type/worker-type-mutation.ts +0 -66
  97. package/server/service/worker-type/worker-type-query.ts +0 -47
  98. package/server/service/worker-type/worker-type-type.ts +0 -26
  99. package/server/service/worker-type/worker-type.ts +0 -68
  100. package/server/tsconfig.json +0 -10
@@ -1,876 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
- import '@material/web/button/elevated-button.js'
3
- import '@material/web/textfield/outlined-text-field.js'
4
-
5
- import { PageView } from '@operato/shell'
6
- import { PageLifecycle } from '@operato/shell/dist/src/app/pages/page-view'
7
- import { css, html } from 'lit'
8
- import { customElement, state } from 'lit/decorators.js'
9
- import { ScopedElementsMixin } from '@open-wc/scoped-elements'
10
- import { client } from '@operato/graphql'
11
- import { notify } from '@operato/layout'
12
- import gql from 'graphql-tag'
13
- import { Project } from './project-list'
14
- import '../lib/select2-component'
15
- import './component/project-update-header'
16
-
17
- @customElement('project-update')
18
- export class ProjectUpdate extends ScopedElementsMixin(PageView) {
19
- static styles = [
20
- css`
21
- :host {
22
- display: grid;
23
- grid-template-rows: 55px auto;
24
- color: #4e5055;
25
-
26
- width: 100%;
27
- background-color: var(--md-sys-color-background, #f6f6f6);
28
- overflow-y: auto;
29
-
30
- --grid-record-emphasized-background-color: red;
31
- --grid-record-emphasized-color: yellow;
32
- }
33
-
34
- md-outlined-text-field {
35
- width: 100%;
36
-
37
- --md-outlined-text-field-container-shape: 5px;
38
- --md-outlined-text-field-outline-color: rgba(51,51,51,.20);
39
- --md-outlined-text-field-focus-outline-color: #1f7fd9;
40
- --md-outlined-text-field-focus-outline-width: 1px;
41
- --md-sys-color-primary: #586878;
42
- --md-outlined-text-field-input-text-size: 14px;
43
- --md-outlined-field-bottom-space: 3px;
44
- --md-outlined-field-top-space: 3px;
45
- --md-outlined-field-leading-space: var(--spacing-medium, 8px);
46
- --md-outlined-field-trailing-space: var(--spacing-medium, 8px);
47
- }
48
- select2-component {
49
- width:100%;
50
- }
51
- input[type="date"] {
52
- border:1px solid rgba(51,51,51,.20);
53
- padding:var(--spacing-small, 4px) var(--spacing-medium, 8px);
54
- border-radius: 5px;
55
- }
56
- md-outlined-text-field[type='textarea'] {
57
- width: 100%;
58
- height: 120px;
59
- resize: none;
60
- }
61
-
62
- ox-input-image {
63
- width: 120px;
64
- height: 90px;
65
- }
66
- ox-input-file {
67
- width: 120px;
68
- height: 90px;
69
- padding: 0;
70
- }
71
-
72
- div[body] {
73
- display: flex;
74
- margin: var(--spacing-large, 12px);
75
- margin-top:0;
76
- gap: var(--spacing-medium, 8px);
77
-
78
- & > div {
79
- display: flex;
80
- height: fit-content;
81
- flex-direction: column;
82
- padding: var(--spacing-large, 12px);
83
- background-color: var(--md-sys-color-on-primary);
84
- border: 1px solid #cccccc80;
85
- border-radius: 5px;
86
- gap: var(--spacing-medium, 8px);
87
-
88
- h3 {
89
- color: #2e79be;
90
- font-size: 16px;
91
- margin: 0px;
92
- }
93
-
94
- div[row] {
95
- display: flex;
96
- align-items: center;
97
-
98
- span:first-child {
99
- flex: 0.3;
100
- text-align: right;
101
- font-size: 14px;
102
- }
103
-
104
- span:last-child {
105
- flex: 0.7;
106
- display: flex;
107
- gap: var(--spacing-medium, 8px);
108
- margin-left: var(--spacing-medium, 8px);
109
- align-items: center;
110
-
111
- &[align-end] {
112
- align-items: end;
113
- }
114
- }
115
- }
116
- }
117
-
118
- div[project-info] {
119
- flex: 0.55;
120
- }
121
-
122
- div[detail-info] {
123
- flex: 0.45;
124
- padding: 0px;
125
- gap: 10px;
126
- background-color: transparent;
127
- border: none;
128
-
129
- & > div {
130
- display: flex;
131
- flex-direction: column;
132
- gap: var(--spacing-medium, 8px);
133
- border: 1px solid #cccccc80;
134
- border-radius: 5px;
135
- padding: var(--spacing-large, 12px);
136
- background-color: var(--md-sys-color-on-primary);
137
-
138
- md-outlined-text-field[type='text'] {
139
- width: 60%;
140
- }
141
-
142
- md-elevated-button {
143
- --md-elevated-button-container-height: 30px;
144
- --md-elevated-button-container-color: var(--md-sys-color-on-primary);
145
- --md-elevated-button-label-text-size: 16px;
146
- }
147
- hr {
148
- border: 1px rgba(51,51,51,.1) dashed;
149
- width: 100%;
150
- margin-bottom: var(--spacing-tiny, 2px);
151
- }
152
- div[warn] {
153
- font-size: 12px;
154
- color: red;
155
- margin-left: var(--spacing-small, 4px);
156
- margin-bottom: var(--spacing-small, 4px);
157
- }
158
-
159
- md-outlined-button {
160
- min-height: 30px;
161
- padding: 0 var(--spacing-large, 12px);
162
- box-shadow: 1px 1px 1px #0000001a;
163
- --md-outlined-button-label-text-color: #586878;
164
- --md-outlined-button-label-text-weight: bold;
165
- --md-sys-color-outline: rgba(51,51,51,.20);
166
- }
167
-
168
- div[row] {
169
- span:first-child {
170
- flex: 0.2;
171
- }
172
- span:last-child {
173
- flex: 0.8;
174
- }
175
- }
176
-
177
- div[separate-container] {
178
- display: grid;
179
- grid-template-columns: repeat(2, 1fr);
180
- gap: var(--spacing-medium, 8px);
181
-
182
- md-outlined-text-field {
183
- width: 70px;
184
- }
185
-
186
- & > div {
187
- display: flex;
188
-
189
- span[floor-title] {
190
- min-width: 33px;
191
- margin-right: var(--spacing-small, 4px);
192
- }
193
- span:first-child {
194
- flex: 0.4;
195
- justify-content: end;
196
- display: flex;
197
- }
198
- span:last-child {
199
- flex: 0.6;
200
- display: flex;
201
- align-items: center;
202
- padding-left: var(--spacing-medium, 8px);
203
- }
204
- }
205
- }
206
-
207
- &[project] {
208
- div[separate-container] {
209
- & > div {
210
- span:first-child {
211
- flex: 0.6;
212
- min-width: 100px;
213
- }
214
- span:last-child {
215
- flex: 0.4;
216
- margin-left: 0;
217
- }
218
- }
219
- }
220
- }
221
- }
222
- }
223
- }
224
- `
225
- ]
226
-
227
- get context() {
228
- return {
229
- title: '프로젝트 정보 관리'
230
- }
231
- }
232
-
233
- private defaultProject = {
234
- name: '',
235
- buildingComplex: {
236
- address: '',
237
- area: 0,
238
- constructionCompany: '',
239
- clientCompany: '',
240
- supervisoryCompany: '',
241
- designCompany: '',
242
- constructionType: '',
243
- buildings: []
244
- }
245
- }
246
- @state() projectId: string = ''
247
- @state() project: Project = { ...this.defaultProject }
248
- @state() selectedValues: string[] = []
249
- @state() overallConstructorList: Array<{ name: string; value: string }> = []
250
- @state() taskConstructorList: Array<{ name: string; value: string }> = []
251
- @state() taskSupervisoryList: Array<{ name: string; value: string }> = []
252
- @state() overallSupervisoryList: Array<{ name: string; value: string }> = []
253
-
254
- render() {
255
- return html`
256
- <project-update-header .projectId=${this.project.id || ''} title="프로젝트 정보 관리" @custom-click=${this._saveProject}>
257
- </project-update-header>
258
-
259
- <div body>
260
- <div project-info>
261
- <h3>기본 정보</h3>
262
- <div row>
263
- <span>프로젝트명</span>
264
- <span
265
- ><md-outlined-text-field
266
- type="text"
267
- name="name"
268
- project
269
- .value=${this.project.name || ''}
270
- @input=${this._onInputChange}
271
- ></md-outlined-text-field>
272
- </span>
273
- </div>
274
- <div row>
275
- <span>프로젝트 주소</span>
276
- <span>
277
- <md-outlined-text-field
278
- type="text"
279
- name="address"
280
- building-complex
281
- .value=${this.project?.buildingComplex?.address || ''}
282
- @input=${this._onInputChange}
283
- ></md-outlined-text-field>
284
- </span>
285
- </div>
286
- <div row>
287
- <span>위도</span>
288
- <span>
289
- <md-outlined-text-field
290
- type="text"
291
- name="latitude"
292
- numeric
293
- building-complex
294
- .value=${this.project?.buildingComplex?.latitude?.toString() || ''}
295
- @input=${this._onInputChange}
296
- ></md-outlined-text-field>
297
- </span>
298
- </div>
299
- <div row>
300
- <span>경도</span>
301
- <span>
302
- <md-outlined-text-field
303
- type="text"
304
- name="longitude"
305
- numeric
306
- building-complex
307
- .value=${this.project?.buildingComplex?.longitude?.toString() || ''}
308
- @input=${this._onInputChange}
309
- ></md-outlined-text-field>
310
- </span>
311
- </div>
312
- <div row>
313
- <span>면적</span>
314
- <span align-end
315
- ><md-outlined-text-field
316
- type="text"
317
- name="area"
318
- numeric
319
- building-complex
320
- .value=${this.project?.buildingComplex?.area?.toString() || ''}
321
- @input=${this._onInputChange}
322
- ></md-outlined-text-field>
323
- ㎡</span
324
- >
325
- </div>
326
- <div row>
327
- <span>착공일정 ~ 준공일정</span>
328
- <span
329
- ><input
330
- type="date"
331
- name="startDate"
332
- project
333
- .value=${this.project.startDate || ''}
334
- @input=${this._onInputChange}
335
- max="9999-12-31"
336
- />
337
- ~
338
- <input
339
- type="date"
340
- name="endDate"
341
- project
342
- .value=${this.project.endDate || ''}
343
- @input=${this._onInputChange}
344
- max="9999-12-31"
345
- />
346
- </span>
347
- </div>
348
- <div row>
349
- <span>발주처</span>
350
- <span
351
- ><md-outlined-text-field
352
- type="text"
353
- name="clientCompany"
354
- building-complex
355
- .value=${this.project?.buildingComplex?.clientCompany || ''}
356
- @input=${this._onInputChange}
357
- ></md-outlined-text-field>
358
- </span>
359
- </div>
360
- <div row>
361
- <span>건설사</span>
362
- <span
363
- ><md-outlined-text-field
364
- type="text"
365
- name="constructionCompany"
366
- building-complex
367
- .value=${this.project?.buildingComplex?.constructionCompany || ''}
368
- @input=${this._onInputChange}
369
- ></md-outlined-text-field>
370
- </span>
371
- </div>
372
- <div row>
373
- <span>설계사</span>
374
- <span
375
- ><md-outlined-text-field
376
- type="text"
377
- name="designCompany"
378
- building-complex
379
- .value=${this.project?.buildingComplex?.designCompany || ''}
380
- @input=${this._onInputChange}
381
- ></md-outlined-text-field>
382
- </span>
383
- </div>
384
- <div row>
385
- <span>감리사</span>
386
- <span
387
- ><md-outlined-text-field
388
- type="text"
389
- name="supervisoryCompany"
390
- building-complex
391
- .value=${this.project?.buildingComplex?.supervisoryCompany || ''}
392
- @input=${this._onInputChange}
393
- ></md-outlined-text-field>
394
- </span>
395
- </div>
396
- <div row>
397
- <span>건설구분</span>
398
- <span
399
- ><md-outlined-text-field
400
- type="text"
401
- name="constructionType"
402
- building-complex
403
- .value=${this.project?.buildingComplex?.constructionType || ''}
404
- @input=${this._onInputChange}
405
- ></md-outlined-text-field>
406
- </span>
407
- </div>
408
- <div row>
409
- <span>대표사진 업로드</span>
410
- <span>
411
- <ox-input-image
412
- name="mainPhoto"
413
- value=${this.project?.mainPhoto?.fullpath || ''}
414
- @change=${this.onCreateAttachment.bind(this)}
415
- ></ox-input-image>
416
- </span>
417
- </div>
418
- <div row>
419
- <span>단지 BIM</span>
420
- <span>
421
- <ox-input-file
422
- name="drawing"
423
- label=" "
424
- description="IFC 업로드"
425
- .value=${this.project?.buildingComplex?.drawing || ''}
426
- @change=${this.onCreateAttachment.bind(this)}
427
- ></ox-input-file>
428
- </span>
429
- </div>
430
- <div row>
431
- <span>공사금액</span>
432
- <span
433
- ><md-outlined-text-field
434
- type="text"
435
- name="constructionCost"
436
- numeric
437
- building-complex
438
- .value=${this.project?.buildingComplex?.constructionCost?.toString() || ''}
439
- @input=${this._onInputChange}
440
- ></md-outlined-text-field>
441
- </span>
442
- </div>
443
- <div row>
444
- <span>기타사항</span>
445
- <span>
446
- <md-outlined-text-field
447
- type="textarea"
448
- name="etc"
449
- building-complex
450
- .value=${this.project?.buildingComplex?.etc || ''}
451
- @input=${this._onInputChange}
452
- ></md-outlined-text-field>
453
- </span>
454
- </div>
455
- <div row>
456
- <span>총괄 시공 관리자 리스트</span>
457
- <span>
458
- <select2-component
459
- placeholder="총괄 시공 관리자 리스트"
460
- name="overallConstructorEmails"
461
- .options=${this.overallConstructorList}
462
- .selectedValues=${this.project?.buildingComplex?.overallConstructorEmails || []}
463
- @selection-changed=${this._handleSelectionChange}
464
- ></select2-component>
465
- </span>
466
- </div>
467
- <div row>
468
- <span>공종별 시공 관리자 리스트</span>
469
- <span>
470
- <select2-component
471
- placeholder="공종별 시공 관리자 리스트"
472
- name="taskConstructorEmails"
473
- .options=${this.taskConstructorList}
474
- .selectedValues=${this.project?.buildingComplex?.taskConstructorEmails || []}
475
- @selection-changed=${this._handleSelectionChange}
476
- ></select2-component>
477
- </span>
478
- </div>
479
- <div row>
480
- <span>총괄 감리 책임자 리스트</span>
481
- <span>
482
- <select2-component
483
- placeholder="총괄 감리 책임자 리스트"
484
- name="overallSupervisoryEmails"
485
- .options=${this.overallSupervisoryList}
486
- .selectedValues=${this.project?.buildingComplex?.overallSupervisoryEmails || []}
487
- @selection-changed=${this._handleSelectionChange}
488
- ></select2-component>
489
- </span>
490
- </div>
491
- <div row>
492
- <span>공종별 감리 책임자 리스트</span>
493
- <span>
494
- <select2-component
495
- placeholder="공종별 감리 책임자 리스트"
496
- name="taskSupervisoryEmails"
497
- .options=${this.taskSupervisoryList}
498
- .selectedValues=${this.project?.buildingComplex?.taskSupervisoryEmails || []}
499
- @selection-changed=${this._handleSelectionChange}
500
- ></select2-component
501
- ></span>
502
- </div>
503
- </div>
504
-
505
- <div detail-info>
506
- <div>
507
- <h3>건설구분 상세 정보</h3>
508
- <div row>
509
- <span>세대수</span>
510
- <span
511
- ><md-outlined-text-field
512
- type="text"
513
- numeric
514
- building-complex
515
- name="householdCount"
516
- .value=${this.project?.buildingComplex?.householdCount?.toString() || ''}
517
- @input=${this._onInputChange}
518
- ></md-outlined-text-field>
519
- </span>
520
- </div>
521
- <div row>
522
- <span>동수</span>
523
- <span
524
- ><md-outlined-text-field
525
- type="text"
526
- numeric
527
- building-complex
528
- name="buildingCount"
529
- value=${this.project?.buildingComplex?.buildingCount?.toString() || ''}
530
- @input=${this._onInputChange}
531
- ></md-outlined-text-field>
532
- <md-outlined-button @click=${this._setBuilding}>적용</md-outlined-button>
533
- </span>
534
- </div>
535
- <hr />
536
- <div warn>* 동/층의 정보를 수정하면 기존의 동/층 정보는 모두 제거됩니다.</div>
537
- <div separate-container>
538
- ${this.project?.buildingComplex?.buildings?.map(
539
- (building, idx) => html`
540
- <div>
541
- <span>
542
- <md-outlined-text-field
543
- type="text"
544
- building
545
- name="name"
546
- .value=${building?.name || ''}
547
- @input=${e => this._onInputChange(e, idx)}
548
- placeholder="ooo동"
549
- ></md-outlined-text-field>
550
- </span>
551
- <span>
552
- <span floor-title>층수</span>
553
- <md-outlined-text-field
554
- type="text"
555
- numeric
556
- building
557
- name="floorCount"
558
- .value=${building?.floorCount?.toString() || ''}
559
- @input=${e => this._onInputChange(e, idx)}
560
- placeholder="oo"
561
- ></md-outlined-text-field>
562
- </span>
563
- </div>
564
- `
565
- )}
566
- </div>
567
- </div>
568
-
569
- <div project>
570
- <h3>프로젝트 현황</h3>
571
- <div row separate-container>
572
- <div>
573
- <span>전체 진행현황</span>
574
- <span>
575
- <md-outlined-text-field
576
- type="text"
577
- numeric
578
- project
579
- name="totalProgress"
580
- .value=${this.project.totalProgress?.toString() || ''}
581
- @input=${this._onInputChange}
582
- suffix-text="%"
583
- ></md-outlined-text-field>
584
- </span>
585
- </div>
586
- <div>
587
- <span>검측/통과비율</span>
588
- <span>
589
- <md-outlined-text-field
590
- type="text"
591
- numeric
592
- project
593
- name="inspPassRate"
594
- .value=${this.project.inspPassRate?.toString() || ''}
595
- @input=${this._onInputChange}
596
- suffix-text="%"
597
- ></md-outlined-text-field>
598
- </span>
599
- </div>
600
- </div>
601
- <div row separate-container>
602
- <div>
603
- <span>주간 진행현황</span>
604
- <span>
605
- <md-outlined-text-field
606
- type="text"
607
- numeric
608
- project
609
- name="weeklyProgress"
610
- .value=${this.project.weeklyProgress?.toString() || ''}
611
- @input=${this._onInputChange}
612
- suffix-text="%"
613
- ></md-outlined-text-field>
614
- </span>
615
- </div>
616
- <div>
617
- <span>로봇작업진행율</span>
618
- <span>
619
- <md-outlined-text-field
620
- type="text"
621
- numeric
622
- project
623
- name="robotProgressRate"
624
- .value=${this.project.robotProgressRate?.toString() || ''}
625
- @input=${this._onInputChange}
626
- suffix-text="%"
627
- ></md-outlined-text-field>
628
- </span>
629
- </div>
630
- </div>
631
- <div row separate-container>
632
- <div>
633
- <span>KPI</span>
634
- <span
635
- ><md-outlined-text-field
636
- type="text"
637
- numeric
638
- project
639
- name="kpi"
640
- .value=${this.project.kpi?.toString() || ''}
641
- @input=${this._onInputChange}
642
- suffix-text="%"
643
- ></md-outlined-text-field>
644
- </span>
645
- </div>
646
- <div>
647
- <span>구조안전도</span>
648
- <span
649
- ><md-outlined-text-field
650
- type="text"
651
- numeric
652
- project
653
- name="structuralSafetyRate"
654
- .value=${this.project.structuralSafetyRate?.toString() || ''}
655
- @input=${this._onInputChange}
656
- suffix-text="%"
657
- ></md-outlined-text-field>
658
- </span>
659
- </div>
660
- </div>
661
- </div>
662
-
663
- <div>
664
- <h3>공지사항</h3>
665
- <div>
666
- <span></span>
667
- <span>
668
- <md-outlined-text-field
669
- type="textarea"
670
- name="notice"
671
- building-complex
672
- .value=${this.project?.buildingComplex?.notice || ''}
673
- @input=${this._onInputChange}
674
- ></md-outlined-text-field>
675
- </span>
676
- </div>
677
- </div>
678
- </div>
679
- </div>
680
- `
681
- }
682
-
683
- async pageInitialized(lifecycle: PageLifecycle) {}
684
-
685
- async pageUpdated(changes: any, lifecycle: PageLifecycle) {
686
- if (this.active) {
687
- this.projectId = lifecycle.resourceId || ''
688
- await this.initProject(this.projectId)
689
- }
690
- }
691
-
692
- async initProject(projectId: string = '') {
693
- const response = await client.query({
694
- query: gql`
695
- query Project($id: String!, $filters: [Filter!]) {
696
- project(id: $id) {
697
- id
698
- name
699
- startDate
700
- endDate
701
- mainPhoto {
702
- fullpath
703
- }
704
- totalProgress
705
- weeklyProgress
706
- kpi
707
- inspPassRate
708
- robotProgressRate
709
- structuralSafetyRate
710
- buildingComplex {
711
- id
712
- address
713
- latitude
714
- longitude
715
- area
716
- clientCompany
717
- constructionCompany
718
- supervisoryCompany
719
- designCompany
720
- drawing {
721
- id
722
- name
723
- }
724
- constructionType
725
- constructionCost
726
- etc
727
- notice
728
- householdCount
729
- buildingCount
730
- overallConstructorEmails
731
- taskConstructorEmails
732
- overallSupervisoryEmails
733
- taskSupervisoryEmails
734
- buildings {
735
- id
736
- name
737
- floorCount
738
- }
739
- }
740
- }
741
-
742
- employees(filters: $filters) {
743
- items {
744
- id
745
- name
746
- jobResponsibility
747
- active
748
- user {
749
- id
750
- name
751
- email
752
- }
753
- }
754
- }
755
- }
756
- `,
757
- variables: {
758
- id: projectId,
759
- filters: [
760
- {
761
- name: 'active',
762
- operator: 'eq',
763
- value: true
764
- },
765
- {
766
- name: 'userId',
767
- operator: 'is_not_null',
768
- value: ''
769
- }
770
- ]
771
- }
772
- })
773
-
774
- this.project = response.data?.project
775
-
776
- const items = response.data?.employees?.items || []
777
- this.overallConstructorList = this._filterUserByPermission(items, 'OVERALL_CONSTRUCTOR')
778
- this.taskConstructorList = this._filterUserByPermission(items, 'TASK_CONSTRUCTOR')
779
- this.overallSupervisoryList = this._filterUserByPermission(items, 'OVERALL_SUPERVISORY')
780
- this.taskSupervisoryList = this._filterUserByPermission(items, 'TASK_SUPERVISORY')
781
- }
782
-
783
- private _filterUserByPermission(userList, permission: string) {
784
- return userList
785
- .filter(v => v.jobResponsibility == permission || v.jobResponsibility == 'ADMIN')
786
- .map(v => ({ name: v.name, value: v.user.email }))
787
- }
788
-
789
- private async _saveProject() {
790
- // 첨부 파일 필드 제거 (첨부 파일은 {filename}Upload 로 전송)
791
- delete this.project.mainPhoto
792
- delete this.project.buildingComplex.drawing
793
-
794
- const response = await client.mutate({
795
- mutation: gql`
796
- mutation UpdateProject($project: ProjectPatch!) {
797
- updateProject(project: $project) {
798
- id
799
- }
800
- }
801
- `,
802
- variables: {
803
- project: this.project
804
- },
805
- context: {
806
- hasUpload: true
807
- }
808
- })
809
-
810
- if (!response.errors) {
811
- notify({ message: '저장에 성공하였습니다.' })
812
- }
813
- }
814
-
815
- // 동 적용 버튼을 누르면 입력한 수 만큼 해당 단지에 동 데이터 생성
816
- private _setBuilding() {
817
- const buildingCount: number = this.project?.buildingComplex?.buildingCount || 0
818
- const buildingInitData = { name: undefined, floorCount: undefined }
819
-
820
- // 빌딩 데이터가 없으면 빈 배열 넣어줌
821
- if (!this.project?.buildingComplex?.buildings?.length) {
822
- this.project.buildingComplex.buildings = []
823
- }
824
-
825
- if (this.project.buildingComplex.buildings.length >= buildingCount) {
826
- // 동 수가 더 작게 들어오면 기존 배열을 필요한 크기만큼 잘라내기
827
- this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings!.slice(0, buildingCount)]
828
- } else {
829
- // 동수가 더 크게 들어오면 기존 배열 + 빈 값을 채움
830
- const additionalCount = buildingCount - this.project.buildingComplex.buildings.length
831
- const additionalBuildings = Array.from({ length: additionalCount }, () => ({ ...buildingInitData }))
832
- this.project.buildingComplex.buildings = [...this.project.buildingComplex.buildings, ...additionalBuildings]
833
- }
834
-
835
- // 리렌더링
836
- this.project = { ...this.project }
837
- }
838
-
839
- // Input 요소의 값이 변경될 때 호출되는 콜백 함수
840
- private _onInputChange(event: InputEvent, idx: number) {
841
- const target = event.target as HTMLInputElement
842
- let inputVal: any = target.value
843
-
844
- // 숫자 타입은 다른 문자 입력 제거
845
- if (target.hasAttribute('numeric')) {
846
- inputVal = Number(inputVal.replace(/[^\d.]/g, ''))
847
- }
848
-
849
- if (target.hasAttribute('project')) {
850
- this.project[target.name] = inputVal
851
- } else if (target.hasAttribute('building-complex')) {
852
- this.project.buildingComplex![target.name] = inputVal
853
- } else if (target.hasAttribute('building')) {
854
- this.project.buildingComplex.buildings![idx][target.name] = inputVal
855
- }
856
- }
857
-
858
- // 이미지 업로드
859
- async onCreateAttachment(e: CustomEvent) {
860
- const target = e.target as HTMLInputElement
861
- const file = (target.name === 'mainPhoto' ? e.detail : e.detail[0]) || null
862
-
863
- if (target.name === 'mainPhoto') {
864
- this.project.mainPhotoUpload = file
865
- } else {
866
- this.project.buildingComplex.drawingUpload = file
867
- }
868
- }
869
-
870
- private _handleSelectionChange(e) {
871
- const name = e.target.getAttribute('name')
872
- const selectedValues = e.detail.selectedValues
873
-
874
- this.project.buildingComplex[name] = selectedValues
875
- }
876
- }