From 399835a06f35dacff2c80e919428787f37ab6c42 Mon Sep 17 00:00:00 2001 From: gunpitimac Date: Fri, 4 Aug 2023 14:16:52 +0700 Subject: [PATCH] [init] -init version --- .browserslistrc | 12 + .editorconfig | 13 + .gitignore | 46 + .vscode/settings.json | 9 + Dockerfile | 14 + README.md | 27 + angular.json | 167 + bitbucket-pipelines.yml | 31 + e2e/protractor.conf.js | 32 + e2e/src/app.e2e-spec.ts | 23 + e2e/src/app.po.ts | 11 + e2e/tsconfig.json | 13 + karma.conf.js | 32 + nginx.conf | 9 + package-lock.json | 35312 ++++++++++++++++ package.json | 72 + report.20210410.171439.4055.0.001.json | 610 + src/app/app-routing.module.ts | 613 + src/app/app.component.html | 1 + src/app/app.component.scss | 0 src/app/app.component.spec.ts | 35 + src/app/app.component.ts | 10 + src/app/app.module.ts | 53 + src/app/core/base/base-form-uid.ts | 93 + src/app/core/base/base-form.ts | 95 + src/app/core/base/base-list-role.ts | 39 + src/app/core/base/base-list.ts | 98 + src/app/core/base/base-openid-service.ts | 92 + src/app/core/base/base-service.ts | 93 + src/app/core/base/base-sub-list.ts | 36 + src/app/core/base/tinymce.ts | 49 + src/app/core/configs/config.ts | 0 src/app/core/core.module.ts | 23 + src/app/core/enum/role.ts | 76 + src/app/core/guards/auth.guard.spec.ts | 16 + src/app/core/guards/auth.guard.ts | 29 + .../token-intercepter.interceptor.spec.ts | 16 + .../token-intercepter.interceptor.ts | 41 + .../testing-center.service.spec.ts | 16 + .../TestingCenter/testing-center.service.ts | 27 + src/app/core/service/app.service.spec.ts | 16 + src/app/core/service/app.service.ts | 9 + .../card-print/card-printing-time.service.ts | 23 + .../card-print/card-printing.service.ts | 16 + .../card-print/testing-score.service.ts | 15 + .../enrollment-api/candidate-type.service.ts | 17 + .../testing-register-enrollment.service.ts | 34 + src/app/core/service/oidc/oidc.service.ts | 55 + src/app/core/service/openid/user.service.ts | 30 + .../permission/user-counter-login.service.ts | 19 + .../permission/user-counters.service.ts | 27 + .../core/service/province/provice.service.ts | 15 + .../question/question-category.service.ts | 35 + src/app/core/service/region/region.service.ts | 14 + .../candidate-registered-by-center.service.ts | 32 + ...candidate-registered-by-subject.service.ts | 32 + .../candidate-subject.service.ts | 32 + .../report/candidate/candidate.service.ts | 33 + .../daily-register-payment-total.service.ts | 31 + .../daily-register-payment.service.ts | 31 + .../eligible-candidate.service.ts | 23 + .../exam-card-print/testing-card.service.ts | 21 + .../exam-result-print.service.ts | 19 + .../exam-result-subject.service.ts | 34 + .../report/exam_total/exam-total.service.ts | 34 + .../excel-all-test/excel-all-test.service.ts | 25 + .../report-invigilator-cost.service.ts | 19 + ...yment-and-application-by-center.service.ts | 32 + ...ment-and-application-by-subject.service.ts | 33 + .../period-register-payment-online.service.ts | 23 + .../period-register-payment.service.ts | 23 + .../receipt-by-payment-code.service.ts | 71 + .../report/receiptAll/receipt-all.service.ts | 26 + .../service/report/reciept/reciept.service.ts | 25 + .../register-by-payment.service.ts | 33 + .../separated-by-exam-center.service.ts | 35 + .../setting-testing-center.service.ts | 35 + .../setting-testing-room.service.ts | 66 + .../signature-examination.service.ts | 33 + .../summary-candidate.service.ts | 32 + ...ry-candidates-absentees-passers.service.ts | 29 + .../testing-center-information.service.ts | 34 + .../testing-registration.service.ts | 34 + .../testing-room/testing-room.service.ts | 34 + .../testing-seat-and-room.service.ts | 33 + .../testing-subject/tesing-subject.service.ts | 32 + .../ru-student-registers.service.ts | 16 + .../service/ru-student/ru-student.service.ts | 27 + .../service/security/app-object.service.ts | 15 + .../security/app-permission.service.ts | 15 + .../core/service/security/app-role.service.ts | 15 + .../service/security/app-token.service.ts | 72 + .../core/service/security/app-user.service.ts | 15 + .../insturctor-payment-accout.service.ts | 15 + .../invigilator-cost.service.ts | 15 + .../settings/academic-semester.service.ts | 15 + .../service/settings/academic-year.service.ts | 15 + .../core/service/settings/branch.service.ts | 20 + .../service/settings/calendar-type.service.ts | 15 + .../service/settings/department.service.ts | 15 + .../settings/education-types.service.ts | 15 + .../core/service/settings/facultys.service.ts | 15 + .../settings/online-counters.service.ts | 15 + .../settings/recipient-signature.service.ts | 15 + .../service/settings/subject-types.service.ts | 15 + .../core/service/settings/subjects.service.ts | 27 + .../service/settings/testing-field.service.ts | 20 + .../service/settings/testing-vdos.service.ts | 14 + .../store-api/subject-information.service.ts | 17 + .../core/service/store-api/sync.service.ts | 22 + .../student-payment-confirm.service.ts | 19 + .../student-payment-not-paid.service.ts | 19 + .../student-payment.service.ts | 31 + .../student-payment/student-upload.service.ts | 19 + .../student/delete-import-student.service.ts | 31 + .../generate-group-seat-detail.service.ts | 19 + .../service/student/generate-group.service.ts | 19 + .../service/student/getstudent.service.ts | 14 + .../service/student/reset-seat.service.ts | 19 + .../student-generate-register.service.ts | 23 + .../student/student-generate-seat.service.ts | 19 + .../service/student/student-upload.service.ts | 48 + .../core/service/student/student.service.ts | 23 + src/app/core/service/sweetalert/sweetalert.ts | 274 + src/app/core/service/sync/sync.service.ts | 25 + .../exam-notification.service.ts | 80 + .../testing-information/grading.service.ts | 15 + .../random-questions.service.ts | 15 + .../room-invigilators.service.ts | 28 + .../testing-controls.service.ts | 26 + .../testing-fee.service.ts | 15 + .../testing-information.service.ts | 124 + .../testing-period.service.ts | 15 + .../testing-subject-add-date.service.ts | 23 + .../candidate-payment-status.service.ts | 15 + .../change-testing-date.service.ts | 25 + .../change-testing-room-and-date.service.ts | 19 + .../change-testing-room.service.ts | 15 + ...check-available-room-and-period.service.ts | 23 + ...eck-available-room-no-condition.service.ts | 19 + .../check-available-room.service.ts | 14 + .../check-available-seat.service.ts | 21 + .../check-subject-and-date.service.ts | 15 + .../daily-summary-ttb.service.ts | 19 + .../testing-register/daily-summary.service.ts | 19 + .../enrollment-counter-payments.service.ts | 19 + .../period-summary.service.ts | 21 + .../shared-usercouter.service.ts | 21 + .../testing-reciept.service.ts | 32 + .../testing-register-is-pay.service.ts | 19 + .../testing-register.service.ts | 20 + .../update-testing-seat.service.ts | 19 + .../v-eligible-candidates.service.ts | 28 + src/app/core/service/upload/upload.service.ts | 17 + src/app/core/service/user/user.service.ts | 17 + .../approve-examination.module.ts | 37 + .../approve-examination.container.html | 6 + .../approve-examination.container.scss | 15 + .../approve-examination.container.spec.ts | 25 + .../approve-examination.container.ts | 30 + .../approve-dialog.component.html | 28 + .../approve-dialog.component.scss | 9 + .../approve-dialog.component.spec.ts | 25 + .../approve-dialog.component.ts | 78 + .../approve-examination-list.component.html | 69 + .../approve-examination-list.component.scss | 0 ...approve-examination-list.component.spec.ts | 25 + .../approve-examination-list.component.ts | 48 + .../approve-examination-search.component.html | 28 + .../approve-examination-search.component.scss | 0 ...prove-examination-search.component.spec.ts | 25 + .../approve-examination-search.component.ts | 43 + .../router/approve-examination-router.ts | 15 + .../auth-callback/auth-callback.module.ts | 33 + .../auth-callback.component.html | 1 + .../auth-callback.component.scss | 0 .../auth-callback.component.spec.ts | 25 + .../auth-callback/auth-callback.component.ts | 36 + .../feature/auth-callback/router/router.ts | 15 + .../candidate-list/candidate-list.module.ts | 54 + ...idate-list-test-information.container.html | 7 + ...idate-list-test-information.container.scss | 0 ...te-list-test-information.container.spec.ts | 25 + ...ndidate-list-test-information.container.ts | 35 + .../candidate-list.container.html | 17 + .../candidate-list.container.scss | 0 .../candidate-list.container.spec.ts | 25 + .../candidate-list.container.ts | 111 + .../dialog-change-room.component.html | 59 + .../dialog-change-room.component.scss | 0 .../dialog-change-room.component.spec.ts | 25 + .../dialog-change-room.component.ts | 135 + .../dialog-change-seat.component.html | 46 + .../dialog-change-seat.component.scss | 9 + .../dialog-change-seat.component.spec.ts | 25 + .../dialog-change-seat.component.ts | 74 + .../dialog-sync/dialog-sync.component.html | 66 + .../dialog-sync/dialog-sync.component.scss | 0 .../dialog-sync/dialog-sync.component.spec.ts | 25 + .../dialog-sync/dialog-sync.component.ts | 116 + .../candidate-list-list.component.html | 75 + .../candidate-list-list.component.scss | 0 .../candidate-list-list.component.spec.ts | 25 + .../candidate-list-list.component.ts | 86 + ...idate-list-test-information.component.html | 85 + ...idate-list-test-information.component.scss | 0 ...te-list-test-information.component.spec.ts | 25 + ...ndidate-list-test-information.component.ts | 52 + .../candidate-list-search.component.html | 113 + .../candidate-list-search.component.scss | 0 .../candidate-list-search.component.spec.ts | 25 + .../candidate-list-search.component.ts | 150 + ...ist-test-information-search.component.html | 27 + ...ist-test-information-search.component.scss | 0 ...-test-information-search.component.spec.ts | 25 + ...-list-test-information-search.component.ts | 49 + .../router/candidate-list-router.ts | 15 + .../check-candidate-list.module.ts | 55 + .../check-candidate-list.container.html | 12 + .../check-candidate-list.container.scss | 0 .../check-candidate-list.container.spec.ts | 25 + .../check-candidate-list.container.ts | 130 + .../check-candidate-testing.container.html | 9 + .../check-candidate-testing.container.scss | 0 .../check-candidate-testing.container.spec.ts | 25 + .../check-candidate-testing.container.ts | 57 + ...check-candidate-list-search.component.html | 100 + ...check-candidate-list-search.component.scss | 0 ...ck-candidate-list-search.component.spec.ts | 25 + .../check-candidate-list-search.component.ts | 124 + .../check-candidate-list-table.component.html | 57 + .../check-candidate-list-table.component.scss | 0 ...eck-candidate-list-table.component.spec.ts | 25 + .../check-candidate-list-table.component.ts | 42 + ...ndidate-testing-list-search.component.html | 27 + ...ndidate-testing-list-search.component.scss | 0 ...date-testing-list-search.component.spec.ts | 25 + ...candidate-testing-list-search.component.ts | 51 + ...heck-candidate-testing-list.component.html | 76 + ...heck-candidate-testing-list.component.scss | 0 ...k-candidate-testing-list.component.spec.ts | 25 + .../check-candidate-testing-list.component.ts | 54 + .../router/check-candidate-list-router.ts | 15 + ...eat-change-test-information.container.html | 7 + ...eat-change-test-information.container.scss | 0 ...-change-test-information.container.spec.ts | 25 + .../seat-change-test-information.container.ts | 33 + .../seat-change/seat-change.container.html | 14 + .../seat-change/seat-change.container.scss | 0 .../seat-change/seat-change.container.spec.ts | 25 + .../seat-change/seat-change.container.ts | 89 + .../change-exam-day-dialog.component.html | 81 + .../change-exam-day-dialog.component.scss | 0 .../change-exam-day-dialog.component.spec.ts | 25 + .../change-exam-day-dialog.component.ts | 110 + ...hange-test-information-list.component.html | 96 + ...hange-test-information-list.component.scss | 0 ...ge-test-information-list.component.spec.ts | 25 + ...-change-test-information-list.component.ts | 29 + ...nge-test-information-search.component.html | 27 + ...nge-test-information-search.component.scss | 0 ...-test-information-search.component.spec.ts | 25 + ...hange-test-information-search.component.ts | 50 + .../seat-change-list.component.html | 65 + .../seat-change-list.component.scss | 0 .../seat-change-list.component.spec.ts | 25 + .../seat-change-list.component.ts | 106 + .../seat-change-search.component.html | 105 + .../seat-change-search.component.scss | 0 .../seat-change-search.component.spec.ts | 25 + .../seat-change-search.component.ts | 134 + .../seat-change/router/seat-change-router.ts | 15 + .../seat-change/seat-change.module.ts | 48 + .../candidate-payment-status.module.ts | 47 + .../candidate-payment-status.container.html | 5 + .../candidate-payment-status.container.scss | 0 ...candidate-payment-status.container.spec.ts | 25 + .../candidate-payment-status.container.ts | 42 + .../testing-info/testing-info.container.html | 8 + .../testing-info/testing-info.container.scss | 0 .../testing-info.container.spec.ts | 25 + .../testing-info/testing-info.container.ts | 36 + .../presenter/list/list.component.html | 58 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 34 + .../presenter/search/search.component.html | 105 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 98 + .../testing-info-list.component.html | 96 + .../testing-info-list.component.scss | 0 .../testing-info-list.component.spec.ts | 25 + .../testing-info-list.component.ts | 30 + .../testing-info-search.component.html | 27 + .../testing-info-search.component.scss | 0 .../testing-info-search.component.spec.ts | 25 + .../testing-info-search.component.ts | 42 + .../candidate-payment-status/router/router.ts | 15 + .../change-exam-day/change-exam-day.module.ts | 44 + .../change-exam-day.container.html | 7 + .../change-exam-day.container.scss | 0 .../change-exam-day.container.spec.ts | 25 + .../change-exam-day.container.ts | 39 + .../alrdy-list/alrdy-list.component.html | 62 + .../alrdy-list/alrdy-list.component.scss | 0 .../alrdy-list/alrdy-list.component.spec.ts | 25 + .../alrdy-list/alrdy-list.component.ts | 36 + .../change-dialog.component.html | 42 + .../change-dialog.component.scss | 0 .../change-dialog.component.spec.ts | 25 + .../change-dialog/change-dialog.component.ts | 79 + .../reason-dialog.component.html | 12 + .../reason-dialog.component.scss | 0 .../reason-dialog.component.spec.ts | 25 + .../reason-dialog/reason-dialog.component.ts | 28 + .../empty-list/empty-list.component.html | 55 + .../empty-list/empty-list.component.scss | 0 .../empty-list/empty-list.component.spec.ts | 25 + .../empty-list/empty-list.component.ts | 29 + .../presenter/list/list/list.component.html | 41 + .../presenter/list/list/list.component.scss | 41 + .../list/list/list.component.spec.ts | 25 + .../presenter/list/list/list.component.ts | 39 + .../wait-list/wait-list.component.html | 62 + .../wait-list/wait-list.component.scss | 0 .../wait-list/wait-list.component.spec.ts | 25 + .../wait-list/wait-list.component.ts | 51 + .../feature/change-exam-day/router/router.ts | 15 + .../change-exam-room.module.ts | 51 + .../change-exam-room-view.container.html | 12 + .../change-exam-room-view.container.scss | 0 .../change-exam-room-view.container.spec.ts | 25 + .../change-exam-room-view.container.ts | 94 + .../change-exam-room.container.html | 2 + .../change-exam-room.container.scss | 0 .../change-exam-room.container.spec.ts | 25 + .../change-exam-room.container.ts | 27 + .../presenter/dialog/dialog.component.html | 87 + .../presenter/dialog/dialog.component.scss | 0 .../presenter/dialog/dialog.component.spec.ts | 25 + .../presenter/dialog/dialog.component.ts | 102 + .../presenter/list/list.component.html | 79 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 29 + .../room-view-list.component.html | 43 + .../room-view-list.component.scss | 0 .../room-view-list.component.spec.ts | 25 + .../room-view-list.component.ts | 52 + .../room-view-search.component.html | 55 + .../room-view-search.component.scss | 0 .../room-view-search.component.spec.ts | 25 + .../room-view-search.component.ts | 71 + .../presenter/search/search.component.html | 27 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 55 + .../presenter/view/view.component.html | 95 + .../presenter/view/view.component.scss | 0 .../presenter/view/view.component.spec.ts | 25 + .../presenter/view/view.component.ts | 117 + .../feature/change-exam-room/router/router.ts | 15 + .../change-password/change-password.module.ts | 32 + .../change-password/form/form.component.html | 38 + .../change-password/form/form.component.scss | 0 .../form/form.component.spec.ts | 25 + .../change-password/form/form.component.ts | 94 + .../feature/change-password/router/router.ts | 15 + .../testing-info/testing-info.container.html | 2 + .../testing-info/testing-info.container.scss | 0 .../testing-info.container.spec.ts | 25 + .../testing-info/testing-info.container.ts | 37 + .../create-exam-seat.module.ts | 50 + .../create-seat/create-seat.component.html | 93 + .../create-seat/create-seat.component.scss | 0 .../create-seat/create-seat.component.spec.ts | 25 + .../create-seat/create-seat.component.ts | 96 + .../student-dialog.component.html | 32 + .../student-dialog.component.scss | 0 .../student-dialog.component.spec.ts | 25 + .../student-dialog.component.ts | 83 + .../testing-info-list.component.html | 73 + .../testing-info-list.component.scss | 0 .../testing-info-list.component.spec.ts | 25 + .../testing-info-list.component.ts | 48 + .../testing-info-search.component.html | 29 + .../testing-info-search.component.scss | 0 .../testing-info-search.component.spec.ts | 25 + .../testing-info-search.component.ts | 53 + .../presenter/view/view.component.html | 91 + .../presenter/view/view.component.scss | 0 .../presenter/view/view.component.spec.ts | 25 + .../presenter/view/view.component.ts | 92 + .../feature/create-exam-seat/router/router.ts | 15 + .../approve-exam/approve-exam.module.ts | 42 + .../approve-exam/approve-exam.container.html | 9 + .../approve-exam/approve-exam.container.scss | 0 .../approve-exam.container.spec.ts | 25 + .../approve-exam/approve-exam.container.ts | 107 + ...confirm-approve-exam-dialog.component.html | 46 + ...confirm-approve-exam-dialog.component.scss | 11 + ...firm-approve-exam-dialog.component.spec.ts | 25 + .../confirm-approve-exam-dialog.component.ts | 70 + .../approve-exam-list.component.html | 77 + .../approve-exam-list.component.scss | 0 .../approve-exam-list.component.spec.ts | 25 + .../approve-exam-list.component.ts | 75 + .../approve-exam-search.component.html | 34 + .../approve-exam-search.component.scss | 0 .../approve-exam-search.component.spec.ts | 25 + .../approve-exam-search.component.ts | 58 + .../router/approve-exam-router.ts | 15 + .../create-exam-calender.container.html | 10 + .../create-exam-calender.container.scss | 0 .../create-exam-calender.container.spec.ts | 25 + .../create-exam-calender.container.ts | 67 + .../create-exam-calendar.module.ts | 46 + .../create-exam-calendar-form.component.html | 103 + .../create-exam-calendar-form.component.scss | 0 ...reate-exam-calendar-form.component.spec.ts | 25 + .../create-exam-calendar-form.component.ts | 410 + .../create-exam-calendar-list.component.html | 89 + .../create-exam-calendar-list.component.scss | 0 ...reate-exam-calendar-list.component.spec.ts | 25 + .../create-exam-calendar-list.component.ts | 65 + ...create-exam-calender-search.component.html | 28 + ...create-exam-calender-search.component.scss | 0 ...ate-exam-calender-search.component.spec.ts | 25 + .../create-exam-calender-search.component.ts | 57 + .../router/create-exam-calendar-router.ts | 15 + .../create-exam-condition.container.html | 10 + .../create-exam-condition.container.scss | 0 .../create-exam-condition.container.spec.ts | 25 + .../create-exam-condition.container.ts | 67 + .../create-exam-condition.module.ts | 46 + .../create-exam-condition-form.component.html | 31 + .../create-exam-condition-form.component.scss | 0 ...eate-exam-condition-form.component.spec.ts | 25 + .../create-exam-condition-form.component.ts | 366 + .../create-exam-condition-list.component.html | 89 + .../create-exam-condition-list.component.scss | 0 ...eate-exam-condition-list.component.spec.ts | 25 + .../create-exam-condition-list.component.ts | 69 + ...reate-exam-condition-search.component.html | 28 + ...reate-exam-condition-search.component.scss | 0 ...te-exam-condition-search.component.spec.ts | 25 + .../create-exam-condition-search.component.ts | 53 + .../router/create-exam-condition-router.ts | 15 + .../create-exam-information.container.html | 13 + .../create-exam-information.container.scss | 0 .../create-exam-information.container.spec.ts | 25 + .../create-exam-information.container.ts | 67 + .../create-exam-information.module.ts | 48 + ...reate-exam-information-form.component.html | 291 + ...reate-exam-information-form.component.scss | 10 + ...te-exam-information-form.component.spec.ts | 25 + .../create-exam-information-form.component.ts | 542 + ...reate-exam-information-list.component.html | 90 + ...reate-exam-information-list.component.scss | 1 + ...te-exam-information-list.component.spec.ts | 25 + .../create-exam-information-list.component.ts | 84 + ...ate-exam-information-search.component.html | 28 + ...ate-exam-information-search.component.scss | 0 ...-exam-information-search.component.spec.ts | 25 + ...reate-exam-information-search.component.ts | 52 + .../router/create-exam-information-router.ts | 16 + .../create-exam-room.container.html | 9 + .../create-exam-room.container.scss | 0 .../create-exam-room.container.spec.ts | 25 + .../create-exam-room.container.ts | 62 + .../create-exam-room.module.ts | 46 + .../create-exam-room-form.component.html | 131 + .../create-exam-room-form.component.scss | 0 .../create-exam-room-form.component.spec.ts | 25 + .../create-exam-room-form.component.ts | 633 + .../create-exam-room-list.component.html | 89 + .../create-exam-room-list.component.scss | 0 .../create-exam-room-list.component.spec.ts | 25 + .../create-exam-room-list.component.ts | 61 + .../create-exam-room-search.component.html | 28 + .../create-exam-room-search.component.scss | 0 .../create-exam-room-search.component.spec.ts | 25 + .../create-exam-room-search.component.ts | 52 + .../router/create-exam-room-router.ts | 16 + ...xam-setup-period-by-subject.container.html | 12 + ...xam-setup-period-by-subject.container.scss | 0 ...-setup-period-by-subject.container.spec.ts | 25 + ...-exam-setup-period-by-subject.container.ts | 36 + ...ate-exam-setup-period-by-subject.module.ts | 50 + ...dialog-create-period-by-day.component.html | 38 + ...dialog-create-period-by-day.component.scss | 0 ...log-create-period-by-day.component.spec.ts | 25 + .../dialog-create-period-by-day.component.ts | 229 + ...tup-period-by-subject-infor.component.html | 81 + ...tup-period-by-subject-infor.component.scss | 0 ...-period-by-subject-infor.component.spec.ts | 25 + ...setup-period-by-subject-infor.component.ts | 171 + ...etup-period-by-subject-list.component.html | 53 + ...etup-period-by-subject-list.component.scss | 0 ...p-period-by-subject-list.component.spec.ts | 25 + .../setup-period-by-subject-list.component.ts | 56 + ...d-by-subject-testinfor-list.component.html | 83 + ...d-by-subject-testinfor-list.component.scss | 0 ...y-subject-testinfor-list.component.spec.ts | 25 + ...iod-by-subject-testinfor-list.component.ts | 49 + ...by-subject-testinfor-search.component.html | 27 + ...by-subject-testinfor-search.component.scss | 0 ...subject-testinfor-search.component.spec.ts | 25 + ...d-by-subject-testinfor-search.component.ts | 49 + ...ate-exam-setup-period-by-subject-router.ts | 15 + .../create-exam-subject.container.html | 9 + .../create-exam-subject.container.scss | 0 .../create-exam-subject.container.spec.ts | 25 + .../create-exam-subject.container.ts | 62 + .../create-exam-subject.module.ts | 48 + .../create-exam-subject-form.component.html | 11 + .../create-exam-subject-form.component.scss | 0 ...create-exam-subject-form.component.spec.ts | 25 + .../create-exam-subject-form.component.ts | 577 + .../create-exam-suject-table.component.html | 119 + .../create-exam-suject-table.component.scss | 0 ...create-exam-suject-table.component.spec.ts | 25 + .../create-exam-suject-table.component.ts | 175 + .../create-exam-subject-list.component.html | 90 + .../create-exam-subject-list.component.scss | 0 ...create-exam-subject-list.component.spec.ts | 25 + .../create-exam-subject-list.component.ts | 58 + .../create-exam-subject-search.component.html | 28 + .../create-exam-subject-search.component.scss | 0 ...eate-exam-subject-search.component.spec.ts | 25 + .../create-exam-subject-search.component.ts | 54 + .../router/create-exam-subject-router.ts | 15 + .../reject-exam/reject-exam.container.html | 7 + .../reject-exam/reject-exam.container.scss | 0 .../reject-exam/reject-exam.container.spec.ts | 25 + .../reject-exam/reject-exam.container.ts | 74 + .../confirm-reject-exam-dialog.component.html | 46 + .../confirm-reject-exam-dialog.component.scss | 11 + ...nfirm-reject-exam-dialog.component.spec.ts | 25 + .../confirm-reject-exam-dialog.component.ts | 68 + .../reject-exam-list.component.html | 80 + .../reject-exam-list.component.scss | 0 .../reject-exam-list.component.spec.ts | 25 + .../reject-exam-list.component.ts | 67 + .../reject-exam-search.component.html | 33 + .../reject-exam-search.component.scss | 0 .../reject-exam-search.component.spec.ts | 25 + .../reject-exam-search.component.ts | 53 + .../reject-exam/reject-exam.module.ts | 38 + .../reject-exam/router/reject-exam-router.ts | 15 + src/app/feature/default/default.module.ts | 32 + .../presenter/default/default.component.html | 4 + .../presenter/default/default.component.scss | 0 .../default/default.component.spec.ts | 25 + .../presenter/default/default.component.ts | 18 + .../feature/default/router/default-router.ts | 15 + .../daily-summary-ttb.container.html | 7 + .../daily-summary-ttb.container.scss | 0 .../daily-summary-ttb.container.spec.ts | 25 + .../daily-summary-ttb.container.ts | 45 + .../daily-summary-ttb.module.ts | 35 + .../daily-summary-ttb-list.component.html | 39 + .../daily-summary-ttb-list.component.scss | 0 .../daily-summary-ttb-list.component.spec.ts | 25 + .../daily-summary-ttb-list.component.ts | 54 + .../daily-summary-ttb-search.component.html | 21 + .../daily-summary-ttb-search.component.scss | 0 ...daily-summary-ttb-search.component.spec.ts | 25 + .../daily-summary-ttb-search.component.ts | 26 + .../router/daily-summary-ttb-router.ts | 15 + .../daily-summary.container.html | 5 + .../daily-summary.container.scss | 0 .../daily-summary.container.spec.ts | 25 + .../daily-summary/daily-summary.container.ts | 35 + .../daily-summary/daily-summary.module.ts | 38 + .../presenter/dialog/dialog.component.html | 68 + .../presenter/dialog/dialog.component.scss | 0 .../presenter/dialog/dialog.component.spec.ts | 25 + .../presenter/dialog/dialog.component.ts | 74 + .../daily-summary-list.component.html | 93 + .../daily-summary-list.component.scss | 0 .../daily-summary-list.component.spec.ts | 25 + .../daily-summary-list.component.ts | 146 + .../daily-summary-search.component.html | 21 + .../daily-summary-search.component.scss | 0 .../daily-summary-search.component.spec.ts | 25 + .../daily-summary-search.component.ts | 27 + .../router/daily-summary-router.ts | 15 + .../manage-receipt.container.html | 11 + .../manage-receipt.container.scss | 0 .../manage-receipt.container.spec.ts | 25 + .../manage-receipt.container.ts | 71 + .../manage-receipt/manage-receipt.module.ts | 35 + .../manage-receipt-list.component.html | 53 + .../manage-receipt-list.component.scss | 0 .../manage-receipt-list.component.spec.ts | 25 + .../manage-receipt-list.component.ts | 117 + .../manage-receipt-search.component.html | 57 + .../manage-receipt-search.component.scss | 0 .../manage-receipt-search.component.spec.ts | 25 + .../manage-receipt-search.component.ts | 89 + .../router/manage-receipt-router.component.ts | 15 + .../period-summary.container.html | 5 + .../period-summary.container.scss | 0 .../period-summary.container.spec.ts | 25 + .../period-summary.container.ts | 35 + .../period-summary/period-summary.module.ts | 35 + .../period-summary-list.component.html | 158 + .../period-summary-list.component.scss | 11 + .../period-summary-list.component.spec.ts | 25 + .../period-summary-list.component.ts | 90 + .../period-summary-search.component.html | 38 + .../period-summary-search.component.scss | 0 .../period-summary-search.component.spec.ts | 25 + .../period-summary-search.component.ts | 37 + .../router/period-summary-router.ts | 15 + .../receive-payment.container.html | 23 + .../receive-payment.container.scss | 0 .../receive-payment.container.spec.ts | 25 + .../receive-payment.container.ts | 93 + .../receive-payment-detail.component.html | 208 + .../receive-payment-detail.component.scss | 0 .../receive-payment-detail.component.spec.ts | 25 + .../receive-payment-detail.component.ts | 358 + .../receive-payment-list.component.html | 56 + .../receive-payment-list.component.scss | 3 + .../receive-payment-list.component.spec.ts | 25 + .../receive-payment-list.component.ts | 44 + .../receive-payment-search.component.html | 24 + .../receive-payment-search.component.scss | 0 .../receive-payment-search.component.spec.ts | 25 + .../receive-payment-search.component.ts | 33 + .../receive-payment-summary.component.html | 47 + .../receive-payment-summary.component.scss | 11 + .../receive-payment-summary.component.spec.ts | 25 + .../receive-payment-summary.component.ts | 51 + .../receive-payment/receive-payment.module.ts | 44 + .../receive-payment-router.component.ts | 15 + .../register-cancel.container.html | 8 + .../register-cancel.container.scss | 0 .../register-cancel.container.spec.ts | 25 + .../register-cancel.container.ts | 31 + .../register-cancel-list.component.html | 71 + .../register-cancel-list.component.scss | 0 .../register-cancel-list.component.spec.ts | 25 + .../register-cancel-list.component.ts | 86 + .../register-cancel-search.component.html | 19 + .../register-cancel-search.component.scss | 0 .../register-cancel-search.component.spec.ts | 25 + .../register-cancel-search.component.ts | 29 + .../register-cancel/register-cancel.module.ts | 41 + .../router/register-cancel-router.ts | 15 + .../register-summary.container.html | 45 + .../register-summary.container.scss | 0 .../register-summary.container.spec.ts | 25 + .../register-summary.container.ts | 457 + ...ialog-check-payment-counter.component.html | 25 + ...ialog-check-payment-counter.component.scss | 0 ...og-check-payment-counter.component.spec.ts | 25 + .../dialog-check-payment-counter.component.ts | 61 + .../list-payment-counter.component.html | 51 + .../list-payment-counter.component.scss | 0 .../list-payment-counter.component.spec.ts | 25 + .../list-payment-counter.component.ts | 62 + ...-enrollment-counter-payment.component.html | 32 + ...-enrollment-counter-payment.component.scss | 0 ...rollment-counter-payment.component.spec.ts | 25 + ...og-enrollment-counter-payment.component.ts | 66 + ...-enrollment-counter-payment.component.html | 40 + ...-enrollment-counter-payment.component.scss | 0 ...rollment-counter-payment.component.spec.ts | 25 + ...st-enrollment-counter-payment.component.ts | 46 + .../register-summary-form.component.html | 456 + .../register-summary-form.component.scss | 14 + .../register-summary-form.component.spec.ts | 25 + .../register-summary-form.component.ts | 1396 + .../preview-image.component.html | 4 + .../preview-image.component.scss | 4 + .../preview-image.component.spec.ts | 25 + .../preview-image/preview-image.component.ts | 41 + .../register-summary-search.component.html | 22 + .../register-summary-search.component.scss | 0 .../register-summary-search.component.spec.ts | 25 + .../register-summary-search.component.ts | 25 + .../register-summary-summary.component.html | 61 + .../register-summary-summary.component.scss | 11 + ...register-summary-summary.component.spec.ts | 25 + .../register-summary-summary.component.ts | 76 + .../table-summary.component.html | 76 + .../table-summary.component.scss | 0 .../table-summary.component.spec.ts | 25 + .../table-summary/table-summary.component.ts | 86 + .../user-counter-login.component.html | 18 + .../user-counter-login.component.scss | 0 .../user-counter-login.component.spec.ts | 25 + .../user-counter-login.component.ts | 135 + .../register-summary.module.ts | 52 + .../register-summary-router.component.ts | 15 + src/app/feature/exam-register/routes.ts | 59 + .../change-exam-information.module.ts | 56 + .../change-exam-information.container.html | 15 + .../change-exam-information.container.scss | 0 .../change-exam-information.container.spec.ts | 25 + .../change-exam-information.container.ts | 73 + ...hange-exam-information-form.component.html | 321 + ...hange-exam-information-form.component.scss | 0 ...ge-exam-information-form.component.spec.ts | 25 + .../change-exam-information-form.component.ts | 743 + ...hange-exam-information-list.component.html | 27 + ...hange-exam-information-list.component.scss | 0 ...ge-exam-information-list.component.spec.ts | 25 + .../change-exam-information-list.component.ts | 83 + .../is-main-false.component.html | 85 + .../is-main-false.component.scss | 0 .../is-main-false.component.spec.ts | 25 + .../is-main-false/is-main-false.component.ts | 57 + .../is-main-true/is-main-true.component.html | 85 + .../is-main-true/is-main-true.component.scss | 0 .../is-main-true.component.spec.ts | 25 + .../is-main-true/is-main-true.component.ts | 58 + ...nge-exam-information-search.component.html | 28 + ...nge-exam-information-search.component.scss | 0 ...-exam-information-search.component.spec.ts | 25 + ...hange-exam-information-search.component.ts | 54 + .../router/change-exam-information-router.ts | 15 + .../grade-summary.container.html | 2 + .../grade-summary.container.scss | 0 .../grade-summary.container.spec.ts | 25 + .../grade-summary/grade-summary.container.ts | 29 + .../grade-summary/grade-summary.module.ts | 65 + .../grade-dialog/grade-dialog.component.html | 13 + .../grade-dialog/grade-dialog.component.scss | 0 .../grade-dialog.component.spec.ts | 25 + .../grade-dialog/grade-dialog.component.ts | 45 + .../grade-list/grade-list.component.html | 67 + .../grade-list/grade-list.component.scss | 0 .../grade-list/grade-list.component.spec.ts | 25 + .../grade-list/grade-list.component.ts | 40 + .../grade-summary.component.html | 98 + .../grade-summary.component.scss | 0 .../grade-summary.component.spec.ts | 25 + .../grade-summary/grade-summary.component.ts | 266 + .../grade-summary-list.component.html | 64 + .../grade-summary-list.component.scss | 0 .../grade-summary-list.component.spec.ts | 25 + .../grade-summary-list.component.ts | 46 + .../grade-summary-search.component.html | 27 + .../grade-summary-search.component.scss | 0 .../grade-summary-search.component.spec.ts | 25 + .../grade-summary-search.component.ts | 48 + .../grade-summary-subject-list.component.html | 89 + .../grade-summary-subject-list.component.scss | 0 ...ade-summary-subject-list.component.spec.ts | 25 + .../grade-summary-subject-list.component.ts | 84 + .../presenter/view/view/view.component.html | 84 + .../presenter/view/view/view.component.scss | 0 .../view/view/view.component.spec.ts | 25 + .../presenter/view/view/view.component.ts | 111 + .../grade-summary/router/router.ts | 15 + .../manage-exam-officer.container.html | 12 + .../manage-exam-officer.container.scss | 0 .../manage-exam-officer.container.spec.ts | 25 + .../manage-exam-officer.container.ts | 57 + .../manage-exam-officer.module.ts | 48 + .../manage-exam-officer-detail.component.html | 101 + .../manage-exam-officer-detail.component.scss | 0 ...nage-exam-officer-detail.component.spec.ts | 25 + .../manage-exam-officer-detail.component.ts | 230 + .../manage-exam-officer-list.component.html | 86 + .../manage-exam-officer-list.component.scss | 0 ...manage-exam-officer-list.component.spec.ts | 25 + .../manage-exam-officer-list.component.ts | 49 + .../manage-exam-officer-search.component.html | 28 + .../manage-exam-officer-search.component.scss | 0 ...nage-exam-officer-search.component.spec.ts | 25 + .../manage-exam-officer-search.component.ts | 53 + .../router/manage-exam-officer-router.ts | 15 + .../random-questions.container.html | 6 + .../random-questions.container.scss | 0 .../random-questions.container.spec.ts | 25 + .../random-questions.container.ts | 26 + .../random-questions-form.container.html | 107 + .../random-questions-form.container.scss | 0 .../random-questions-form.container.spec.ts | 25 + .../random-questions-form.container.ts | 340 + .../category-list.component.html | 121 + .../category-list.component.scss | 0 .../category-list.component.spec.ts | 25 + .../category-list/category-list.component.ts | 210 + .../group-list/group-list.component.html | 63 + .../group-list/group-list.component.scss | 0 .../group-list/group-list.component.spec.ts | 25 + .../group/group-list/group-list.component.ts | 72 + .../form/type/teacher/teacher.component.html | 85 + .../form/type/teacher/teacher.component.scss | 0 .../type/teacher/teacher.component.spec.ts | 25 + .../form/type/teacher/teacher.component.ts | 141 + .../random-questions-list.component.html | 64 + .../random-questions-list.component.scss | 0 .../random-questions-list.component.spec.ts | 25 + .../random-questions-list.component.ts | 48 + .../random-list/random-list.component.html | 75 + .../random-list/random-list.component.scss | 0 .../random-list/random-list.component.spec.ts | 25 + .../random-list/random-list.component.ts | 53 + .../random-questions-search.component.html | 28 + .../random-questions-search.component.scss | 0 .../random-questions-search.component.spec.ts | 25 + .../random-questions-search.component.ts | 48 + ...ndom-questions-subject-list.component.html | 77 + ...ndom-questions-subject-list.component.scss | 0 ...m-questions-subject-list.component.spec.ts | 25 + ...random-questions-subject-list.component.ts | 99 + .../presenter/view/view/view.component.html | 235 + .../presenter/view/view/view.component.scss | 0 .../view/view/view.component.spec.ts | 25 + .../presenter/view/view/view.component.ts | 58 + .../random-questions.module.ts | 69 + .../random-questions/router/router.ts | 15 + .../extend-information-date.container.html | 10 + .../extend-information-date.container.scss | 0 .../extend-information-date.container.spec.ts | 25 + .../extend-information-date.container.ts | 66 + .../extend-information-date.module.ts | 48 + ...xtend-information-date-form.component.html | 43 + ...xtend-information-date-form.component.scss | 0 ...nd-information-date-form.component.spec.ts | 25 + ...-extend-information-date-form.component.ts | 472 + ...xtend-information-date-form.component.html | 1 + ...xtend-information-date-form.component.scss | 0 ...nd-information-date-form.component.spec.ts | 25 + .../extend-information-date-form.component.ts | 16 + ...xtend-information-date-list.component.html | 88 + ...xtend-information-date-list.component.scss | 0 ...nd-information-date-list.component.spec.ts | 25 + .../extend-information-date-list.component.ts | 69 + ...end-information-date-search.component.html | 27 + ...end-information-date-search.component.scss | 0 ...-information-date-search.component.spec.ts | 25 + ...xtend-information-date-search.component.ts | 53 + .../router/extend-information-date-router.ts | 15 + .../extend-information-room.container.html | 11 + .../extend-information-room.container.scss | 0 .../extend-information-room.container.spec.ts | 25 + .../extend-information-room.container.ts | 38 + .../extend-information-room.module.ts | 42 + ...xtend-information-room-form.component.html | 129 + ...xtend-information-room-form.component.scss | 0 ...nd-information-room-form.component.spec.ts | 25 + .../extend-information-room-form.component.ts | 651 + ...xtend-information-room-list.component.html | 88 + ...xtend-information-room-list.component.scss | 0 ...nd-information-room-list.component.spec.ts | 25 + .../extend-information-room-list.component.ts | 70 + ...end-information-room-search.component.html | 27 + ...end-information-room-search.component.scss | 0 ...-information-room-search.component.spec.ts | 25 + ...xtend-information-room-search.component.ts | 53 + .../router/extend-information-room-router.ts | 15 + .../manage-payment/confirm/confirm.module.ts | 34 + .../container/confirm/confirm.container.html | 6 + .../container/confirm/confirm.container.scss | 0 .../confirm/confirm.container.spec.ts | 25 + .../container/confirm/confirm.container.ts | 72 + .../presenter/list/list.component.html | 75 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../confirm/presenter/list/list.component.ts | 76 + .../manage-payment/confirm/router/router.ts | 15 + .../container/import/import.container.html | 1 + .../container/import/import.container.scss | 0 .../container/import/import.container.spec.ts | 25 + .../container/import/import.container.ts | 16 + .../manage-payment/import/import.module.ts | 34 + .../import/presenter/list/list.component.html | 46 + .../import/presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../import/presenter/list/list.component.ts | 75 + .../manage-payment/import/router/router.ts | 15 + .../manage-test-center-router.component.ts | 15 + .../manage-test-center.module.ts | 56 + .../presenter/dialog/copy/copy.component.html | 25 + .../presenter/dialog/copy/copy.component.scss | 0 .../dialog/copy/copy.component.spec.ts | 25 + .../presenter/dialog/copy/copy.component.ts | 143 + .../dialog/preview/preview.component.html | 26 + .../dialog/preview/preview.component.scss | 11 + .../dialog/preview/preview.component.spec.ts | 25 + .../dialog/preview/preview.component.ts | 39 + .../dialog/view-seat/view-seat.component.html | 55 + .../dialog/view-seat/view-seat.component.scss | 0 .../view-seat/view-seat.component.spec.ts | 25 + .../dialog/view-seat/view-seat.component.ts | 53 + .../manage-test-center-form.component.html | 196 + .../manage-test-center-form.component.scss | 0 .../manage-test-center-form.component.spec.ts | 25 + .../manage-test-center-form.component.ts | 376 + .../manage-test-center-list.component.html | 15 + .../manage-test-center-list.component.scss | 0 .../manage-test-center-list.component.spec.ts | 25 + .../manage-test-center-list.component.ts | 59 + .../manage-test-center-search.component.html | 49 + .../manage-test-center-search.component.scss | 1 + ...anage-test-center-search.component.spec.ts | 25 + .../manage-test-center-search.component.ts | 57 + .../manage-test-center-table.component.html | 121 + .../manage-test-center-table.component.scss | 6 + ...manage-test-center-table.component.spec.ts | 25 + .../manage-test-center-table.component.ts | 124 + ...otification-check-exam-list.container.html | 7 + ...otification-check-exam-list.container.scss | 0 ...fication-check-exam-list.container.spec.ts | 25 + .../notification-check-exam-list.container.ts | 36 + .../notification-check-exam.container.html | 14 + .../notification-check-exam.container.scss | 0 .../notification-check-exam.container.spec.ts | 25 + .../notification-check-exam.container.ts | 48 + .../notification-check-exam.module.ts | 50 + ...otification-check-exam-list.component.html | 79 + ...otification-check-exam-list.component.scss | 0 ...fication-check-exam-list.component.spec.ts | 25 + .../notification-check-exam-list.component.ts | 48 + ...tion-check-exam-list-search.component.html | 27 + ...tion-check-exam-list-search.component.scss | 0 ...n-check-exam-list-search.component.spec.ts | 25 + ...cation-check-exam-list-search.component.ts | 50 + ...ification-check-exam-dialog.component.html | 62 + ...ification-check-exam-dialog.component.scss | 11 + ...cation-check-exam-dialog.component.spec.ts | 25 + ...otification-check-exam-dialog.component.ts | 114 + ...notification-check-exam-all.component.html | 51 + ...notification-check-exam-all.component.scss | 0 ...ification-check-exam-all.component.spec.ts | 25 + .../notification-check-exam-all.component.ts | 43 + ...ification-check-exam-search.component.html | 43 + ...ification-check-exam-search.component.scss | 0 ...cation-check-exam-search.component.spec.ts | 25 + ...otification-check-exam-search.component.ts | 58 + .../router/notification-check-exam-router.ts | 15 + .../online-summary.container.html | 4 + .../online-summary.container.scss | 0 .../online-summary.container.spec.ts | 25 + .../online-summary.container.ts | 40 + .../online-summary/online-summary.module.ts | 36 + .../presenter/dialog/dialog.component.html | 59 + .../presenter/dialog/dialog.component.scss | 0 .../presenter/dialog/dialog.component.spec.ts | 25 + .../presenter/dialog/dialog.component.ts | 94 + .../presenter/list/list.component.html | 88 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 138 + .../feature/online-summary/router/router.ts | 15 + .../print-exam-card.container.html | 4 + .../print-exam-card.container.scss | 0 .../print-exam-card.container.spec.ts | 25 + .../print-exam-card.container.ts | 25 + .../presenter/info/info.component.html | 78 + .../presenter/info/info.component.scss | 0 .../presenter/info/info.component.spec.ts | 25 + .../presenter/info/info.component.ts | 45 + .../presenter/search/search.component.html | 44 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 57 + .../print-exam-card/print-exam-card.module.ts | 40 + .../feature/print-exam-card/router/router.ts | 15 + .../print-exam-result.container.html | 4 + .../print-exam-result.container.scss | 0 .../print-exam-result.container.spec.ts | 25 + .../print-exam-result.container.ts | 25 + .../presenter/search/search.component.html | 134 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 65 + .../print-exam-result.module.ts | 35 + .../print-exam-result/router/router.ts | 15 + .../container/report/report.container.html | 8 + .../container/report/report.container.scss | 0 .../container/report/report.container.spec.ts | 25 + .../container/report/report.container.ts | 760 + .../report-preview.component.html | 6 + .../report-preview.component.scss | 0 .../report-preview.component.spec.ts | 25 + .../report-preview.component.ts | 17 + ...andidate-register-by-center.component.html | 106 + ...andidate-register-by-center.component.scss | 0 ...idate-register-by-center.component.spec.ts | 25 + ...-candidate-register-by-center.component.ts | 121 + ...ndidate-register-by-subject.component.html | 45 + ...ndidate-register-by-subject.component.scss | 0 ...date-register-by-subject.component.spec.ts | 25 + ...candidate-register-by-subject.component.ts | 71 + .../report-candidate-subject.component.html | 45 + .../report-candidate-subject.component.scss | 0 ...report-candidate-subject.component.spec.ts | 25 + .../report-candidate-subject.component.ts | 69 + .../report-candidate-summary.component.html | 86 + .../report-candidate-summary.component.scss | 0 ...report-candidate-summary.component.spec.ts | 25 + .../report-candidate-summary.component.ts | 154 + .../report-candidate.component.html | 67 + .../report-candidate.component.scss | 0 .../report-candidate.component.spec.ts | 25 + .../report-candidate.component.ts | 110 + .../report-exam-detail.component.html | 23 + .../report-exam-detail.component.scss | 0 .../report-exam-detail.component.spec.ts | 25 + .../report-exam-detail.component.ts | 67 + .../report-exam-result.component.html | 64 + .../report-exam-result.component.scss | 0 .../report-exam-result.component.spec.ts | 25 + .../report-exam-result.component.ts | 124 + .../report-exam-subject.component.html | 23 + .../report-exam-subject.component.scss | 0 .../report-exam-subject.component.spec.ts | 25 + .../report-exam-subject.component.ts | 66 + .../report-exam-total.component.html | 23 + .../report-exam-total.component.scss | 0 .../report-exam-total.component.spec.ts | 25 + .../report-exam-total.component.ts | 62 + ...t-payment-and-app-by-center.component.html | 66 + ...t-payment-and-app-by-center.component.scss | 0 ...ayment-and-app-by-center.component.spec.ts | 25 + ...ort-payment-and-app-by-center.component.ts | 69 + ...-payment-and-app-by-subject.component.html | 78 + ...-payment-and-app-by-subject.component.scss | 0 ...yment-and-app-by-subject.component.spec.ts | 25 + ...rt-payment-and-app-by-subject.component.ts | 74 + .../report-receipt.component.html | 49 + .../report-receipt.component.scss | 0 .../report-receipt.component.spec.ts | 25 + .../report-receipt.component.ts | 65 + .../report-register-by-payment.component.html | 43 + .../report-register-by-payment.component.scss | 0 ...port-register-by-payment.component.spec.ts | 25 + .../report-register-by-payment.component.ts | 93 + .../report-search.component.html | 181 + .../report-search.component.scss | 0 .../report-search.component.spec.ts | 25 + .../report-search/report-search.component.ts | 129 + ...rt-separated-by-exam-center.component.html | 70 + ...rt-separated-by-exam-center.component.scss | 0 ...separated-by-exam-center.component.spec.ts | 25 + ...port-separated-by-exam-center.component.ts | 110 + ...port-setting-testing-center.component.html | 110 + ...port-setting-testing-center.component.scss | 0 ...t-setting-testing-center.component.spec.ts | 25 + ...report-setting-testing-center.component.ts | 154 + ...report-setting-testing-room.component.html | 62 + ...report-setting-testing-room.component.scss | 0 ...ort-setting-testing-room.component.spec.ts | 25 + .../report-setting-testing-room.component.ts | 95 + ...eport-signature-examination.component.html | 97 + ...eport-signature-examination.component.scss | 0 ...rt-signature-examination.component.spec.ts | 25 + .../report-signature-examination.component.ts | 180 + .../report-summary-candidate.component.html | 52 + .../report-summary-candidate.component.scss | 0 ...report-summary-candidate.component.spec.ts | 25 + .../report-summary-candidate.component.ts | 95 + ...-testing-center-information.component.html | 77 + ...-testing-center-information.component.scss | 0 ...sting-center-information.component.spec.ts | 25 + ...rt-testing-center-information.component.ts | 111 + ...report-testing-registration.component.html | 65 + ...report-testing-registration.component.scss | 0 ...ort-testing-registration.component.spec.ts | 25 + .../report-testing-registration.component.ts | 95 + ...eport-testing-seat-and-room.component.html | 74 + ...eport-testing-seat-and-room.component.scss | 0 ...rt-testing-seat-and-room.component.spec.ts | 25 + .../report-testing-seat-and-room.component.ts | 158 + src/app/feature/report/report.module.ts | 77 + .../feature/report/router/report-router.ts | 15 + .../set-exam-information.container.html | 12 + .../set-exam-information.container.scss | 0 .../set-exam-information.container.spec.ts | 25 + .../set-exam-information.container.ts | 77 + ...set-exam-information-dialog.component.html | 204 + ...set-exam-information-dialog.component.scss | 1 + ...-exam-information-dialog.component.spec.ts | 25 + .../set-exam-information-dialog.component.ts | 272 + .../set-exam-information-form.component.html | 552 + .../set-exam-information-form.component.scss | 55 + ...et-exam-information-form.component.spec.ts | 25 + .../set-exam-information-form.component.ts | 1028 + .../table-swap-subject.component.html | 100 + .../table-swap-subject.component.scss | 0 .../table-swap-subject.component.spec.ts | 25 + .../table-swap-subject.component.ts | 137 + .../set-exam-information-list.component.html | 110 + .../set-exam-information-list.component.scss | 0 ...et-exam-information-list.component.spec.ts | 25 + .../set-exam-information-list.component.ts | 75 + ...set-exam-information-search.component.html | 28 + ...set-exam-information-search.component.scss | 0 ...-exam-information-search.component.spec.ts | 25 + .../set-exam-information-search.component.ts | 53 + .../change-time-section.component.html | 44 + .../change-time-section.component.scss | 0 .../change-time-section.component.spec.ts | 25 + .../change-time-section.component.ts | 86 + .../set-exam-information-view.component.html | 232 + .../set-exam-information-view.component.scss | 0 ...et-exam-information-view.component.spec.ts | 25 + .../set-exam-information-view.component.ts | 216 + ...ng-exam-view-table-calendar.component.html | 51 + ...ng-exam-view-table-calendar.component.scss | 0 ...exam-view-table-calendar.component.spec.ts | 25 + ...ting-exam-view-table-calendar.component.ts | 26 + ...ting-exam-view-table-center.component.html | 87 + ...ting-exam-view-table-center.component.scss | 0 ...g-exam-view-table-center.component.spec.ts | 25 + ...etting-exam-view-table-center.component.ts | 71 + ...ing-exam-view-table-section.component.html | 60 + ...ing-exam-view-table-section.component.scss | 0 ...-exam-view-table-section.component.spec.ts | 25 + ...tting-exam-view-table-section.component.ts | 57 + ...ing-exam-view-table-subject.component.html | 48 + ...ing-exam-view-table-subject.component.scss | 0 ...-exam-view-table-subject.component.spec.ts | 25 + ...tting-exam-view-table-subject.component.ts | 50 + ...-view-table-summary-subject.component.html | 74 + ...-view-table-summary-subject.component.scss | 0 ...ew-table-summary-subject.component.spec.ts | 25 + ...ng-view-table-summary-subject.component.ts | 36 + .../router/set-exam-information-router.ts | 15 + .../set-exam-information.module.ts | 80 + .../create-user/create-user.container.html | 7 + .../create-user/create-user.container.scss | 0 .../create-user/create-user.container.spec.ts | 25 + .../create-user/create-user.container.ts | 43 + .../create-user/create-user.module.ts | 46 + .../presenter/form/form/form.component.html | 75 + .../presenter/form/form/form.component.scss | 4 + .../form/form/form.component.spec.ts | 25 + .../presenter/form/form/form.component.ts | 111 + .../presenter/list/list/list.component.html | 44 + .../presenter/list/list/list.component.scss | 0 .../list/list/list.component.spec.ts | 25 + .../presenter/list/list/list.component.ts | 36 + .../search/search/search.component.html | 20 + .../search/search/search.component.scss | 0 .../search/search/search.component.spec.ts | 25 + .../search/search/search.component.ts | 42 + .../create-user/router/router.ts | 15 + .../set-role/set-role.container.html | 5 + .../set-role/set-role.container.scss | 0 .../set-role/set-role.container.spec.ts | 25 + .../container/set-role/set-role.container.ts | 43 + .../set-role-form.component.html | 82 + .../set-role-form.component.scss | 0 .../set-role-form.component.spec.ts | 25 + .../set-role-form/set-role-form.component.ts | 180 + .../set-role-list.component.html | 40 + .../set-role-list.component.scss | 0 .../set-role-list.component.spec.ts | 25 + .../set-role-list/set-role-list.component.ts | 36 + .../set-role-search.component.html | 20 + .../set-role-search.component.scss | 0 .../set-role-search.component.spec.ts | 25 + .../set-role-search.component.ts | 42 + .../set-permission/set-role/router/router.ts | 15 + .../set-role/set-role.module.ts | 46 + .../set-user/set-user.container.html | 7 + .../set-user/set-user.container.scss | 0 .../set-user/set-user.container.spec.ts | 25 + .../container/set-user/set-user.container.ts | 44 + .../presenter/form/form/form.component.html | 55 + .../presenter/form/form/form.component.scss | 0 .../form/form/form.component.spec.ts | 25 + .../presenter/form/form/form.component.ts | 113 + .../presenter/list/list/list.component.html | 40 + .../presenter/list/list/list.component.scss | 0 .../list/list/list.component.spec.ts | 25 + .../presenter/list/list/list.component.ts | 36 + .../search/search/search.component.html | 20 + .../search/search/search.component.scss | 0 .../search/search/search.component.spec.ts | 25 + .../search/search/search.component.ts | 42 + .../set-permission/set-user/router/router.ts | 15 + .../set-user/set-user.module.ts | 46 + .../user-couter/user-couter.container.html | 10 + .../user-couter/user-couter.container.scss | 0 .../user-couter/user-couter.container.spec.ts | 25 + .../user-couter/user-couter.container.ts | 55 + .../user-couter-form.component.html | 113 + .../user-couter-form.component.scss | 0 .../user-couter-form.component.spec.ts | 25 + .../user-couter-form.component.ts | 191 + .../user-couter-list.component.html | 45 + .../user-couter-list.component.scss | 0 .../user-couter-list.component.spec.ts | 25 + .../user-couter-list.component.ts | 34 + .../user-couter-search.component.html | 32 + .../user-couter-search.component.scss | 0 .../user-couter-search.component.spec.ts | 25 + .../user-couter-search.component.ts | 44 + .../user-couter-router/user-couter-router.ts | 15 + .../user-couter/user-couter.module.ts | 54 + .../setting-exam/setting-exam.container.html | 11 + .../setting-exam/setting-exam.container.scss | 0 .../setting-exam.container.spec.ts | 25 + .../setting-exam/setting-exam.container.ts | 43 + .../setting-exam-form.component.html | 122 + .../setting-exam-form.component.scss | 0 .../setting-exam-form.component.spec.ts | 25 + .../setting-exam-form.component.ts | 218 + .../setting-exam-list.component.html | 77 + .../setting-exam-list.component.scss | 0 .../setting-exam-list.component.spec.ts | 25 + .../setting-exam-list.component.ts | 55 + .../setting-exam-search.component.html | 30 + .../setting-exam-search.component.scss | 0 .../setting-exam-search.component.spec.ts | 25 + .../setting-exam-search.component.ts | 41 + .../router/setting-exam-router.ts | 15 + .../setting-exam/setting-exam.module.ts | 46 + .../setting-print-card.container.html | 1 + .../setting-print-card.container.scss | 0 .../setting-print-card.container.spec.ts | 25 + .../setting-print-card.container.ts | 16 + .../presenter/search/search.component.html | 56 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 62 + .../setting-print-card/router/router.ts | 15 + .../setting-print-card.module.ts | 34 + .../exam-finance/exam-finance.container.html | 9 + .../exam-finance/exam-finance.container.scss | 0 .../exam-finance.container.spec.ts | 25 + .../exam-finance/exam-finance.container.ts | 47 + .../exam-finance/exam-finance.module.ts | 48 + .../exam-finance-dialog.component.html | 30 + .../exam-finance-dialog.component.scss | 0 .../exam-finance-dialog.component.spec.ts | 25 + .../exam-finance-dialog.component.ts | 63 + .../exam-finance-info.component.html | 79 + .../exam-finance-info.component.scss | 0 .../exam-finance-info.component.spec.ts | 25 + .../exam-finance-info.component.ts | 83 + .../exam-finance-list.component.html | 29 + .../exam-finance-list.component.scss | 0 .../exam-finance-list.component.spec.ts | 25 + .../exam-finance-list.component.ts | 41 + .../finance-is-main-false.component.html | 78 + .../finance-is-main-false.component.scss | 0 .../finance-is-main-false.component.spec.ts | 25 + .../finance-is-main-false.component.ts | 55 + .../finance-is-main-true.component.html | 83 + .../finance-is-main-true.component.scss | 0 .../finance-is-main-true.component.spec.ts | 25 + .../finance-is-main-true.component.ts | 57 + .../exam-finance-search.component.html | 21 + .../exam-finance-search.component.scss | 0 .../exam-finance-search.component.spec.ts | 25 + .../exam-finance-search.component.ts | 40 + .../router/exam-finance-router.ts | 15 + .../invigilate-finance.container.html | 10 + .../invigilate-finance.container.scss | 0 .../invigilate-finance.container.spec.ts | 25 + .../invigilate-finance.container.ts | 56 + .../invigilate-finance.module.ts | 48 + ...vigilate-finance-form-array.component.html | 48 + ...vigilate-finance-form-array.component.scss | 0 ...ilate-finance-form-array.component.spec.ts | 25 + ...invigilate-finance-form-array.component.ts | 40 + .../invigilate-finance-form.component.html | 112 + .../invigilate-finance-form.component.scss | 58 + .../invigilate-finance-form.component.spec.ts | 25 + .../invigilate-finance-form.component.ts | 287 + .../invigilate-finance-list.component.html | 58 + .../invigilate-finance-list.component.scss | 0 .../invigilate-finance-list.component.spec.ts | 25 + .../invigilate-finance-list.component.ts | 38 + .../invigilate-finance-search.component.html | 37 + .../invigilate-finance-search.component.scss | 34 + ...nvigilate-finance-search.component.spec.ts | 25 + .../invigilate-finance-search.component.ts | 39 + .../router/invigilate-finance-router.ts | 15 + src/app/feature/settings-finance/routes.ts | 28 + .../teacher-finance.container.html | 10 + .../teacher-finance.container.scss | 0 .../teacher-finance.container.spec.ts | 25 + .../teacher-finance.container.ts | 61 + .../teacher-finance-form.component.html | 73 + .../teacher-finance-form.component.scss | 0 .../teacher-finance-form.component.spec.ts | 25 + .../teacher-finance-form.component.ts | 130 + .../teacher-finance-list.component.html | 53 + .../teacher-finance-list.component.scss | 0 .../teacher-finance-list.component.spec.ts | 25 + .../teacher-finance-list.component.ts | 34 + .../teacher-finance-search.component.html | 30 + .../teacher-finance-search.component.scss | 0 .../teacher-finance-search.component.spec.ts | 25 + .../teacher-finance-search.component.ts | 41 + .../router/teacher-finance-router.ts | 15 + .../teacher-finance/teacher-finance.module.ts | 46 + .../academic-semesters.module.ts | 38 + .../academic-semesters.container.html | 9 + .../academic-semesters.container.scss | 0 .../academic-semesters.container.spec.ts | 25 + .../academic-semesters.container.ts | 69 + .../academic-semesters-dialog.component.html | 24 + .../academic-semesters-dialog.component.scss | 0 ...cademic-semesters-dialog.component.spec.ts | 25 + .../academic-semesters-dialog.component.ts | 80 + .../academic-semesters-list.component.html | 48 + .../academic-semesters-list.component.scss | 0 .../academic-semesters-list.component.spec.ts | 25 + .../academic-semesters-list.component.ts | 35 + .../academic-semesters-search.component.html | 15 + .../academic-semesters-search.component.scss | 0 ...cademic-semesters-search.component.spec.ts | 25 + .../academic-semesters-search.component.ts | 38 + .../router/academic-semesters-router.ts | 15 + .../academic-years/academic-years.module.ts | 38 + .../academic-years.container.html | 9 + .../academic-years.container.scss | 0 .../academic-years.container.spec.ts | 25 + .../academic-years.container.ts | 69 + .../academic-years-dialog.component.html | 24 + .../academic-years-dialog.component.scss | 0 .../academic-years-dialog.component.spec.ts | 25 + .../academic-years-dialog.component.ts | 78 + .../academic-years-list.component.html | 48 + .../academic-years-list.component.scss | 0 .../academic-years-list.component.spec.ts | 25 + .../academic-years-list.component.ts | 34 + .../academic-years-search.component.html | 15 + .../academic-years-search.component.scss | 0 .../academic-years-search.component.spec.ts | 25 + .../academic-years-search.component.ts | 38 + .../router/academic-years-router.ts | 15 + .../settings/calendars/calendars.module.ts | 38 + .../calendars/calendars.container.html | 9 + .../calendars/calendars.container.scss | 0 .../calendars/calendars.container.spec.ts | 25 + .../calendars/calendars.container.ts | 69 + .../calendar-dialog.component.html | 24 + .../calendar-dialog.component.scss | 3 + .../calendar-dialog.component.spec.ts | 25 + .../calendar-dialog.component.ts | 77 + .../calendar-list.component.html | 48 + .../calendar-list.component.scss | 0 .../calendar-list.component.spec.ts | 25 + .../calendar-list/calendar-list.component.ts | 37 + .../calendar-search.component.html | 15 + .../calendar-search.component.scss | 0 .../calendar-search.component.spec.ts | 25 + .../calendar-search.component.ts | 36 + .../calendars/router/calendars-router.ts | 15 + .../department/department.container.html | 9 + .../department/department.container.scss | 0 .../department/department.container.spec.ts | 25 + .../department/department.container.ts | 74 + .../settings/department/department.module.ts | 37 + .../department-dialog.component.html | 41 + .../department-dialog.component.scss | 0 .../department-dialog.component.spec.ts | 25 + .../department-dialog.component.ts | 92 + .../department-list.component.html | 63 + .../department-list.component.scss | 0 .../department-list.component.spec.ts | 25 + .../department-list.component.ts | 39 + .../department-search.component.html | 35 + .../department-search.component.scss | 0 .../department-search.component.spec.ts | 25 + .../department-search.component.ts | 66 + .../department/router/department-router.ts | 15 + .../education-type.container.html | 9 + .../education-type.container.scss | 0 .../education-type.container.spec.ts | 25 + .../education-type.container.ts | 70 + .../education-type/education-type.module.ts | 39 + .../education-type-dialog.component.html | 24 + .../education-type-dialog.component.scss | 0 .../education-type-dialog.component.spec.ts | 25 + .../education-type-dialog.component.ts | 79 + .../education-type-list.component.html | 48 + .../education-type-list.component.scss | 0 .../education-type-list.component.spec.ts | 25 + .../education-type-list.component.ts | 35 + .../education-type-search.component.html | 15 + .../education-type-search.component.scss | 0 .../education-type-search.component.spec.ts | 25 + .../education-type-search.component.ts | 36 + .../router/education-type-router.ts | 15 + .../faculties/faculties.container.html | 9 + .../faculties/faculties.container.scss | 0 .../faculties/faculties.container.spec.ts | 25 + .../faculties/faculties.container.ts | 69 + .../settings/faculties/faculties.module.ts | 38 + .../faculty-dialog.component.html | 24 + .../faculty-dialog.component.scss | 0 .../faculty-dialog.component.spec.ts | 25 + .../faculty-dialog.component.ts | 77 + .../faculties-list.component.html | 48 + .../faculties-list.component.scss | 0 .../faculties-list.component.spec.ts | 25 + .../faculties-list.component.ts | 34 + .../faculties-search.component.html | 15 + .../faculties-search.component.scss | 0 .../faculties-search.component.spec.ts | 25 + .../faculties-search.component.ts | 36 + .../faculties/router/faculties-router.ts | 15 + .../online-counter.container.html | 9 + .../online-counter.container.scss | 0 .../online-counter.container.spec.ts | 25 + .../online-counter.container.ts | 70 + .../online-counter/online-counter.module.ts | 38 + .../form-dialog/form-dialog.component.html | 25 + .../form-dialog/form-dialog.component.scss | 0 .../form-dialog/form-dialog.component.spec.ts | 25 + .../form-dialog/form-dialog.component.ts | 84 + .../presenter/list/list.component.html | 54 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 54 + .../presenter/search/search.component.html | 14 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 35 + .../settings/online-counter/router/router.ts | 15 + .../signature/signature.container.html | 9 + .../signature/signature.container.scss | 0 .../signature/signature.container.spec.ts | 25 + .../signature/signature.container.ts | 70 + .../form-dialog/form-dialog.component.html | 39 + .../form-dialog/form-dialog.component.scss | 0 .../form-dialog/form-dialog.component.spec.ts | 25 + .../form-dialog/form-dialog.component.ts | 110 + .../presenter/list/list.component.html | 54 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 55 + .../presenter/search/search.component.html | 14 + .../presenter/search/search.component.scss | 0 .../presenter/search/search.component.spec.ts | 25 + .../presenter/search/search.component.ts | 35 + .../settings/signature/router/router.ts | 15 + .../settings/signature/signature.module.ts | 39 + .../testcenter/testcenter.container.html | 10 + .../testcenter/testcenter.container.scss | 0 .../testcenter/testcenter.container.spec.ts | 25 + .../testcenter/testcenter.container.ts | 76 + .../testcenter-dialog.component.html | 54 + .../testcenter-dialog.component.scss | 0 .../testcenter-dialog.component.spec.ts | 25 + .../testcenter-dialog.component.ts | 116 + .../testcenter-list.component.html | 58 + .../testcenter-list.component.scss | 0 .../testcenter-list.component.spec.ts | 25 + .../testcenter-list.component.ts | 64 + .../testcenter-search.component.html | 39 + .../testcenter-search.component.scss | 0 .../testcenter-search.component.spec.ts | 25 + .../testcenter-search.component.ts | 80 + .../testcenter/router/testcenter-router.ts | 15 + .../settings/testcenter/testcenter.module.ts | 38 + .../testing-field.container.html | 10 + .../testing-field.container.scss | 0 .../testing-field.container.spec.ts | 25 + .../testing-field/testing-field.container.ts | 72 + .../testing-field-dialog.component.html | 42 + .../testing-field-dialog.component.scss | 0 .../testing-field-dialog.component.spec.ts | 25 + .../testing-field-dialog.component.ts | 108 + .../testing-field-list.component.html | 58 + .../testing-field-list.component.scss | 0 .../testing-field-list.component.spec.ts | 25 + .../testing-field-list.component.ts | 65 + .../testing-field-search.component.html | 25 + .../testing-field-search.component.scss | 0 .../testing-field-search.component.spec.ts | 25 + .../testing-field-search.component.ts | 51 + .../router/testing-field-router.ts | 15 + .../testing-field/testing-field.module.ts | 38 + .../testing-vdos/testing-vdos.container.html | 10 + .../testing-vdos/testing-vdos.container.scss | 0 .../testing-vdos.container.spec.ts | 25 + .../testing-vdos/testing-vdos.container.ts | 63 + .../testing-vdos-form.component.html | 68 + .../testing-vdos-form.component.scss | 0 .../testing-vdos-form.component.spec.ts | 25 + .../testing-vdos-form.component.ts | 110 + .../testing-vdos-list.component.html | 73 + .../testing-vdos-list.component.scss | 0 .../testing-vdos-list.component.spec.ts | 25 + .../testing-vdos-list.component.ts | 88 + .../testing-vdos-search.component.html | 20 + .../testing-vdos-search.component.scss | 0 .../testing-vdos-search.component.spec.ts | 25 + .../testing-vdos-search.component.ts | 40 + .../router/testing-vdos-router.ts | 14 + .../testing-vdos/testing-vdos.module.ts | 46 + .../typesubject/typesubject.container.html | 12 + .../typesubject/typesubject.container.scss | 0 .../typesubject/typesubject.container.spec.ts | 25 + .../typesubject/typesubject.container.ts | 71 + .../typesubject-dialog.component.html | 22 + .../typesubject-dialog.component.scss | 0 .../typesubject-dialog.component.spec.ts | 25 + .../typesubject-dialog.component.ts | 78 + .../typesubject-list.component.html | 48 + .../typesubject-list.component.scss | 0 .../typesubject-list.component.spec.ts | 25 + .../typesubject-list.component.ts | 37 + .../typesubject-search.component.html | 15 + .../typesubject-search.component.scss | 0 .../typesubject-search.component.spec.ts | 25 + .../typesubject-search.component.ts | 35 + .../typesubject/router/typesubject-router.ts | 15 + .../typesubject/typesubject.module.ts | 40 + .../student-info/student-info.container.html | 6 + .../student-info/student-info.container.scss | 0 .../student-info/student-info.container.ts | 47 + .../presenter/form/form/form.component.html | 145 + .../presenter/form/form/form.component.scss | 0 .../form/form/form.component.spec.ts | 25 + .../presenter/form/form/form.component.ts | 130 + .../presenter/list/list.component.html | 71 + .../presenter/list/list.component.scss | 0 .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 115 + .../search/search/search.component.html | 1 + .../search/search/search.component.scss | 0 .../search/search/search.component.spec.ts | 25 + .../search/search/search.component.ts | 16 + src/app/feature/student-info/router/router.ts | 15 + .../student-info/student-info.module.ts | 42 + .../testing-info/testing-info.container.html | 2 + .../testing-info/testing-info.container.scss | 0 .../testing-info.container.spec.ts | 25 + .../testing-info/testing-info.container.ts | 34 + .../upload-student.container.html | 6 + .../upload-student.container.scss | 0 .../upload-student.container.spec.ts | 25 + .../upload-student.container.ts | 43 + .../presenter/list/list.component.html | 193 + .../presenter/list/list.component.scss | 5 + .../presenter/list/list.component.spec.ts | 25 + .../presenter/list/list.component.ts | 291 + .../search/search/search.component.html | 1 + .../search/search/search.component.scss | 0 .../search/search/search.component.spec.ts | 25 + .../search/search/search.component.ts | 16 + .../template-dialog.component.html | 26 + .../template-dialog.component.scss | 4 + .../template-dialog.component.spec.ts | 25 + .../template-dialog.component.ts | 47 + .../testing-info-list.component.html | 73 + .../testing-info-list.component.scss | 0 .../testing-info-list.component.spec.ts | 25 + .../testing-info-list.component.ts | 48 + .../testing-info-search.component.html | 29 + .../testing-info-search.component.scss | 0 .../testing-info-search.component.spec.ts | 25 + .../testing-info-search.component.ts | 54 + .../upload-dialog.component.html | 18 + .../upload-dialog.component.scss | 0 .../upload-dialog.component.spec.ts | 25 + .../upload-dialog/upload-dialog.component.ts | 85 + .../feature/upload-student/router/router.ts | 15 + .../upload-student/upload-student.module.ts | 51 + .../main-layout/main-layout.component.html | 13 + .../main-layout/main-layout.component.scss | 20 + .../main-layout/main-layout.component.spec.ts | 25 + .../main-layout/main-layout.component.ts | 16 + src/app/layout/menu/menu/menu.component.html | 491 + src/app/layout/menu/menu/menu.component.scss | 76 + .../layout/menu/menu/menu.component.spec.ts | 25 + src/app/layout/menu/menu/menu.component.ts | 44 + .../toolbar/toolbar/toolbar.component.html | 22 + .../toolbar/toolbar/toolbar.component.scss | 4 + .../toolbar/toolbar/toolbar.component.spec.ts | 25 + .../toolbar/toolbar/toolbar.component.ts | 42 + src/app/shared/animations/animation.ts | 0 src/app/shared/components/README.md | 1 + .../shared/directives/demo.directive.spec.ts | 8 + src/app/shared/directives/demo.directive.ts | 10 + .../directives/email-input.directive.ts | 29 + src/app/shared/directives/input.directive.ts | 29 + .../directives/limit-length.directive.ts | 22 + .../directives/only-number.directive.ts | 24 + src/app/shared/models/user.ts | 0 ...heck-form-exam-information-section.pipe.ts | 19 + .../pipes/checkseat/cheakseatall.pipe.ts | 39 + .../checkseat/checkdupicateallseat.pipe.ts | 58 + .../pipes/checkseat/checkdupicateseat.pipe.ts | 48 + .../shared/pipes/checkseat/checkfield.pipe.ts | 25 + .../pipes/checkseat/checkinrange.pipe.ts | 23 + .../checkseat/checkinrangeallseat.pipe.ts | 56 + .../checkseat/checklessmoreallseat.pipe.ts | 26 + .../pipes/checkseat/checklessmoreseat.pipe.ts | 19 + .../pipes/checkseat/checkmaxseat.pipe.ts | 30 + .../shared/pipes/checkseat/checkseat.pipe.ts | 20 + src/app/shared/pipes/demo.pipe.spec.ts | 8 + src/app/shared/pipes/demo.pipe.ts | 12 + .../shared/pipes/getdata/get-data-id.pipe.ts | 31 + .../previewfile/preview-file.pipe.spec.ts | 9 + .../pipes/previewfile/preview-file.pipe.ts | 15 + src/app/shared/pipes/role/role.pipe.ts | 30 + .../pipes/search-auto/search-auto.pipe.ts | 23 + .../pipes/search-auto/search-autov2.pipe.ts | 13 + src/app/shared/pipes/thaidate/thaidate..ts | 28 + src/app/shared/shared.module.ts | 194 + src/app/shared/util/func.ts | 31 + .../validator/real-citizen-id.validator.ts | 43 + src/app/state/app-reducer.ts | 9 + src/assets/.gitkeep | 0 src/assets/images/preview.png | Bin 0 -> 7276 bytes src/assets/logo/default.png | Bin 0 -> 452970 bytes src/assets/logo/etest-logo.png | Bin 0 -> 31855 bytes .../templates/ru_student_template_paid.xlsx | Bin 0 -> 10029 bytes .../templates/ru_student_template_wait.xlsx | Bin 0 -> 10019 bytes src/assets/templates/student_import.xlsx | Bin 0 -> 9892 bytes src/environments/environment.prod.ts | 20 + src/environments/environment.ru.ts | 20 + src/environments/environment.ts | 20 + src/favicon.ico | Bin 0 -> 1150 bytes src/index.html | 18 + src/main.ts | 12 + src/polyfills.ts | 63 + src/styles.scss | 483 + src/test.ts | 20 + tailwind.config.js | 50 + tsconfig.app.json | 14 + tsconfig.json | 23 + tsconfig.spec.json | 18 + tslint.json | 155 + webpack.config.js | 11 + 1635 files changed, 104192 insertions(+) create mode 100644 .browserslistrc create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 angular.json create mode 100644 bitbucket-pipelines.yml create mode 100644 e2e/protractor.conf.js create mode 100644 e2e/src/app.e2e-spec.ts create mode 100644 e2e/src/app.po.ts create mode 100644 e2e/tsconfig.json create mode 100644 karma.conf.js create mode 100644 nginx.conf create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 report.20210410.171439.4055.0.001.json create mode 100644 src/app/app-routing.module.ts create mode 100644 src/app/app.component.html create mode 100644 src/app/app.component.scss create mode 100644 src/app/app.component.spec.ts create mode 100644 src/app/app.component.ts create mode 100644 src/app/app.module.ts create mode 100644 src/app/core/base/base-form-uid.ts create mode 100644 src/app/core/base/base-form.ts create mode 100644 src/app/core/base/base-list-role.ts create mode 100644 src/app/core/base/base-list.ts create mode 100644 src/app/core/base/base-openid-service.ts create mode 100644 src/app/core/base/base-service.ts create mode 100644 src/app/core/base/base-sub-list.ts create mode 100644 src/app/core/base/tinymce.ts create mode 100644 src/app/core/configs/config.ts create mode 100644 src/app/core/core.module.ts create mode 100644 src/app/core/enum/role.ts create mode 100644 src/app/core/guards/auth.guard.spec.ts create mode 100644 src/app/core/guards/auth.guard.ts create mode 100644 src/app/core/intercepter/token-intercepter.interceptor.spec.ts create mode 100644 src/app/core/intercepter/token-intercepter.interceptor.ts create mode 100644 src/app/core/service/TestingCenter/testing-center.service.spec.ts create mode 100644 src/app/core/service/TestingCenter/testing-center.service.ts create mode 100644 src/app/core/service/app.service.spec.ts create mode 100644 src/app/core/service/app.service.ts create mode 100644 src/app/core/service/card-print/card-printing-time.service.ts create mode 100644 src/app/core/service/card-print/card-printing.service.ts create mode 100644 src/app/core/service/card-print/testing-score.service.ts create mode 100644 src/app/core/service/enrollment-api/candidate-type.service.ts create mode 100644 src/app/core/service/enrollment-api/testing-register-enrollment.service.ts create mode 100644 src/app/core/service/oidc/oidc.service.ts create mode 100644 src/app/core/service/openid/user.service.ts create mode 100644 src/app/core/service/permission/user-counter-login.service.ts create mode 100644 src/app/core/service/permission/user-counters.service.ts create mode 100644 src/app/core/service/province/provice.service.ts create mode 100644 src/app/core/service/question/question-category.service.ts create mode 100644 src/app/core/service/region/region.service.ts create mode 100644 src/app/core/service/report/candidate-registered-by-center/candidate-registered-by-center.service.ts create mode 100644 src/app/core/service/report/candidate-registered-by-subject/candidate-registered-by-subject.service.ts create mode 100644 src/app/core/service/report/candidate-subject/candidate-subject.service.ts create mode 100644 src/app/core/service/report/candidate/candidate.service.ts create mode 100644 src/app/core/service/report/daily-register/daily-register-payment-total.service.ts create mode 100644 src/app/core/service/report/daily-register/daily-register-payment.service.ts create mode 100644 src/app/core/service/report/eligible_candidate/eligible-candidate.service.ts create mode 100644 src/app/core/service/report/exam-card-print/testing-card.service.ts create mode 100644 src/app/core/service/report/exam-result-print/exam-result-print.service.ts create mode 100644 src/app/core/service/report/exam-result-subject/exam-result-subject.service.ts create mode 100644 src/app/core/service/report/exam_total/exam-total.service.ts create mode 100644 src/app/core/service/report/excel-all-test/excel-all-test.service.ts create mode 100644 src/app/core/service/report/invigilator-cost/report-invigilator-cost.service.ts create mode 100644 src/app/core/service/report/payment-and-application-by-center/payment-and-application-by-center.service.ts create mode 100644 src/app/core/service/report/payment-and-application-by-subject/payment-and-application-by-subject.service.ts create mode 100644 src/app/core/service/report/period-register/period-register-payment-online.service.ts create mode 100644 src/app/core/service/report/period-register/period-register-payment.service.ts create mode 100644 src/app/core/service/report/receipt-by-payment-code/receipt-by-payment-code.service.ts create mode 100644 src/app/core/service/report/receiptAll/receipt-all.service.ts create mode 100644 src/app/core/service/report/reciept/reciept.service.ts create mode 100644 src/app/core/service/report/register-by-payment/register-by-payment.service.ts create mode 100644 src/app/core/service/report/separated-by-exam-center/separated-by-exam-center.service.ts create mode 100644 src/app/core/service/report/setting-testing-center/setting-testing-center.service.ts create mode 100644 src/app/core/service/report/setting-testing-room/setting-testing-room.service.ts create mode 100644 src/app/core/service/report/signature-examination/signature-examination.service.ts create mode 100644 src/app/core/service/report/summary-candidate/summary-candidate.service.ts create mode 100644 src/app/core/service/report/summary-candidates-absentees-passers/summary-candidates-absentees-passers.service.ts create mode 100644 src/app/core/service/report/testing-center-information/testing-center-information.service.ts create mode 100644 src/app/core/service/report/testing-registration/testing-registration.service.ts create mode 100644 src/app/core/service/report/testing-room/testing-room.service.ts create mode 100644 src/app/core/service/report/testing-seat-and-room/testing-seat-and-room.service.ts create mode 100644 src/app/core/service/report/testing-subject/tesing-subject.service.ts create mode 100644 src/app/core/service/ru-student/ru-student-registers.service.ts create mode 100644 src/app/core/service/ru-student/ru-student.service.ts create mode 100644 src/app/core/service/security/app-object.service.ts create mode 100644 src/app/core/service/security/app-permission.service.ts create mode 100644 src/app/core/service/security/app-role.service.ts create mode 100644 src/app/core/service/security/app-token.service.ts create mode 100644 src/app/core/service/security/app-user.service.ts create mode 100644 src/app/core/service/settingPayment/insturctor-payment-accout.service.ts create mode 100644 src/app/core/service/settingPayment/invigilator-cost.service.ts create mode 100644 src/app/core/service/settings/academic-semester.service.ts create mode 100644 src/app/core/service/settings/academic-year.service.ts create mode 100644 src/app/core/service/settings/branch.service.ts create mode 100644 src/app/core/service/settings/calendar-type.service.ts create mode 100644 src/app/core/service/settings/department.service.ts create mode 100644 src/app/core/service/settings/education-types.service.ts create mode 100644 src/app/core/service/settings/facultys.service.ts create mode 100644 src/app/core/service/settings/online-counters.service.ts create mode 100644 src/app/core/service/settings/recipient-signature.service.ts create mode 100644 src/app/core/service/settings/subject-types.service.ts create mode 100644 src/app/core/service/settings/subjects.service.ts create mode 100644 src/app/core/service/settings/testing-field.service.ts create mode 100644 src/app/core/service/settings/testing-vdos.service.ts create mode 100644 src/app/core/service/store-api/subject-information.service.ts create mode 100644 src/app/core/service/store-api/sync.service.ts create mode 100644 src/app/core/service/student-payment/student-payment-confirm.service.ts create mode 100644 src/app/core/service/student-payment/student-payment-not-paid.service.ts create mode 100644 src/app/core/service/student-payment/student-payment.service.ts create mode 100644 src/app/core/service/student-payment/student-upload.service.ts create mode 100644 src/app/core/service/student/delete-import-student.service.ts create mode 100644 src/app/core/service/student/generate-group-seat-detail.service.ts create mode 100644 src/app/core/service/student/generate-group.service.ts create mode 100644 src/app/core/service/student/getstudent.service.ts create mode 100644 src/app/core/service/student/reset-seat.service.ts create mode 100644 src/app/core/service/student/student-generate-register.service.ts create mode 100644 src/app/core/service/student/student-generate-seat.service.ts create mode 100644 src/app/core/service/student/student-upload.service.ts create mode 100644 src/app/core/service/student/student.service.ts create mode 100644 src/app/core/service/sweetalert/sweetalert.ts create mode 100644 src/app/core/service/sync/sync.service.ts create mode 100644 src/app/core/service/testing-information/exam-notification.service.ts create mode 100644 src/app/core/service/testing-information/grading.service.ts create mode 100644 src/app/core/service/testing-information/random-questions.service.ts create mode 100644 src/app/core/service/testing-information/room-invigilators.service.ts create mode 100644 src/app/core/service/testing-information/testing-controls.service.ts create mode 100644 src/app/core/service/testing-information/testing-fee.service.ts create mode 100644 src/app/core/service/testing-information/testing-information.service.ts create mode 100644 src/app/core/service/testing-information/testing-period.service.ts create mode 100644 src/app/core/service/testing-information/testing-subject-add-date.service.ts create mode 100644 src/app/core/service/testing-register/candidate-payment-status.service.ts create mode 100644 src/app/core/service/testing-register/change-testing-date.service.ts create mode 100644 src/app/core/service/testing-register/change-testing-room-and-date.service.ts create mode 100644 src/app/core/service/testing-register/change-testing-room.service.ts create mode 100644 src/app/core/service/testing-register/check-available-room-and-period.service.ts create mode 100644 src/app/core/service/testing-register/check-available-room-no-condition.service.ts create mode 100644 src/app/core/service/testing-register/check-available-room.service.ts create mode 100644 src/app/core/service/testing-register/check-available-seat.service.ts create mode 100644 src/app/core/service/testing-register/check-subject-and-date.service.ts create mode 100644 src/app/core/service/testing-register/daily-summary-ttb.service.ts create mode 100644 src/app/core/service/testing-register/daily-summary.service.ts create mode 100644 src/app/core/service/testing-register/enrollment-counter-payments.service.ts create mode 100644 src/app/core/service/testing-register/period-summary.service.ts create mode 100644 src/app/core/service/testing-register/shared-usercouter.service.ts create mode 100644 src/app/core/service/testing-register/testing-reciept.service.ts create mode 100644 src/app/core/service/testing-register/testing-register-is-pay.service.ts create mode 100644 src/app/core/service/testing-register/testing-register.service.ts create mode 100644 src/app/core/service/testing-register/update-testing-seat.service.ts create mode 100644 src/app/core/service/testing-register/v-eligible-candidates.service.ts create mode 100644 src/app/core/service/upload/upload.service.ts create mode 100644 src/app/core/service/user/user.service.ts create mode 100644 src/app/feature/approve-examination/approve-examination.module.ts create mode 100644 src/app/feature/approve-examination/container/approve-examination/approve-examination.container.html create mode 100644 src/app/feature/approve-examination/container/approve-examination/approve-examination.container.scss create mode 100644 src/app/feature/approve-examination/container/approve-examination/approve-examination.container.spec.ts create mode 100644 src/app/feature/approve-examination/container/approve-examination/approve-examination.container.ts create mode 100644 src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.html create mode 100644 src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.scss create mode 100644 src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.spec.ts create mode 100644 src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.ts create mode 100644 src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.html create mode 100644 src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.scss create mode 100644 src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.spec.ts create mode 100644 src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.ts create mode 100644 src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.html create mode 100644 src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.scss create mode 100644 src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.spec.ts create mode 100644 src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.ts create mode 100644 src/app/feature/approve-examination/router/approve-examination-router.ts create mode 100644 src/app/feature/auth-callback/auth-callback.module.ts create mode 100644 src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.html create mode 100644 src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.scss create mode 100644 src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.spec.ts create mode 100644 src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.ts create mode 100644 src/app/feature/auth-callback/router/router.ts create mode 100644 src/app/feature/candidate-list/candidate-list/candidate-list.module.ts create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.html create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.scss create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.ts create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.html create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.scss create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.html create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.scss create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.ts create mode 100644 src/app/feature/candidate-list/candidate-list/router/candidate-list-router.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/check-candidate-list.module.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.html create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.scss create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.spec.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.ts create mode 100644 src/app/feature/candidate-list/check-candidate-list/router/check-candidate-list-router.ts create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.html create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.scss create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.ts create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.html create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.scss create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.html create mode 100644 src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.scss create mode 100644 src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.html create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.scss create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.html create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.scss create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.html create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.scss create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.html create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.scss create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.spec.ts create mode 100644 src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.ts create mode 100644 src/app/feature/candidate-list/seat-change/router/seat-change-router.ts create mode 100644 src/app/feature/candidate-list/seat-change/seat-change.module.ts create mode 100644 src/app/feature/candidate-payment-status/candidate-payment-status.module.ts create mode 100644 src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.html create mode 100644 src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.scss create mode 100644 src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.spec.ts create mode 100644 src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.ts create mode 100644 src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.html create mode 100644 src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.scss create mode 100644 src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.spec.ts create mode 100644 src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/list/list.component.html create mode 100644 src/app/feature/candidate-payment-status/presenter/list/list.component.scss create mode 100644 src/app/feature/candidate-payment-status/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/list/list.component.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/search/search.component.html create mode 100644 src/app/feature/candidate-payment-status/presenter/search/search.component.scss create mode 100644 src/app/feature/candidate-payment-status/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/search/search.component.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.html create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.scss create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.spec.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.html create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.scss create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.spec.ts create mode 100644 src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.ts create mode 100644 src/app/feature/candidate-payment-status/router/router.ts create mode 100644 src/app/feature/change-exam-day/change-exam-day.module.ts create mode 100644 src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.html create mode 100644 src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.scss create mode 100644 src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.spec.ts create mode 100644 src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.ts create mode 100644 src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.html create mode 100644 src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.ts create mode 100644 src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.html create mode 100644 src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.ts create mode 100644 src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.html create mode 100644 src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.ts create mode 100644 src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.html create mode 100644 src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.ts create mode 100644 src/app/feature/change-exam-day/presenter/list/list/list.component.html create mode 100644 src/app/feature/change-exam-day/presenter/list/list/list.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/list/list/list.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/list/list/list.component.ts create mode 100644 src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.html create mode 100644 src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.scss create mode 100644 src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.spec.ts create mode 100644 src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.ts create mode 100644 src/app/feature/change-exam-day/router/router.ts create mode 100644 src/app/feature/change-exam-room/change-exam-room.module.ts create mode 100644 src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.html create mode 100644 src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.scss create mode 100644 src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.spec.ts create mode 100644 src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.ts create mode 100644 src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.html create mode 100644 src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.scss create mode 100644 src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.spec.ts create mode 100644 src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.ts create mode 100644 src/app/feature/change-exam-room/presenter/dialog/dialog.component.html create mode 100644 src/app/feature/change-exam-room/presenter/dialog/dialog.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/dialog/dialog.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/dialog/dialog.component.ts create mode 100644 src/app/feature/change-exam-room/presenter/list/list.component.html create mode 100644 src/app/feature/change-exam-room/presenter/list/list.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/list/list.component.ts create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.html create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.ts create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.html create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.ts create mode 100644 src/app/feature/change-exam-room/presenter/search/search.component.html create mode 100644 src/app/feature/change-exam-room/presenter/search/search.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/search/search.component.ts create mode 100644 src/app/feature/change-exam-room/presenter/view/view.component.html create mode 100644 src/app/feature/change-exam-room/presenter/view/view.component.scss create mode 100644 src/app/feature/change-exam-room/presenter/view/view.component.spec.ts create mode 100644 src/app/feature/change-exam-room/presenter/view/view.component.ts create mode 100644 src/app/feature/change-exam-room/router/router.ts create mode 100644 src/app/feature/change-password/change-password.module.ts create mode 100644 src/app/feature/change-password/form/form.component.html create mode 100644 src/app/feature/change-password/form/form.component.scss create mode 100644 src/app/feature/change-password/form/form.component.spec.ts create mode 100644 src/app/feature/change-password/form/form.component.ts create mode 100644 src/app/feature/change-password/router/router.ts create mode 100644 src/app/feature/create-exam-seat/container/testing-info/testing-info.container.html create mode 100644 src/app/feature/create-exam-seat/container/testing-info/testing-info.container.scss create mode 100644 src/app/feature/create-exam-seat/container/testing-info/testing-info.container.spec.ts create mode 100644 src/app/feature/create-exam-seat/container/testing-info/testing-info.container.ts create mode 100644 src/app/feature/create-exam-seat/create-exam-seat.module.ts create mode 100644 src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.html create mode 100644 src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.scss create mode 100644 src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.spec.ts create mode 100644 src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.ts create mode 100644 src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.html create mode 100644 src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.scss create mode 100644 src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.spec.ts create mode 100644 src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.ts create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.html create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.scss create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.spec.ts create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.ts create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.html create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.scss create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.spec.ts create mode 100644 src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.ts create mode 100644 src/app/feature/create-exam-seat/presenter/view/view.component.html create mode 100644 src/app/feature/create-exam-seat/presenter/view/view.component.scss create mode 100644 src/app/feature/create-exam-seat/presenter/view/view.component.spec.ts create mode 100644 src/app/feature/create-exam-seat/presenter/view/view.component.ts create mode 100644 src/app/feature/create-exam-seat/router/router.ts create mode 100644 src/app/feature/create-exam/approve-exam/approve-exam.module.ts create mode 100644 src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.html create mode 100644 src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.scss create mode 100644 src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.spec.ts create mode 100644 src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.html create mode 100644 src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.scss create mode 100644 src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.spec.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.html create mode 100644 src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.scss create mode 100644 src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.spec.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.html create mode 100644 src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.scss create mode 100644 src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.spec.ts create mode 100644 src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.ts create mode 100644 src/app/feature/create-exam/approve-exam/router/approve-exam-router.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.html create mode 100644 src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.scss create mode 100644 src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/create-exam-calendar.module.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.html create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.scss create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-calendar/router/create-exam-calendar-router.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.html create mode 100644 src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.scss create mode 100644 src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/create-exam-condition.module.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.html create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.scss create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-condition/router/create-exam-condition-router.ts create mode 100644 src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.html create mode 100644 src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.scss create mode 100644 src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.ts create mode 100644 src/app/feature/create-exam/create-exam-information/create-exam-information.module.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.html create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.scss create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-information/router/create-exam-information-router.ts create mode 100644 src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.html create mode 100644 src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.scss create mode 100644 src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.ts create mode 100644 src/app/feature/create-exam/create-exam-room/create-exam-room.module.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.html create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.scss create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-room/router/create-exam-room-router.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.module.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-setup-period-by-subject/router/create-exam-setup-period-by-subject-router.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.html create mode 100644 src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.scss create mode 100644 src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/create-exam-subject.module.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.html create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.scss create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.html create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.scss create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.html create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.scss create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.html create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.scss create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.spec.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.ts create mode 100644 src/app/feature/create-exam/create-exam-subject/router/create-exam-subject-router.ts create mode 100644 src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.html create mode 100644 src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.scss create mode 100644 src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.spec.ts create mode 100644 src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.html create mode 100644 src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.scss create mode 100644 src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.spec.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.html create mode 100644 src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.scss create mode 100644 src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.spec.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.html create mode 100644 src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.scss create mode 100644 src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.spec.ts create mode 100644 src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.ts create mode 100644 src/app/feature/create-exam/reject-exam/reject-exam.module.ts create mode 100644 src/app/feature/create-exam/reject-exam/router/reject-exam-router.ts create mode 100644 src/app/feature/default/default.module.ts create mode 100644 src/app/feature/default/presenter/default/default.component.html create mode 100644 src/app/feature/default/presenter/default/default.component.scss create mode 100644 src/app/feature/default/presenter/default/default.component.spec.ts create mode 100644 src/app/feature/default/presenter/default/default.component.ts create mode 100644 src/app/feature/default/router/default-router.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.html create mode 100644 src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.scss create mode 100644 src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/daily-summary-ttb.module.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.html create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.scss create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.html create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.scss create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.ts create mode 100644 src/app/feature/exam-register/daily-summary-ttb/router/daily-summary-ttb-router.ts create mode 100644 src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.html create mode 100644 src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.scss create mode 100644 src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.ts create mode 100644 src/app/feature/exam-register/daily-summary/daily-summary.module.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.html create mode 100644 src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.scss create mode 100644 src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.html create mode 100644 src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.scss create mode 100644 src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.html create mode 100644 src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.scss create mode 100644 src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.spec.ts create mode 100644 src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.ts create mode 100644 src/app/feature/exam-register/daily-summary/router/daily-summary-router.ts create mode 100644 src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.html create mode 100644 src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.scss create mode 100644 src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.spec.ts create mode 100644 src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.ts create mode 100644 src/app/feature/exam-register/manage-receipt/manage-receipt.module.ts create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.html create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.scss create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.spec.ts create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.ts create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.html create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.scss create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.spec.ts create mode 100644 src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.ts create mode 100644 src/app/feature/exam-register/manage-receipt/router/manage-receipt-router.component.ts create mode 100644 src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.html create mode 100644 src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.scss create mode 100644 src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.spec.ts create mode 100644 src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.ts create mode 100644 src/app/feature/exam-register/period-summary/period-summary.module.ts create mode 100644 src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.html create mode 100644 src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.scss create mode 100644 src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.spec.ts create mode 100644 src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.ts create mode 100644 src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.html create mode 100644 src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.scss create mode 100644 src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.spec.ts create mode 100644 src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.ts create mode 100644 src/app/feature/exam-register/period-summary/router/period-summary-router.ts create mode 100644 src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.html create mode 100644 src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.scss create mode 100644 src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.spec.ts create mode 100644 src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.html create mode 100644 src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.scss create mode 100644 src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.spec.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.html create mode 100644 src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.scss create mode 100644 src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.spec.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.html create mode 100644 src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.scss create mode 100644 src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.spec.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.html create mode 100644 src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.scss create mode 100644 src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.spec.ts create mode 100644 src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.ts create mode 100644 src/app/feature/exam-register/receive-payment/receive-payment.module.ts create mode 100644 src/app/feature/exam-register/receive-payment/router/receive-payment-router.component.ts create mode 100644 src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.html create mode 100644 src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.scss create mode 100644 src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.spec.ts create mode 100644 src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.ts create mode 100644 src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.html create mode 100644 src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.scss create mode 100644 src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.spec.ts create mode 100644 src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.ts create mode 100644 src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.html create mode 100644 src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.scss create mode 100644 src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.spec.ts create mode 100644 src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.ts create mode 100644 src/app/feature/exam-register/register-cancel/register-cancel.module.ts create mode 100644 src/app/feature/exam-register/register-cancel/router/register-cancel-router.ts create mode 100644 src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.html create mode 100644 src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.scss create mode 100644 src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.html create mode 100644 src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.scss create mode 100644 src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.spec.ts create mode 100644 src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.ts create mode 100644 src/app/feature/exam-register/register-summary/register-summary.module.ts create mode 100644 src/app/feature/exam-register/register-summary/router/register-summary-router.component.ts create mode 100644 src/app/feature/exam-register/routes.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/change-exam-information.module.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.html create mode 100644 src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.html create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.html create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.html create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.html create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.html create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.scss create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.spec.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.ts create mode 100644 src/app/feature/exam-setting/change-exam-information/router/change-exam-information-router.ts create mode 100644 src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.html create mode 100644 src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.scss create mode 100644 src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.ts create mode 100644 src/app/feature/exam-setting/grade-summary/grade-summary.module.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.html create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.scss create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.spec.ts create mode 100644 src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.ts create mode 100644 src/app/feature/exam-setting/grade-summary/router/router.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.html create mode 100644 src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.scss create mode 100644 src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.spec.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/manage-exam-officer.module.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.html create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.scss create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.spec.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.html create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.scss create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.html create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.scss create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.spec.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.ts create mode 100644 src/app/feature/exam-setting/manage-exam-officer/router/manage-exam-officer-router.ts create mode 100644 src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.html create mode 100644 src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.scss create mode 100644 src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.html create mode 100644 src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.scss create mode 100644 src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.spec.ts create mode 100644 src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.ts create mode 100644 src/app/feature/exam-setting/random-questions/random-questions.module.ts create mode 100644 src/app/feature/exam-setting/random-questions/router/router.ts create mode 100644 src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.html create mode 100644 src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.scss create mode 100644 src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.ts create mode 100644 src/app/feature/extend-information/extend-information-date/extend-information-date.module.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.html create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.scss create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.html create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.scss create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.html create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.scss create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.html create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.scss create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.ts create mode 100644 src/app/feature/extend-information/extend-information-date/router/extend-information-date-router.ts create mode 100644 src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.html create mode 100644 src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.scss create mode 100644 src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.ts create mode 100644 src/app/feature/extend-information/extend-information-room/extend-information-room.module.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.html create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.scss create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.html create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.scss create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.html create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.scss create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.spec.ts create mode 100644 src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.ts create mode 100644 src/app/feature/extend-information/extend-information-room/router/extend-information-room-router.ts create mode 100644 src/app/feature/manage-payment/confirm/confirm.module.ts create mode 100644 src/app/feature/manage-payment/confirm/container/confirm/confirm.container.html create mode 100644 src/app/feature/manage-payment/confirm/container/confirm/confirm.container.scss create mode 100644 src/app/feature/manage-payment/confirm/container/confirm/confirm.container.spec.ts create mode 100644 src/app/feature/manage-payment/confirm/container/confirm/confirm.container.ts create mode 100644 src/app/feature/manage-payment/confirm/presenter/list/list.component.html create mode 100644 src/app/feature/manage-payment/confirm/presenter/list/list.component.scss create mode 100644 src/app/feature/manage-payment/confirm/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/manage-payment/confirm/presenter/list/list.component.ts create mode 100644 src/app/feature/manage-payment/confirm/router/router.ts create mode 100644 src/app/feature/manage-payment/import/container/import/import.container.html create mode 100644 src/app/feature/manage-payment/import/container/import/import.container.scss create mode 100644 src/app/feature/manage-payment/import/container/import/import.container.spec.ts create mode 100644 src/app/feature/manage-payment/import/container/import/import.container.ts create mode 100644 src/app/feature/manage-payment/import/import.module.ts create mode 100644 src/app/feature/manage-payment/import/presenter/list/list.component.html create mode 100644 src/app/feature/manage-payment/import/presenter/list/list.component.scss create mode 100644 src/app/feature/manage-payment/import/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/manage-payment/import/presenter/list/list.component.ts create mode 100644 src/app/feature/manage-payment/import/router/router.ts create mode 100644 src/app/feature/manage-test-center/manage-test-center-router/manage-test-center-router.component.ts create mode 100644 src/app/feature/manage-test-center/manage-test-center.module.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.html create mode 100644 src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.html create mode 100644 src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.html create mode 100644 src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.html create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.html create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.html create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.html create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.scss create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.spec.ts create mode 100644 src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.ts create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.html create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.scss create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.spec.ts create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.ts create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.html create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.scss create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.spec.ts create mode 100644 src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.ts create mode 100644 src/app/feature/notification-check-exam/notification-check-exam.module.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.html create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.scss create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.spec.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.html create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.scss create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.spec.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.html create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.scss create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.spec.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.html create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.scss create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.spec.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.html create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.scss create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.spec.ts create mode 100644 src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.ts create mode 100644 src/app/feature/notification-check-exam/router/notification-check-exam-router.ts create mode 100644 src/app/feature/online-summary/container/online-summary/online-summary.container.html create mode 100644 src/app/feature/online-summary/container/online-summary/online-summary.container.scss create mode 100644 src/app/feature/online-summary/container/online-summary/online-summary.container.spec.ts create mode 100644 src/app/feature/online-summary/container/online-summary/online-summary.container.ts create mode 100644 src/app/feature/online-summary/online-summary.module.ts create mode 100644 src/app/feature/online-summary/presenter/dialog/dialog.component.html create mode 100644 src/app/feature/online-summary/presenter/dialog/dialog.component.scss create mode 100644 src/app/feature/online-summary/presenter/dialog/dialog.component.spec.ts create mode 100644 src/app/feature/online-summary/presenter/dialog/dialog.component.ts create mode 100644 src/app/feature/online-summary/presenter/list/list.component.html create mode 100644 src/app/feature/online-summary/presenter/list/list.component.scss create mode 100644 src/app/feature/online-summary/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/online-summary/presenter/list/list.component.ts create mode 100644 src/app/feature/online-summary/router/router.ts create mode 100644 src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.html create mode 100644 src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.scss create mode 100644 src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.spec.ts create mode 100644 src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.ts create mode 100644 src/app/feature/print-exam-card/presenter/info/info.component.html create mode 100644 src/app/feature/print-exam-card/presenter/info/info.component.scss create mode 100644 src/app/feature/print-exam-card/presenter/info/info.component.spec.ts create mode 100644 src/app/feature/print-exam-card/presenter/info/info.component.ts create mode 100644 src/app/feature/print-exam-card/presenter/search/search.component.html create mode 100644 src/app/feature/print-exam-card/presenter/search/search.component.scss create mode 100644 src/app/feature/print-exam-card/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/print-exam-card/presenter/search/search.component.ts create mode 100644 src/app/feature/print-exam-card/print-exam-card.module.ts create mode 100644 src/app/feature/print-exam-card/router/router.ts create mode 100644 src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.html create mode 100644 src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.scss create mode 100644 src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.spec.ts create mode 100644 src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.ts create mode 100644 src/app/feature/print-exam-result/presenter/search/search.component.html create mode 100644 src/app/feature/print-exam-result/presenter/search/search.component.scss create mode 100644 src/app/feature/print-exam-result/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/print-exam-result/presenter/search/search.component.ts create mode 100644 src/app/feature/print-exam-result/print-exam-result.module.ts create mode 100644 src/app/feature/print-exam-result/router/router.ts create mode 100644 src/app/feature/report/container/report/report.container.html create mode 100644 src/app/feature/report/container/report/report.container.scss create mode 100644 src/app/feature/report/container/report/report.container.spec.ts create mode 100644 src/app/feature/report/container/report/report.container.ts create mode 100644 src/app/feature/report/presenter/report-preview/report-preview.component.html create mode 100644 src/app/feature/report/presenter/report-preview/report-preview.component.scss create mode 100644 src/app/feature/report/presenter/report-preview/report-preview.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-preview/report-preview.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-search.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-search.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-search.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-search.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.html create mode 100644 src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.scss create mode 100644 src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.spec.ts create mode 100644 src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.ts create mode 100644 src/app/feature/report/report.module.ts create mode 100644 src/app/feature/report/router/report-router.ts create mode 100644 src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.html create mode 100644 src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.scss create mode 100644 src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.spec.ts create mode 100644 src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.ts create mode 100644 src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.html create mode 100644 src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.html create mode 100644 src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.html create mode 100644 src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.html create mode 100644 src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.html create mode 100644 src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.html create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.scss create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.spec.ts create mode 100644 src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.ts create mode 100644 src/app/feature/set-exam-information/router/set-exam-information-router.ts create mode 100644 src/app/feature/set-exam-information/set-exam-information.module.ts create mode 100644 src/app/feature/set-permission/create-user/container/create-user/create-user.container.html create mode 100644 src/app/feature/set-permission/create-user/container/create-user/create-user.container.scss create mode 100644 src/app/feature/set-permission/create-user/container/create-user/create-user.container.spec.ts create mode 100644 src/app/feature/set-permission/create-user/container/create-user/create-user.container.ts create mode 100644 src/app/feature/set-permission/create-user/create-user.module.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/form/form/form.component.html create mode 100644 src/app/feature/set-permission/create-user/presenter/form/form/form.component.scss create mode 100644 src/app/feature/set-permission/create-user/presenter/form/form/form.component.spec.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/form/form/form.component.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/list/list/list.component.html create mode 100644 src/app/feature/set-permission/create-user/presenter/list/list/list.component.scss create mode 100644 src/app/feature/set-permission/create-user/presenter/list/list/list.component.spec.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/list/list/list.component.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/search/search/search.component.html create mode 100644 src/app/feature/set-permission/create-user/presenter/search/search/search.component.scss create mode 100644 src/app/feature/set-permission/create-user/presenter/search/search/search.component.spec.ts create mode 100644 src/app/feature/set-permission/create-user/presenter/search/search/search.component.ts create mode 100644 src/app/feature/set-permission/create-user/router/router.ts create mode 100644 src/app/feature/set-permission/set-role/container/set-role/set-role.container.html create mode 100644 src/app/feature/set-permission/set-role/container/set-role/set-role.container.scss create mode 100644 src/app/feature/set-permission/set-role/container/set-role/set-role.container.spec.ts create mode 100644 src/app/feature/set-permission/set-role/container/set-role/set-role.container.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.html create mode 100644 src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.scss create mode 100644 src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.spec.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.html create mode 100644 src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.scss create mode 100644 src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.spec.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.html create mode 100644 src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.scss create mode 100644 src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.spec.ts create mode 100644 src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.ts create mode 100644 src/app/feature/set-permission/set-role/router/router.ts create mode 100644 src/app/feature/set-permission/set-role/set-role.module.ts create mode 100644 src/app/feature/set-permission/set-user/container/set-user/set-user.container.html create mode 100644 src/app/feature/set-permission/set-user/container/set-user/set-user.container.scss create mode 100644 src/app/feature/set-permission/set-user/container/set-user/set-user.container.spec.ts create mode 100644 src/app/feature/set-permission/set-user/container/set-user/set-user.container.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/form/form/form.component.html create mode 100644 src/app/feature/set-permission/set-user/presenter/form/form/form.component.scss create mode 100644 src/app/feature/set-permission/set-user/presenter/form/form/form.component.spec.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/form/form/form.component.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/list/list/list.component.html create mode 100644 src/app/feature/set-permission/set-user/presenter/list/list/list.component.scss create mode 100644 src/app/feature/set-permission/set-user/presenter/list/list/list.component.spec.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/list/list/list.component.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/search/search/search.component.html create mode 100644 src/app/feature/set-permission/set-user/presenter/search/search/search.component.scss create mode 100644 src/app/feature/set-permission/set-user/presenter/search/search/search.component.spec.ts create mode 100644 src/app/feature/set-permission/set-user/presenter/search/search/search.component.ts create mode 100644 src/app/feature/set-permission/set-user/router/router.ts create mode 100644 src/app/feature/set-permission/set-user/set-user.module.ts create mode 100644 src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.html create mode 100644 src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.scss create mode 100644 src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.spec.ts create mode 100644 src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.html create mode 100644 src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.scss create mode 100644 src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.spec.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.html create mode 100644 src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.scss create mode 100644 src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.spec.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.html create mode 100644 src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.scss create mode 100644 src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.spec.ts create mode 100644 src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.ts create mode 100644 src/app/feature/set-permission/user-couter/user-couter-router/user-couter-router.ts create mode 100644 src/app/feature/set-permission/user-couter/user-couter.module.ts create mode 100644 src/app/feature/setting-exam/container/setting-exam/setting-exam.container.html create mode 100644 src/app/feature/setting-exam/container/setting-exam/setting-exam.container.scss create mode 100644 src/app/feature/setting-exam/container/setting-exam/setting-exam.container.spec.ts create mode 100644 src/app/feature/setting-exam/container/setting-exam/setting-exam.container.ts create mode 100644 src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.html create mode 100644 src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.scss create mode 100644 src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.spec.ts create mode 100644 src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.ts create mode 100644 src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.html create mode 100644 src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.scss create mode 100644 src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.spec.ts create mode 100644 src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.ts create mode 100644 src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.html create mode 100644 src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.scss create mode 100644 src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.spec.ts create mode 100644 src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.ts create mode 100644 src/app/feature/setting-exam/router/setting-exam-router.ts create mode 100644 src/app/feature/setting-exam/setting-exam.module.ts create mode 100644 src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.html create mode 100644 src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.scss create mode 100644 src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.spec.ts create mode 100644 src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.ts create mode 100644 src/app/feature/setting-print-card/presenter/search/search.component.html create mode 100644 src/app/feature/setting-print-card/presenter/search/search.component.scss create mode 100644 src/app/feature/setting-print-card/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/setting-print-card/presenter/search/search.component.ts create mode 100644 src/app/feature/setting-print-card/router/router.ts create mode 100644 src/app/feature/setting-print-card/setting-print-card.module.ts create mode 100644 src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.html create mode 100644 src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.scss create mode 100644 src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.ts create mode 100644 src/app/feature/settings-finance/exam-finance/exam-finance.module.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.html create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.scss create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.spec.ts create mode 100644 src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.ts create mode 100644 src/app/feature/settings-finance/exam-finance/router/exam-finance-router.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.html create mode 100644 src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.scss create mode 100644 src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.spec.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/invigilate-finance.module.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.html create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.scss create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.spec.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.html create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.scss create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.spec.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.html create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.scss create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.spec.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.html create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.scss create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.spec.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.ts create mode 100644 src/app/feature/settings-finance/invigilate-finance/router/invigilate-finance-router.ts create mode 100644 src/app/feature/settings-finance/routes.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.html create mode 100644 src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.scss create mode 100644 src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.spec.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.html create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.scss create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.spec.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.html create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.scss create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.spec.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.html create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.scss create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.spec.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/router/teacher-finance-router.ts create mode 100644 src/app/feature/settings-finance/teacher-finance/teacher-finance.module.ts create mode 100644 src/app/feature/settings/academic-semesters/academic-semesters.module.ts create mode 100644 src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.html create mode 100644 src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.scss create mode 100644 src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.spec.ts create mode 100644 src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.html create mode 100644 src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.scss create mode 100644 src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.spec.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.html create mode 100644 src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.scss create mode 100644 src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.spec.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.html create mode 100644 src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.scss create mode 100644 src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.spec.ts create mode 100644 src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.ts create mode 100644 src/app/feature/settings/academic-semesters/router/academic-semesters-router.ts create mode 100644 src/app/feature/settings/academic-years/academic-years.module.ts create mode 100644 src/app/feature/settings/academic-years/container/academic-years/academic-years.container.html create mode 100644 src/app/feature/settings/academic-years/container/academic-years/academic-years.container.scss create mode 100644 src/app/feature/settings/academic-years/container/academic-years/academic-years.container.spec.ts create mode 100644 src/app/feature/settings/academic-years/container/academic-years/academic-years.container.ts create mode 100644 src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.html create mode 100644 src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.scss create mode 100644 src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.spec.ts create mode 100644 src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.ts create mode 100644 src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.html create mode 100644 src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.scss create mode 100644 src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.spec.ts create mode 100644 src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.ts create mode 100644 src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.html create mode 100644 src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.scss create mode 100644 src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.spec.ts create mode 100644 src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.ts create mode 100644 src/app/feature/settings/academic-years/router/academic-years-router.ts create mode 100644 src/app/feature/settings/calendars/calendars.module.ts create mode 100644 src/app/feature/settings/calendars/container/calendars/calendars.container.html create mode 100644 src/app/feature/settings/calendars/container/calendars/calendars.container.scss create mode 100644 src/app/feature/settings/calendars/container/calendars/calendars.container.spec.ts create mode 100644 src/app/feature/settings/calendars/container/calendars/calendars.container.ts create mode 100644 src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.html create mode 100644 src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.scss create mode 100644 src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.spec.ts create mode 100644 src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.ts create mode 100644 src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.html create mode 100644 src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.scss create mode 100644 src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.spec.ts create mode 100644 src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.ts create mode 100644 src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.html create mode 100644 src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.scss create mode 100644 src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.spec.ts create mode 100644 src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.ts create mode 100644 src/app/feature/settings/calendars/router/calendars-router.ts create mode 100644 src/app/feature/settings/department/contianer/department/department.container.html create mode 100644 src/app/feature/settings/department/contianer/department/department.container.scss create mode 100644 src/app/feature/settings/department/contianer/department/department.container.spec.ts create mode 100644 src/app/feature/settings/department/contianer/department/department.container.ts create mode 100644 src/app/feature/settings/department/department.module.ts create mode 100644 src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.html create mode 100644 src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.scss create mode 100644 src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.spec.ts create mode 100644 src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.ts create mode 100644 src/app/feature/settings/department/presenter/list/department-list/department-list.component.html create mode 100644 src/app/feature/settings/department/presenter/list/department-list/department-list.component.scss create mode 100644 src/app/feature/settings/department/presenter/list/department-list/department-list.component.spec.ts create mode 100644 src/app/feature/settings/department/presenter/list/department-list/department-list.component.ts create mode 100644 src/app/feature/settings/department/presenter/search/department-search/department-search.component.html create mode 100644 src/app/feature/settings/department/presenter/search/department-search/department-search.component.scss create mode 100644 src/app/feature/settings/department/presenter/search/department-search/department-search.component.spec.ts create mode 100644 src/app/feature/settings/department/presenter/search/department-search/department-search.component.ts create mode 100644 src/app/feature/settings/department/router/department-router.ts create mode 100644 src/app/feature/settings/education-type/container/education-type/education-type.container.html create mode 100644 src/app/feature/settings/education-type/container/education-type/education-type.container.scss create mode 100644 src/app/feature/settings/education-type/container/education-type/education-type.container.spec.ts create mode 100644 src/app/feature/settings/education-type/container/education-type/education-type.container.ts create mode 100644 src/app/feature/settings/education-type/education-type.module.ts create mode 100644 src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.html create mode 100644 src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.scss create mode 100644 src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.spec.ts create mode 100644 src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.ts create mode 100644 src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.html create mode 100644 src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.scss create mode 100644 src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.spec.ts create mode 100644 src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.ts create mode 100644 src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.html create mode 100644 src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.scss create mode 100644 src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.spec.ts create mode 100644 src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.ts create mode 100644 src/app/feature/settings/education-type/router/education-type-router.ts create mode 100644 src/app/feature/settings/faculties/container/faculties/faculties.container.html create mode 100644 src/app/feature/settings/faculties/container/faculties/faculties.container.scss create mode 100644 src/app/feature/settings/faculties/container/faculties/faculties.container.spec.ts create mode 100644 src/app/feature/settings/faculties/container/faculties/faculties.container.ts create mode 100644 src/app/feature/settings/faculties/faculties.module.ts create mode 100644 src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.html create mode 100644 src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.scss create mode 100644 src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.spec.ts create mode 100644 src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.ts create mode 100644 src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.html create mode 100644 src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.scss create mode 100644 src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.spec.ts create mode 100644 src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.ts create mode 100644 src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.html create mode 100644 src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.scss create mode 100644 src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.spec.ts create mode 100644 src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.ts create mode 100644 src/app/feature/settings/faculties/router/faculties-router.ts create mode 100644 src/app/feature/settings/online-counter/container/online-counter/online-counter.container.html create mode 100644 src/app/feature/settings/online-counter/container/online-counter/online-counter.container.scss create mode 100644 src/app/feature/settings/online-counter/container/online-counter/online-counter.container.spec.ts create mode 100644 src/app/feature/settings/online-counter/container/online-counter/online-counter.container.ts create mode 100644 src/app/feature/settings/online-counter/online-counter.module.ts create mode 100644 src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.html create mode 100644 src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.scss create mode 100644 src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.spec.ts create mode 100644 src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.ts create mode 100644 src/app/feature/settings/online-counter/presenter/list/list.component.html create mode 100644 src/app/feature/settings/online-counter/presenter/list/list.component.scss create mode 100644 src/app/feature/settings/online-counter/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/settings/online-counter/presenter/list/list.component.ts create mode 100644 src/app/feature/settings/online-counter/presenter/search/search.component.html create mode 100644 src/app/feature/settings/online-counter/presenter/search/search.component.scss create mode 100644 src/app/feature/settings/online-counter/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/settings/online-counter/presenter/search/search.component.ts create mode 100644 src/app/feature/settings/online-counter/router/router.ts create mode 100644 src/app/feature/settings/signature/container/signature/signature.container.html create mode 100644 src/app/feature/settings/signature/container/signature/signature.container.scss create mode 100644 src/app/feature/settings/signature/container/signature/signature.container.spec.ts create mode 100644 src/app/feature/settings/signature/container/signature/signature.container.ts create mode 100644 src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.html create mode 100644 src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.scss create mode 100644 src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.spec.ts create mode 100644 src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.ts create mode 100644 src/app/feature/settings/signature/presenter/list/list.component.html create mode 100644 src/app/feature/settings/signature/presenter/list/list.component.scss create mode 100644 src/app/feature/settings/signature/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/settings/signature/presenter/list/list.component.ts create mode 100644 src/app/feature/settings/signature/presenter/search/search.component.html create mode 100644 src/app/feature/settings/signature/presenter/search/search.component.scss create mode 100644 src/app/feature/settings/signature/presenter/search/search.component.spec.ts create mode 100644 src/app/feature/settings/signature/presenter/search/search.component.ts create mode 100644 src/app/feature/settings/signature/router/router.ts create mode 100644 src/app/feature/settings/signature/signature.module.ts create mode 100644 src/app/feature/settings/testcenter/container/testcenter/testcenter.container.html create mode 100644 src/app/feature/settings/testcenter/container/testcenter/testcenter.container.scss create mode 100644 src/app/feature/settings/testcenter/container/testcenter/testcenter.container.spec.ts create mode 100644 src/app/feature/settings/testcenter/container/testcenter/testcenter.container.ts create mode 100644 src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.html create mode 100644 src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.scss create mode 100644 src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.spec.ts create mode 100644 src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.ts create mode 100644 src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.html create mode 100644 src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.scss create mode 100644 src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.spec.ts create mode 100644 src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.ts create mode 100644 src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.html create mode 100644 src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.scss create mode 100644 src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.spec.ts create mode 100644 src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.ts create mode 100644 src/app/feature/settings/testcenter/router/testcenter-router.ts create mode 100644 src/app/feature/settings/testcenter/testcenter.module.ts create mode 100644 src/app/feature/settings/testing-field/container/testing-field/testing-field.container.html create mode 100644 src/app/feature/settings/testing-field/container/testing-field/testing-field.container.scss create mode 100644 src/app/feature/settings/testing-field/container/testing-field/testing-field.container.spec.ts create mode 100644 src/app/feature/settings/testing-field/container/testing-field/testing-field.container.ts create mode 100644 src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.html create mode 100644 src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.scss create mode 100644 src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.spec.ts create mode 100644 src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.ts create mode 100644 src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.html create mode 100644 src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.scss create mode 100644 src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.spec.ts create mode 100644 src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.ts create mode 100644 src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.html create mode 100644 src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.scss create mode 100644 src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.spec.ts create mode 100644 src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.ts create mode 100644 src/app/feature/settings/testing-field/router/testing-field-router.ts create mode 100644 src/app/feature/settings/testing-field/testing-field.module.ts create mode 100644 src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.html create mode 100644 src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.scss create mode 100644 src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.spec.ts create mode 100644 src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.html create mode 100644 src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.scss create mode 100644 src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.spec.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.html create mode 100644 src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.scss create mode 100644 src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.spec.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.html create mode 100644 src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.scss create mode 100644 src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.spec.ts create mode 100644 src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.ts create mode 100644 src/app/feature/settings/testing-vdos/router/testing-vdos-router.ts create mode 100644 src/app/feature/settings/testing-vdos/testing-vdos.module.ts create mode 100644 src/app/feature/settings/typesubject/container/typesubject/typesubject.container.html create mode 100644 src/app/feature/settings/typesubject/container/typesubject/typesubject.container.scss create mode 100644 src/app/feature/settings/typesubject/container/typesubject/typesubject.container.spec.ts create mode 100644 src/app/feature/settings/typesubject/container/typesubject/typesubject.container.ts create mode 100644 src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.html create mode 100644 src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.scss create mode 100644 src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.spec.ts create mode 100644 src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.ts create mode 100644 src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.html create mode 100644 src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.scss create mode 100644 src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.spec.ts create mode 100644 src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.ts create mode 100644 src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.html create mode 100644 src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.scss create mode 100644 src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.spec.ts create mode 100644 src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.ts create mode 100644 src/app/feature/settings/typesubject/router/typesubject-router.ts create mode 100644 src/app/feature/settings/typesubject/typesubject.module.ts create mode 100644 src/app/feature/student-info/container/student-info/student-info.container.html create mode 100644 src/app/feature/student-info/container/student-info/student-info.container.scss create mode 100644 src/app/feature/student-info/container/student-info/student-info.container.ts create mode 100644 src/app/feature/student-info/presenter/form/form/form.component.html create mode 100644 src/app/feature/student-info/presenter/form/form/form.component.scss create mode 100644 src/app/feature/student-info/presenter/form/form/form.component.spec.ts create mode 100644 src/app/feature/student-info/presenter/form/form/form.component.ts create mode 100644 src/app/feature/student-info/presenter/list/list.component.html create mode 100644 src/app/feature/student-info/presenter/list/list.component.scss create mode 100644 src/app/feature/student-info/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/student-info/presenter/list/list.component.ts create mode 100644 src/app/feature/student-info/presenter/search/search/search.component.html create mode 100644 src/app/feature/student-info/presenter/search/search/search.component.scss create mode 100644 src/app/feature/student-info/presenter/search/search/search.component.spec.ts create mode 100644 src/app/feature/student-info/presenter/search/search/search.component.ts create mode 100644 src/app/feature/student-info/router/router.ts create mode 100644 src/app/feature/student-info/student-info.module.ts create mode 100644 src/app/feature/upload-student/container/testing-info/testing-info.container.html create mode 100644 src/app/feature/upload-student/container/testing-info/testing-info.container.scss create mode 100644 src/app/feature/upload-student/container/testing-info/testing-info.container.spec.ts create mode 100644 src/app/feature/upload-student/container/testing-info/testing-info.container.ts create mode 100644 src/app/feature/upload-student/container/upload-student/upload-student.container.html create mode 100644 src/app/feature/upload-student/container/upload-student/upload-student.container.scss create mode 100644 src/app/feature/upload-student/container/upload-student/upload-student.container.spec.ts create mode 100644 src/app/feature/upload-student/container/upload-student/upload-student.container.ts create mode 100644 src/app/feature/upload-student/presenter/list/list.component.html create mode 100644 src/app/feature/upload-student/presenter/list/list.component.scss create mode 100644 src/app/feature/upload-student/presenter/list/list.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/list/list.component.ts create mode 100644 src/app/feature/upload-student/presenter/search/search/search.component.html create mode 100644 src/app/feature/upload-student/presenter/search/search/search.component.scss create mode 100644 src/app/feature/upload-student/presenter/search/search/search.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/search/search/search.component.ts create mode 100644 src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.html create mode 100644 src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.scss create mode 100644 src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.ts create mode 100644 src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.html create mode 100644 src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.scss create mode 100644 src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.ts create mode 100644 src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.html create mode 100644 src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.scss create mode 100644 src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.ts create mode 100644 src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.html create mode 100644 src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.scss create mode 100644 src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.spec.ts create mode 100644 src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.ts create mode 100644 src/app/feature/upload-student/router/router.ts create mode 100644 src/app/feature/upload-student/upload-student.module.ts create mode 100644 src/app/layout/main-layout/main-layout.component.html create mode 100644 src/app/layout/main-layout/main-layout.component.scss create mode 100644 src/app/layout/main-layout/main-layout.component.spec.ts create mode 100644 src/app/layout/main-layout/main-layout.component.ts create mode 100644 src/app/layout/menu/menu/menu.component.html create mode 100644 src/app/layout/menu/menu/menu.component.scss create mode 100644 src/app/layout/menu/menu/menu.component.spec.ts create mode 100644 src/app/layout/menu/menu/menu.component.ts create mode 100644 src/app/layout/toolbar/toolbar/toolbar.component.html create mode 100644 src/app/layout/toolbar/toolbar/toolbar.component.scss create mode 100644 src/app/layout/toolbar/toolbar/toolbar.component.spec.ts create mode 100644 src/app/layout/toolbar/toolbar/toolbar.component.ts create mode 100644 src/app/shared/animations/animation.ts create mode 100644 src/app/shared/components/README.md create mode 100644 src/app/shared/directives/demo.directive.spec.ts create mode 100644 src/app/shared/directives/demo.directive.ts create mode 100644 src/app/shared/directives/email-input.directive.ts create mode 100644 src/app/shared/directives/input.directive.ts create mode 100644 src/app/shared/directives/limit-length.directive.ts create mode 100644 src/app/shared/directives/only-number.directive.ts create mode 100644 src/app/shared/models/user.ts create mode 100644 src/app/shared/pipes/checkFormcustom/check-form-exam-information-section.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/cheakseatall.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkdupicateallseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkdupicateseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkfield.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkinrange.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkinrangeallseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checklessmoreallseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checklessmoreseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkmaxseat.pipe.ts create mode 100644 src/app/shared/pipes/checkseat/checkseat.pipe.ts create mode 100644 src/app/shared/pipes/demo.pipe.spec.ts create mode 100644 src/app/shared/pipes/demo.pipe.ts create mode 100644 src/app/shared/pipes/getdata/get-data-id.pipe.ts create mode 100644 src/app/shared/pipes/previewfile/preview-file.pipe.spec.ts create mode 100644 src/app/shared/pipes/previewfile/preview-file.pipe.ts create mode 100644 src/app/shared/pipes/role/role.pipe.ts create mode 100644 src/app/shared/pipes/search-auto/search-auto.pipe.ts create mode 100644 src/app/shared/pipes/search-auto/search-autov2.pipe.ts create mode 100644 src/app/shared/pipes/thaidate/thaidate..ts create mode 100644 src/app/shared/shared.module.ts create mode 100644 src/app/shared/util/func.ts create mode 100644 src/app/shared/validator/real-citizen-id.validator.ts create mode 100644 src/app/state/app-reducer.ts create mode 100644 src/assets/.gitkeep create mode 100644 src/assets/images/preview.png create mode 100644 src/assets/logo/default.png create mode 100644 src/assets/logo/etest-logo.png create mode 100644 src/assets/templates/ru_student_template_paid.xlsx create mode 100644 src/assets/templates/ru_student_template_wait.xlsx create mode 100644 src/assets/templates/student_import.xlsx create mode 100644 src/environments/environment.prod.ts create mode 100644 src/environments/environment.ru.ts create mode 100644 src/environments/environment.ts create mode 100644 src/favicon.ico create mode 100644 src/index.html create mode 100644 src/main.ts create mode 100644 src/polyfills.ts create mode 100644 src/styles.scss create mode 100644 src/test.ts create mode 100644 tailwind.config.js create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.spec.json create mode 100644 tslint.json create mode 100644 webpack.config.js diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..8084853 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,12 @@ +# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries + +# You can see what browsers were selected by your queries by running: +# npx browserslist + +> 0.5% +last 2 versions +Firefox ESR +not dead +not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b585a76 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4f46a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc +# Only exists if Bazel was run +/bazel-out + +# dependencies +/node_modules + +# profiling files +chrome-profiler-events.json +speed-measure-plugin.json + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5e7671 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "javascript.implicitProjectConfig.experimentalDecorators": true, + "typescript.tsdk": "node_modules/typescript/lib", + "enable_typescript_language_service": false, + "css.validate": false, + "less.validate": false, + "scss.validate": false, + "angular.enable-strict-mode-prompt": false +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..37cfd6b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM node:12.19.0-buster AS compile-image + +WORKDIR /opt/ng +COPY package.json /opt/ng/package.json +RUN npm install +RUN npm install -g @angular/cli +ENV PATH="./node_modules/.bin:$PATH" + +COPY . ./ +RUN ng build --configuration production --base-href /manage-testing/ --deploy-url /manage-testing/ + +FROM nginx +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=compile-image /opt/ng/dist/ru-manage-testing /usr/share/nginx/html diff --git a/README.md b/README.md new file mode 100644 index 0000000..f7c0d83 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# AngularFolderStructure + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.1. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..ba097d7 --- /dev/null +++ b/angular.json @@ -0,0 +1,167 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "ru-manage-testing": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss", + "changeDetection": "OnPush" + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-builders/custom-webpack:browser", + "options": { + "aot": true, + "outputPath": "dist/ru-manage-testing", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "src/styles.scss" + ], + "scripts": [], + "customWebpackConfig": { + "path": "webpack.config.js" + } + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ] + }, + "ru": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.ru.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-builders/custom-webpack:dev-server", + "options": { + "browserTarget": "ru-manage-testing:build" + }, + "configurations": { + "production": { + "browserTarget": "ru-manage-testing:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "ru-manage-testing:build" + } + }, + "test": { + "builder": "@angular-builders/custom-webpack:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.spec.json", + "karmaConfig": "karma.conf.js", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "src/styles.scss" + ], + "scripts": [], + "customWebpackConfig": { + "path": "webpack.config.js" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "tsconfig.app.json", + "tsconfig.spec.json", + "e2e/tsconfig.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "ru-manage-testing:serve" + }, + "configurations": { + "production": { + "devServerTarget": "ru-manage-testing:serve:production" + } + } + } + } + } + }, + "defaultProject": "ru-manage-testing", + "cli": { + "analytics": "96b6b0a2-0a7f-4f8a-b945-c66b60e3c39c" + } +} diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml new file mode 100644 index 0000000..23d7a2e --- /dev/null +++ b/bitbucket-pipelines.yml @@ -0,0 +1,31 @@ +pipelines: + branches: + master: + - step: + # runs-on: + # - self.hosted + # - linux + # - 8x + size: 2x + services: + - docker + caches: + - docker + script: # Modify the commands below to build your repository. + - docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD + - docker build -f Dockerfile -t 71dev/ru-manage-testing-web:dev . + - docker push 71dev/ru-manage-testing-web:dev + - step: + # runs-on: + # - self.hosted + # - linux + # - 8x + name: deploy to kubernates + image: atlassian/pipelines-kubectl + script: + - echo $KUBE_CONFIG_DELL | base64 -d > kubeconfig + - kubectl --insecure-skip-tls-verify --kubeconfig=kubeconfig rollout restart deployment/ru-manage-testing-deployment -n ru +definitions: + services: + docker: + memory: 6144 diff --git a/e2e/protractor.conf.js b/e2e/protractor.conf.js new file mode 100644 index 0000000..73e4e68 --- /dev/null +++ b/e2e/protractor.conf.js @@ -0,0 +1,32 @@ +// @ts-check +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +/** + * @type { import("protractor").Config } + */ +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './src/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: require('path').join(__dirname, './tsconfig.json') + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; \ No newline at end of file diff --git a/e2e/src/app.e2e-spec.ts b/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000..4bd7afb --- /dev/null +++ b/e2e/src/app.e2e-spec.ts @@ -0,0 +1,23 @@ +import { AppPage } from './app.po'; +import { browser, logging } from 'protractor'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getTitleText()).toEqual('Welcome to angular-folder-structure!'); + }); + + afterEach(async () => { + // Assert that there are no errors emitted from the browser + const logs = await browser.manage().logs().get(logging.Type.BROWSER); + expect(logs).not.toContain(jasmine.objectContaining({ + level: logging.Level.SEVERE, + } as logging.Entry)); + }); +}); diff --git a/e2e/src/app.po.ts b/e2e/src/app.po.ts new file mode 100644 index 0000000..5776aa9 --- /dev/null +++ b/e2e/src/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get(browser.baseUrl) as Promise; + } + + getTitleText() { + return element(by.css('app-root h1')).getText() as Promise; + } +} diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json new file mode 100644 index 0000000..c92199c --- /dev/null +++ b/e2e/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "module": "commonjs", + "target": "es2018", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..994b29f --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,32 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, './coverage/angular-folder-structure'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true + }); +}; diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..4ede8b1 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,9 @@ +server { + listen 8080; + root /usr/share/nginx/html; + include /etc/nginx/mime.types; + + location / { + try_files $uri /index.html; + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f6accf5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,35312 @@ +{ + "name": "angular-folder-structure", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "angular-folder-structure", + "version": "0.0.0", + "dependencies": { + "@angular/animations": "~11.0.0", + "@angular/cdk": "^11.2.7", + "@angular/common": "~11.0.0", + "@angular/compiler": "~11.0.0", + "@angular/core": "~11.0.0", + "@angular/forms": "~11.0.0", + "@angular/material": "^11.2.7", + "@angular/platform-browser": "~11.0.0", + "@angular/platform-browser-dynamic": "~11.0.0", + "@angular/router": "~11.0.0", + "@auth0/angular-jwt": "5.0.2", + "@briebug/jest-schematic": "^2.1.1", + "@ngneat/tailwind": "^6.0.3", + "@ngrx/effects": "^10.0.0", + "@ngrx/router-store": "^10.0.0", + "@ngrx/schematics": "^10.0.0", + "@ngrx/store": "^10.0.0", + "@ngrx/store-devtools": "^10.0.0", + "@tinymce/tinymce-angular": "^4.2.2", + "ngx-material-timepicker": "^5.5.3", + "ngx-multiple-dates": "^13.1.0", + "ngx-progressbar": "^6.1.1", + "oidc-client": "^1.11.5", + "rxjs": "~6.6.3", + "sweetalert2": "^10.16.9", + "tslib": "^2.0.0", + "zone.js": "~0.10.2" + }, + "devDependencies": { + "@angular-builders/custom-webpack": "11.1.1", + "@angular-devkit/build-angular": "~0.1100.1", + "@angular/cli": "~11.0.1", + "@angular/compiler-cli": "~11.0.0", + "@angular/language-service": "~11.0.0", + "@tailwindcss/aspect-ratio": "0.2.0", + "@tailwindcss/forms": "0.3.2", + "@tailwindcss/line-clamp": "0.2.0", + "@tailwindcss/typography": "0.4.0", + "@types/jasmine": "~3.6.0", + "@types/jasminewd2": "~2.0.3", + "@types/node": "^12.11.1", + "autoprefixer": "^10.2.5", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", + "jasmine-spec-reporter": "~5.0.0", + "karma": "~5.1.1", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "postcss": "^8.2.9", + "postcss-ng-tailwind-in-components": "0.0.4", + "protractor": "~7.0.0", + "tailwindcss": "^2.0.4", + "ts-node": "~7.0.0", + "tslint": "~6.1.0", + "typescript": "~4.0.5" + } + }, + "node_modules/@angular-builders/custom-webpack": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-11.1.1.tgz", + "integrity": "sha512-9l2yC9+QMwWj9IEsOpQtMIBcH87UMZdoR2+8DbIt53ypst/8aVMhMsKmR5n33wRkLlIJ6/ubyXldQymIHzoF1g==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": ">=0.1100.0 < 0.1200.0", + "@angular-devkit/build-angular": ">=0.1100.0 < 0.1200.0", + "@angular-devkit/core": "^11.0.0", + "lodash": "^4.17.15", + "ts-node": "^9.0.0", + "tsconfig-paths": "^3.9.0", + "webpack-merge": "^5.7.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@angular-builders/custom-webpack/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@angular-builders/custom-webpack/node_modules/ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/@angular-builders/custom-webpack/node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@angular-builders/custom-webpack/node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1100.1.tgz", + "integrity": "sha512-DIAvTRRY+k7T2xHf4RVV06P16D0V7wSf1MSpGSDWVpfWcA3HNOSGfsk1F+COMlbFehXuKztwieXarv5rXbBCng==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.0.1", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1100.1.tgz", + "integrity": "sha512-w8NcoXuruOHio0D/JbX47iDl9FVH8X9k/OlZ/rSNVQ3uEpV6uxIaTm3fZ1ZSrKffi+97rKEwpHOf2N0DXl4XGQ==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/build-optimizer": "0.1100.1", + "@angular-devkit/build-webpack": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "@babel/core": "7.12.3", + "@babel/generator": "7.12.1", + "@babel/plugin-transform-runtime": "7.12.1", + "@babel/preset-env": "7.12.1", + "@babel/runtime": "7.12.1", + "@babel/template": "7.10.4", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "11.0.1", + "ansi-colors": "4.1.1", + "autoprefixer": "9.8.6", + "babel-loader": "8.1.0", + "browserslist": "^4.9.1", + "cacache": "15.0.5", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.0", + "copy-webpack-plugin": "6.2.1", + "core-js": "3.6.5", + "css-loader": "5.0.0", + "cssnano": "4.1.10", + "file-loader": "6.1.1", + "find-cache-dir": "3.3.1", + "glob": "7.1.6", + "inquirer": "7.3.3", + "jest-worker": "26.5.0", + "karma-source-map-support": "1.4.0", + "less": "3.12.2", + "less-loader": "7.0.2", + "license-webpack-plugin": "2.3.1", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "1.2.1", + "minimatch": "3.0.4", + "open": "7.3.0", + "ora": "5.1.0", + "parse5-html-rewriting-stream": "6.0.1", + "pnp-webpack-plugin": "1.6.4", + "postcss": "7.0.32", + "postcss-import": "12.0.1", + "postcss-loader": "4.0.4", + "raw-loader": "4.0.2", + "regenerator-runtime": "0.13.7", + "resolve-url-loader": "3.1.2", + "rimraf": "3.0.2", + "rollup": "2.32.1", + "rxjs": "6.6.3", + "sass": "1.27.0", + "sass-loader": "10.0.5", + "semver": "7.3.2", + "source-map": "0.7.3", + "source-map-loader": "1.1.2", + "source-map-support": "0.5.19", + "speed-measure-webpack-plugin": "1.3.3", + "style-loader": "2.0.0", + "stylus": "0.54.8", + "stylus-loader": "4.1.1", + "terser": "5.3.7", + "terser-webpack-plugin": "4.2.3", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "webpack": "4.44.2", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.11.0", + "webpack-merge": "5.2.0", + "webpack-sources": "2.0.1", + "webpack-subresource-integrity": "1.5.1", + "worker-plugin": "5.0.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^11.0.0 || ^11.0.0-next", + "@angular/localize": "^11.0.0 || ^11.0.0-next", + "karma": "~5.1.0", + "ng-packagr": "^11.0.0 || ^11.0.0-next", + "protractor": "^7.0.0", + "tslint": "^6.1.0", + "typescript": "~4.0.0" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tslint": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-optimizer": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.1.tgz", + "integrity": "sha512-PpqBmDd+/cmaMj9MURe5pSSudo+Qz6BrGdzvYB16ekSp8bSDYLUriv5NvE/bm+ODKwo3jHgFrwWLiwK65vQcxQ==", + "dev": true, + "dependencies": { + "loader-utils": "2.0.0", + "source-map": "0.7.3", + "tslib": "2.0.3", + "typescript": "4.0.5", + "webpack-sources": "2.0.1" + }, + "bin": { + "build-optimizer": "src/build-optimizer/cli.js" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "dev": true + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1100.1.tgz", + "integrity": "sha512-nfgsUfP6WyZ35rxgjqDYydB552Si/JdYLMtwy/kAFybW/6yTpw0sBOgCQoppyQ4mvVwyX9X0ZTQsMNhPOzy3sA==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^4.6.0", + "webpack-dev-server": "^3.1.4" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular-devkit/core": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.1.2.tgz", + "integrity": "sha512-V7zOMqL2l56JcwXVyswkG+7+t67r9XtkrVzRcG2Z5ZYwafU+iKWMwg5kBFZr1SX7fM1M9E4MpskxqtagQeUKng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular-devkit/schematics": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.0.1.tgz", + "integrity": "sha512-rAOnAndcybEH398xf5wzmcUPCoCi0dKiOo/+1dkKU5aTxynw1OUnANt5K6A+ZZTGnJmfjtP0ovkZGYun9IUDxQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.0.1", + "ora": "5.1.0", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular/animations": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.0.0.tgz", + "integrity": "sha512-RGaAnZOI73bPnNWrJq/p8sc+hpUBhScq139M6r4qQjQPsPahazL6v6hHAgRhZNemqw164d1oE4K/22O/i0E3Tw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "11.0.0" + } + }, + "node_modules/@angular/cdk": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-11.2.7.tgz", + "integrity": "sha512-18h7dyXHl/h+rsXFoNpqxiFCDhqewXVPpLG/WWeiFXKdtHeIk1yzfoSjo7nBzclicFFN/A+M2IQSIt21doJ0aA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "optionalDependencies": { + "parse5": "^5.0.0" + }, + "peerDependencies": { + "@angular/common": "^11.0.0 || ^12.0.0-0", + "@angular/core": "^11.0.0 || ^12.0.0-0" + } + }, + "node_modules/@angular/cdk/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "node_modules/@angular/cli": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.0.1.tgz", + "integrity": "sha512-zB20jTLQxLpkJjhbYelhRyMcgGsjwbD8pSYYAO6QX656Tx1tCtJ2UskEtf4ePQvgzu0Ds2dnAEfco+tekIMRTA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "@schematics/angular": "11.0.1", + "@schematics/update": "0.1100.1", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.2.0", + "ini": "1.3.5", + "inquirer": "7.3.3", + "npm-package-arg": "8.1.0", + "npm-pick-manifest": "6.1.0", + "open": "7.3.0", + "pacote": "9.5.12", + "resolve": "1.18.1", + "rimraf": "3.0.2", + "semver": "7.3.2", + "symbol-observable": "2.0.3", + "universal-analytics": "0.4.23", + "uuid": "8.3.1" + }, + "bin": { + "ng": "bin/ng" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@angular/cli/node_modules/resolve": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@angular/cli/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular/cli/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular/cli/node_modules/uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@angular/common": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-11.0.0.tgz", + "integrity": "sha512-chlbtxR7jpPs3Rc1ymdp3UfUzqEr57OFIxVMG6hROODclPQQk/7oOHdQB4hpUObaF9y4ZTLeKHKWiR/twi21Pg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "11.0.0", + "rxjs": "^6.5.3" + } + }, + "node_modules/@angular/compiler": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.0.0.tgz", + "integrity": "sha512-I7wVhdqvhtBTQTtW61z0lwPb1LiQQ0NOwjsbfN5sAc7/uwxw7em+Kyb/XJgBwgaTKtAL8bZEzdoQGLdsSKQF2g==", + "dependencies": { + "tslib": "^2.0.0" + } + }, + "node_modules/@angular/compiler-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.0.0.tgz", + "integrity": "sha512-zrd/cU9syZ8XuQ3ItfIGaKDn1ZBCWyiqdLVRH9VDmyNqQFiCc/VWQ9Th9z8qpLptgdpzE9+lKFgeZJTDtbcveQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.0.0", + "yargs": "15.3.0" + }, + "bin": { + "ivy-ngcc": "ngcc/main-ivy-ngcc.js", + "ng-xi18n": "src/extract_i18n.js", + "ngc": "src/main.js", + "ngcc": "ngcc/main-ngcc.js" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "@angular/compiler": "11.0.0", + "typescript": ">=4.0 <4.1" + } + }, + "node_modules/@angular/compiler-cli/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/compiler-cli/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/yargs": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", + "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/core": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-11.0.0.tgz", + "integrity": "sha512-FNewyMwYy+kGdw1xWfrtaPD2cSQs3kDVFbl8mNMSzp933W5yMsHDvjXb0+nPFqEb8ywEIdm3MsBMK0y3iBWZQw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3", + "zone.js": "~0.10.3" + } + }, + "node_modules/@angular/forms": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.0.9.tgz", + "integrity": "sha512-DHi4puesP5iSBToT4FZVqLYZZpZDlAy2wgBe+OhCq7GCIqi8OLejB3bp9BnUd/WnNAHJd3zEjytexih6EPE0Xg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.0.9", + "@angular/core": "11.0.9", + "@angular/platform-browser": "11.0.9", + "rxjs": "^6.5.3" + } + }, + "node_modules/@angular/language-service": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-11.0.9.tgz", + "integrity": "sha512-wmt/siAwHUMNIXeu4OCW3z6JtP/VoJLkiQXDfSnetuCfHwy401b72L4h+TWiX3x2ZLzeYwmi0sbqMb5UCctrIw==", + "dev": true + }, + "node_modules/@angular/material": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-11.2.7.tgz", + "integrity": "sha512-mNIGKxBzZGlOEezprInTiQIwktiz9XSJuxZ2fp6rtJ7jqpSrUprCwBECRl6X62JWrDVwIFTDQO1FxS3mrBIZ2Q==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/animations": "^11.0.0 || ^12.0.0-0", + "@angular/cdk": "11.2.7", + "@angular/common": "^11.0.0 || ^12.0.0-0", + "@angular/core": "^11.0.0 || ^12.0.0-0", + "@angular/forms": "^11.0.0 || ^12.0.0-0" + } + }, + "node_modules/@angular/platform-browser": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.0.9.tgz", + "integrity": "sha512-snuq8SaIRuVDYJLy80kYCEuVITZZbtG3PvxamATvzpgYpAzBskToc4/7LKJk0IEVSMvKzi8eSBCDaK2f2ZJB3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/animations": "11.0.9", + "@angular/common": "11.0.9", + "@angular/core": "11.0.9" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.9.tgz", + "integrity": "sha512-OCbXCXxPvpPu7vh3Ra1X+FfqA27TP2NcL/AlWhPTSGB+ggrEUgfdUjBSsULpMVPsD6pG/runGdM9CQjEK7g+DQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.0.9", + "@angular/compiler": "11.0.9", + "@angular/core": "11.0.9", + "@angular/platform-browser": "11.0.9" + } + }, + "node_modules/@angular/router": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-11.0.9.tgz", + "integrity": "sha512-WopMMhOw4YT8cplDXxxnTS7ByaGop3+frLOkVirY9MKcpcqLwXPblVq4rNKn395XgBVjNK6hmU91RScBnAuVLQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.0.9", + "@angular/core": "11.0.9", + "@angular/platform-browser": "11.0.9", + "rxjs": "^6.5.3" + } + }, + "node_modules/@auth0/angular-jwt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-5.0.2.tgz", + "integrity": "sha512-rSamC9mu+gUxoR86AXcIo+KD7xRIro+/iu1F2Ld85YAZEVKlpB5vYG+g0yGaEOqjtQWP/i0H6fi6XMGPVHSYYQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=9.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.12.tgz", + "integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ==", + "dev": true + }, + "node_modules/@babel/core": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", + "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.1", + "@babel/parser": "^7.12.3", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.1", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", + "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-annotate-as-pure/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz", + "integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz", + "integrity": "sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.12", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.13.11", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz", + "integrity": "sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-split-export-declaration": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", + "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.12.13", + "regexpu-core": "^4.7.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-map": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.13.12.tgz", + "integrity": "sha512-r9/bcpR9n3FHH4Iq9Pz96mvnBbV4D8aDYUW5HjkR8eaQhJmsGshRh1bfOalGKofWOB/3KVFtmLf0iJi7/6Lgfg==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.12.13", + "@babel/types": "^7.13.12" + } + }, + "node_modules/@babel/helper-define-map/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", + "integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-get-function-arity/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz", + "integrity": "sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-hoist-variables/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.12" + } + }, + "node_modules/@babel/helper-member-expression-to-functions/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.12" + } + }, + "node_modules/@babel/helper-module-imports/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz", + "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.13", + "@babel/types": "^7.13.14" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-optimise-call-expression/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", + "dev": true + }, + "node_modules/@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz", + "integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-wrap-function": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.13.12", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-replace-supers/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.12" + } + }, + "node_modules/@babel/helper-simple-access/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.1" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "dev": true + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz", + "integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", + "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/helpers/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", + "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", + "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", + "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", + "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", + "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", + "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz", + "integrity": "sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", + "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", + "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", + "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", + "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", + "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", + "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", + "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", + "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", + "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", + "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-identifier": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs/node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", + "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", + "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", + "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", + "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", + "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", + "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", + "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", + "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", + "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.12.1", + "@babel/helper-compilation-targets": "^7.12.1", + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.1", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.1", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.1", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.1", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.1", + "core-js-compat": "^3.6.2", + "semver": "^5.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", + "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/template/node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/template/node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz", + "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.5", + "@babel/types": "^7.12.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz", + "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/traverse/node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/traverse/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/types": { + "version": "7.12.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz", + "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/types/node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@briebug/jest-schematic": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@briebug/jest-schematic/-/jest-schematic-2.1.1.tgz", + "integrity": "sha512-AZMjSWvfk8NcCR3LuIKuLSN3zHJYnKmWMoFoLR6WATWfRR+WYNKlDLz/OUEKLu8gqSTY0eH0e2WxE3QEICNDJw==", + "dependencies": { + "@angular-devkit/core": "^8.2.0", + "@angular-devkit/schematics": "^8.2.0", + "@schematics/angular": "^8.2.0", + "rxjs": "6.4.0" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/@angular-devkit/core": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.28.tgz", + "integrity": "sha512-tM0oPjzftJMdfuAuZF2EspVKtJyhtS2IQ02S7eKTZqkh5p/oVv710aND2D2IN5qdFrzpUSearx6D+Mr/Jo8jrA==", + "dependencies": { + "ajv": "6.10.2", + "fast-json-stable-stringify": "2.0.0", + "magic-string": "0.25.3", + "rxjs": "6.4.0", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.9.0", + "npm": ">= 6.2.0" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/@angular-devkit/schematics": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.28.tgz", + "integrity": "sha512-WFktBtTynViexVrgHiQV9rKfNS2YNONpi25A8+5tQR5kGKuQyHI3aEN0UMNA2sztWnPQ9AI8xz2uciQsHljgDw==", + "dependencies": { + "@angular-devkit/core": "8.3.28", + "rxjs": "6.4.0" + }, + "engines": { + "node": ">= 10.9.0", + "npm": ">= 6.2.0" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/@schematics/angular": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.28.tgz", + "integrity": "sha512-XS+eB/XwS+C97UW/WFQFvkrIzcPZF4qILOX3xZkJflJ3OtaM3q/WKoHxJVRDZWBJQlaNHv2X4UZZWN1LP3o7dw==", + "dependencies": { + "@angular-devkit/core": "8.3.28", + "@angular-devkit/schematics": "8.3.28" + }, + "engines": { + "node": ">= 10.9.0", + "npm": ">= 6.2.0" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dependencies": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@briebug/jest-schematic/node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "dependencies": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + } + }, + "node_modules/@ngneat/tailwind": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@ngneat/tailwind/-/tailwind-6.0.3.tgz", + "integrity": "sha512-LF0f2Z1+MkVu+M98miO7OaTNEAtGqvlu/UC+QqcaaVQWPIcD0gC6ETaGYb73fuCimEDrEhuXlZ10ktzcMybrXg==" + }, + "node_modules/@ngrx/effects": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-10.0.0.tgz", + "integrity": "sha512-HHcQQ6mj1Cd0rQgnX5Wp3f7G8PKhh+Rk+jofsOsE6aHQPuuNhmnDwSA1U4PT4sXNv6JmFi5GjUqBz+tuw83oFQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "^10.0.0", + "@ngrx/store": "10.0.0", + "rxjs": "^6.5.3" + } + }, + "node_modules/@ngrx/router-store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-10.0.0.tgz", + "integrity": "sha512-naK+IlgTQNEWWlKndQIBS/EQZ2h3pRF4owF+4kVpn+OI5Il7+Nugf0spj+0IFGd21Z7YvBe9C54SQPOPP4HARg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "^10.0.0", + "@angular/core": "^10.0.0", + "@angular/router": "^10.0.0", + "@ngrx/store": "10.0.0", + "rxjs": "^6.5.3" + } + }, + "node_modules/@ngrx/schematics": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/schematics/-/schematics-10.0.0.tgz", + "integrity": "sha512-MAZaxTEzny92ISMmHPu1djQFZRDpC875mJ2WhBQrNe66EBXIkJq7feb9/26hH1mKmOqVR83k9TpXPsJA9YimgA==" + }, + "node_modules/@ngrx/store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-10.0.0.tgz", + "integrity": "sha512-+mhTGJXjc+55KI1pWV5SSuP+JBAr35U1AbnBYJqqXuwJVXnJ8+n6gAr06qpPN+YMf+zRQDFwAIrqyFOfMqeJHg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "^10.0.0", + "rxjs": "^6.5.3" + } + }, + "node_modules/@ngrx/store-devtools": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-10.0.0.tgz", + "integrity": "sha512-+7SSPW9H+IdGX04QYmfgqYOeFM++PLD6CxGRUkIIc+6jFovanMS6CVKw6V+WeerPwoZaRn43cMIDj9FChMQ4oA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@ngrx/store": "10.0.0", + "rxjs": "^6.5.3" + } + }, + "node_modules/@ngtools/webpack": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.0.1.tgz", + "integrity": "sha512-z62qQ4J5LhDxW68HjYYCRo+sDK/5yHwX4fCCY2iXngyTtA5cQbGI5WXr3+9B4foX64ft5WvV0WJkx8mjE/VR6w==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.0.1", + "enhanced-resolve": "5.3.1", + "webpack-sources": "2.0.1" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^11.0.0 || ^11.0.0-next", + "typescript": "~4.0.0", + "webpack": "^4.0.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@schematics/angular": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.0.1.tgz", + "integrity": "sha512-cYq3NhFn4DLSXXtbYYU2w0sginkMfN1w7pXjZLT/+etXXbtANQAXSPrPrDQql004ZNMbuDKuC0aoXjv8hgXOfw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "jsonc-parser": "2.3.1" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@schematics/update": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1100.1.tgz", + "integrity": "sha512-EVcqdM/d5rC5L1UYnwhFMk/TjHlNgL5LGfroE13C38A+WpKKJquAjgOQLj4nPvJ5csdEZqn3Sui9yeEWc3hklQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "npm-package-arg": "^8.0.0", + "pacote": "9.5.12", + "semver": "7.3.2", + "semver-intersect": "1.4.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/update/node_modules/@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 6.11.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/update/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/@schematics/update/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tailwindcss/aspect-ratio": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.2.0.tgz", + "integrity": "sha512-v5LyHkwXj/4lI74B06zUrmWEdmSqS43+jw717pkt3fAXqb7ALwu77A8t7j+Bej+ZbdlIIqNMYheGN7wSGV1A6w==", + "dev": true + }, + "node_modules/@tailwindcss/forms": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.2.tgz", + "integrity": "sha512-aj2/rJsGb2whAZ/BQWHWWQRSbhH0r/l1ozOByiv+ZNjBD84GMvb5dhAyfpeasFky+EJrAwX5eaqft8NQMZFWvA==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=2.0.0" + } + }, + "node_modules/@tailwindcss/line-clamp": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.2.0.tgz", + "integrity": "sha512-+jXSdRK3/9V/BCPCr+iNpMMhxWMMv62vn/AS2b3/ClmueGuhCijW3bUwO1IiHnE7uCaF74Sli8jUCv9djwvpLg==", + "dev": true + }, + "node_modules/@tailwindcss/typography": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.4.0.tgz", + "integrity": "sha512-3BfOYT5MYNEq81Ism3L2qu/HRP2Q5vWqZtZRQqQrthHuaTK9qpuPfbMT5WATjAM5J1OePKBaI5pLoX4S1JGNMQ==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "peerDependencies": { + "tailwindcss": "2.0.0-alpha.24 || ^2.0.0" + } + }, + "node_modules/@tinymce/tinymce-angular": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tinymce/tinymce-angular/-/tinymce-angular-4.2.2.tgz", + "integrity": "sha512-zFAlEKlTVuUXea8bWKF+pM0MkQltQRKinO8Ej+kGZo8SoRMtHV2hC9DaRzC1DgLkQsiEqgVPAdj7Bdm8HAsreg==", + "dependencies": { + "tslib": "^1.10.0" + }, + "peerDependencies": { + "@angular/common": ">=9.0.0", + "@angular/core": ">=9.0.0", + "@angular/forms": ">=9.0.0" + } + }, + "node_modules/@tinymce/tinymce-angular/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.1.tgz", + "integrity": "sha512-eeSCVhBsgwHNS1FmaMu4zrLxfykCTWJMLFZv7lmyrZQjw7foUUXoPu4GukSN9v7JvUw7X+/aDH3kCaymirBSTg==", + "dev": true + }, + "node_modules/@types/jasminewd2": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.8.tgz", + "integrity": "sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg==", + "dev": true, + "dependencies": { + "@types/jasmine": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/luxon": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-1.11.1.tgz", + "integrity": "sha512-XBHQ7rzpOHyJudEQcMyoT67Np61FTb6S2jWqWQER/U7H2NAS+dpC8wv5T+6ygV5g/yJQdaojQbsJQiweool0Aw==" + }, + "node_modules/@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "12.12.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz", + "integrity": "sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "node_modules/@types/selenium-webdriver": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz", + "integrity": "sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==", + "dev": true + }, + "node_modules/@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "node_modules/@types/webpack-sources": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + } + }, + "node_modules/@types/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz", + "integrity": "sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ajv/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "dependencies": { + "type-fest": "^0.11.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "node_modules/arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "node_modules/axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7" + } + }, + "node_modules/babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 6.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/babel-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "dependencies": { + "callsite": "1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "node_modules/blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "blocking-proxy": "built/lib/bin.js" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/browserstack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.0.tgz", + "integrity": "sha512-HJDJ0TSlmkwnt9RZ+v5gFpa1XZTBYTj0ywvLwJ3241J7vMw2jAsGNVhKHtmCOyg+VxeLZyaibO9UL71AsUeDIw==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "dependencies": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chrome-trace-event/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/circular-dependency-plugin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz", + "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": ">=4.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", + "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "node_modules/codelyzer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.1.tgz", + "integrity": "sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g==", + "dev": true, + "dependencies": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "peerDependencies": { + "@angular/compiler": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", + "@angular/core": ">=2.3.1 <12.0.0 || ^11.0.0-next || ^11.1.0-next || ^11.2.0-next", + "tslint": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", + "dev": true, + "peerDependencies": { + "tslib": "^1.10.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", + "dev": true, + "peerDependencies": { + "rxjs": "^6.5.3", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" + } + }, + "node_modules/codelyzer/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codelyzer/node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "node_modules/codelyzer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.1", + "color-string": "^1.5.4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "node_modules/compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", + "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", + "dev": true, + "dependencies": { + "arity-n": "^1.0.4" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.2.1.tgz", + "integrity": "sha512-VH2ZTMIBsx4p++Lmpg77adZ0KUyM5gFR/9cuTrbneNnJlcQXUFvsNariPqq2dq2kV3F2skHiDGPQCyKWy1+U0Q==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/copy-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz", + "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==", + "dev": true, + "dependencies": { + "browserslist": "^4.14.6", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "engines": { + "node": ">4" + } + }, + "node_modules/css-declaration-sorter/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-declaration-sorter/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.0.0.tgz", + "integrity": "sha512-9g35eXRBgjvswyJWoqq/seWp+BOxvUl8IinVNTsUBFFxtwfEYvlmEn6ciyn0liXGbGh5HyJjPGCuobDSfqMIVg==", + "dev": true, + "dependencies": { + "camelcase": "^6.1.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.0.0", + "loader-utils": "^2.0.0", + "postcss": "^8.1.1", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/css-loader/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "node_modules/css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "dev": true + }, + "node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "dependencies": { + "through": "X.X.X" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "dependencies": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/cssnano-preset-default/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/cssnano-util-raw-cache/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/cssnano/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/csso": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.1.0.tgz", + "integrity": "sha512-h+6w/W1WqXaJA4tb1dk7r5tVbOm97MsKxzwnvOR04UQ6GILroryjMWu3pmCCtL2mLaEStQ0fZgeGiy99mo7iyg==", + "dev": true, + "dependencies": { + "css-tree": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.1.tgz", + "integrity": "sha512-WroX+2MvsYcRGP8QA0p+rxzOniT/zpAoQ/DTKDSJzh5T3IQKUkFHeIIfgIapm2uaP178GWY3Mime1qbk8GO/tA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.12", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.12.tgz", + "integrity": "sha512-ULbAlgzVb8IqZ0Hsxm6hHSlQl3Jckst2YEQS7fODu9ilNWy2LvcoSY7TRFIktABP2mdppBioc66va90T+NUs8Q==", + "dev": true + }, + "node_modules/csso/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "node_modules/detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.385", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.385.tgz", + "integrity": "sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", + "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "0.3.1", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/engine.io-client": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", + "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", + "dev": true, + "dependencies": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/engine.io-client/node_modules/parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true + }, + "node_modules/engine.io-client/node_modules/parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "dev": true, + "dependencies": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/enhanced-resolve": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.3.1.tgz", + "integrity": "sha512-G1XD3MRGrGfNcf6Hg0LVZG7GIKcYkbfHa5QMxt1HDUTdYoXH0JR1xXyg+MaKLF73E9A27uWNVxvFivNRYeUB6w==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", + "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-loader": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.1.1.tgz", + "integrity": "sha512-Klt8C4BjWSXYQAfhpYYkG4qHNTna4toMHEbWrI5IuVoxbU6uiDKeKAP99R8mmbJi3lvewn/jQBOgU4+NS3tDQw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "dependencies": { + "isarray": "2.0.1" + } + }, + "node_modules/has-binary2/node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "node_modules/has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-value/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hosted-git-info": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, + "node_modules/html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "dependencies": { + "agent-base": "4", + "debug": "3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "dependencies": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.0.0.tgz", + "integrity": "sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "dependencies": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "dependencies": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "node_modules/is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "dependencies": { + "html-comment-regex": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "dependencies": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, + "node_modules/jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "node_modules/jasmine-spec-reporter": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", + "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jasmine/node_modules/jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + }, + "node_modules/jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true, + "engines": { + "node": ">= 6.9.x" + } + }, + "node_modules/jest-worker": { + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", + "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/jszip": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", + "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "node_modules/karma": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz", + "integrity": "sha512-xAlOr5PMqUbiKXSv5PCniHWV3aiwj6wIZ0gUVcwpTCPVQm/qH2WAMFWxtnpM6KJqhkRWrIpovR4Rb0rn8GtJzQ==", + "dev": true, + "dependencies": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "flatted": "^2.0.2", + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.6", + "lodash": "^4.17.15", + "log4js": "^6.2.1", + "mime": "^2.4.5", + "minimatch": "^3.0.4", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^2.3.0", + "source-map": "^0.6.1", + "tmp": "0.2.1", + "ua-parser-js": "0.7.21", + "yargs": "^15.3.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-coverage-istanbul-reporter": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz", + "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^3.0.2", + "minimatch": "^3.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/mattlewis92" + } + }, + "node_modules/karma-jasmine": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", + "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", + "dev": true, + "dependencies": { + "jasmine-core": "^3.6.0" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "karma": "*" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.3.tgz", + "integrity": "sha512-ci0VrjuCaFj+9d1tYlTE3KIPUCp0rz874zWWU3JgCMqGIyw5ke+BXWFPOAGAqUdCJcrMwneyvp1zFXA74MiPUA==", + "dev": true, + "peerDependencies": { + "jasmine-core": ">=3.5", + "karma": ">=0.9", + "karma-jasmine": ">=1.1" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/karma/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/less": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/less/-/less-3.12.2.tgz", + "integrity": "sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q==", + "dev": true, + "dependencies": { + "tslib": "^1.10.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.0.2.tgz", + "integrity": "sha512-7MKlgjnkCf63E3Lv6w2FvAEgLMx3d/tNBExITcanAq7ys5U8VPWT3F6xcRjYmdNfkoQ9udoVFb1r2azSiTnD6w==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/less-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/less/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/license-webpack-plugin": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.1.tgz", + "integrity": "sha512-yhqTmlYIEpZWA122lf6E0G8+rkn0AzoQ1OpzUKKs/lXUqG1plmGnwmkuuPlfggzJR5y6DLOdot/Tv00CC51CeQ==", + "dev": true, + "dependencies": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + } + }, + "node_modules/license-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/license-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.topath": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "dev": true, + "dependencies": { + "date-format": "^3.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.1", + "rfdc": "^1.1.4", + "streamroller": "^2.2.4" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/loglevel": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", + "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-loglevel?utm_medium=referral&utm_source=npm_fund" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/luxon": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.24.0.tgz", + "integrity": "sha512-PNeB5cFbBtmuS137OuEdaJnCMTMPS2vz9hnM1Zl6tUIuYdtUgEhMqfVZ7yxX0jHEGx6rp757ECe7cdZxDgq2Tg==", + "engines": { + "node": "*" + } + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "dependencies": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.2.1.tgz", + "integrity": "sha512-G3yw7/TQaPfkuiR73MDcyiqhyP8SnbmLhUbpC76H+wtQxA6wfKhMCQOCb6wnPK0dQbjORAeOILQqEesg4/wF7A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "webpack-sources": "^1.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/modern-normalize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.1.0.tgz", + "integrity": "sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/native-request": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz", + "integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==", + "dev": true, + "optional": true + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/ngx-material-timepicker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/ngx-material-timepicker/-/ngx-material-timepicker-5.5.3.tgz", + "integrity": "sha512-Ua6eNNNneHS8S1/3Tn2dUOnLdZ4k6MhQqvLM/eFVoeF0WF+q/uK1DAH8eAki3HW1ogq2oDWnVRSeXvvZGJldhQ==", + "dependencies": { + "@types/luxon": "1.11.1", + "luxon": "1.24.0", + "tslib": "^1.9.0" + } + }, + "node_modules/ngx-material-timepicker/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/ngx-multiple-dates": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/ngx-multiple-dates/-/ngx-multiple-dates-13.1.0.tgz", + "integrity": "sha512-k33tEKJ4jtV1X7nDD6v4lK7hLo3TnEw7wXg59rUhPCneVAQtNzY/n1BnGELzUNSGZFgs1lODoMPMedLTxPhS3w==", + "dependencies": { + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@angular/cdk": "^13.1.3", + "@angular/common": "^13.1.3", + "@angular/core": "^13.1.3", + "@angular/forms": "^13.1.3", + "@angular/material": "^13.1.3", + "rxjs": "^7.5.2" + } + }, + "node_modules/ngx-progressbar": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ngx-progressbar/-/ngx-progressbar-6.1.1.tgz", + "integrity": "sha512-6FbCxbhy+lwX0hzfrr+pp4wAf0tX85664j1tnEdRd6LIfSTlUtXARiyUbGAEMyDS9MCbXhQhJyIylsJrB3gYOg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=8.0.0", + "@angular/core": ">=8.0.0", + "@angular/router": ">=8.0.0", + "rxjs": ">=6.0.0" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "dependencies": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "node_modules/npm-package-arg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", + "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "dev": true, + "dependencies": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-pick-manifest": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz", + "integrity": "sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw==", + "dev": true, + "dependencies": { + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + } + }, + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-registry-fetch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.7.tgz", + "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "JSONStream": "^1.3.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/npm-registry-fetch/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-registry-fetch/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-visit/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/oidc-client": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.11.5.tgz", + "integrity": "sha512-LcKrKC8Av0m/KD/4EFmo9Sg8fSQ+WFJWBrmtWd+tZkNn3WT/sQG3REmPANE9tzzhbjW6VkTNy4xhAXCfPApAOg==", + "dependencies": { + "acorn": "^7.4.1", + "base64-js": "^1.5.1", + "core-js": "^3.8.3", + "crypto-js": "^4.0.0", + "serialize-javascript": "^4.0.0" + } + }, + "node_modules/oidc-client/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/oidc-client/node_modules/core-js": { + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/oidc-client/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz", + "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/opn/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz", + "integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.4.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "mute-stream": "0.0.8", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "dependencies": { + "url-parse": "^1.4.3" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "9.5.12", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.12.tgz", + "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^3.0.0", + "npm-registry-fetch": "^4.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + } + }, + "node_modules/pacote/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/pacote/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/pacote/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/pacote/node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/pacote/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/pacote/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/pacote/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/pacote/node_modules/npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "node_modules/pacote/node_modules/npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "node_modules/pacote/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/pacote/node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/pacote/node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/pacote/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "dependencies": { + "better-assert": "~1.0.0" + } + }, + "node_modules/parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "dependencies": { + "better-assert": "~1.0.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "dependencies": { + "ts-pnp": "^1.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/postcss-calc/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-calc/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-colormin/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-colormin/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-colormin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-convert-values/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-convert-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-comments/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-comments/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-duplicates/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-duplicates/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-empty/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-empty/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-overridden/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-overridden/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-import/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-import/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-import/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz", + "integrity": "sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1", + "postcss": "^8.1.6" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-loader": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.0.4.tgz", + "integrity": "sha512-pntA9zIR14drQo84yGTjQJg1m7T0DkXR4vXYHBngiRZdJtEeCrojL6lOpqUanMzG375lIJbT4Yug85zC/AJWGw==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-loader/node_modules/parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-loader/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "dependencies": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-longhand/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-merge-longhand/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-merge-rules/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-font-values/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-font-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-gradients/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-gradients/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-params/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-params/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-minify-selectors/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-ng-tailwind-in-components": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/postcss-ng-tailwind-in-components/-/postcss-ng-tailwind-in-components-0.0.4.tgz", + "integrity": "sha512-AESphDCMXmE2WXxZRoIf5mgsSNO5WyYuMO65Fk0YnLEtusd9RhtIAOUUcdSWZKZ6p8Nch1y9Tt8HCgk5ebvmOw==", + "dev": true, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-charset/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-charset/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-display-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-positions/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-positions/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-repeat-style/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "dependencies": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-string/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-string/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-timing-functions/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-unicode/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "dependencies": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-url/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-url/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-whitespace/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-ordered-values/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-ordered-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-initial/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-reduce-initial/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-reduce-transforms/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", + "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "dependencies": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-svgo/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-svgo/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-svgo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-unique-selectors/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-unique-selectors/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "node_modules/promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "dependencies": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/promise-retry/node_modules/retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "dependencies": { + "genfun": "^5.0.0" + } + }, + "node_modules/protractor": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "dev": true, + "dependencies": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "bin": { + "protractor": "bin/protractor", + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=10.13.x" + } + }, + "node_modules/protractor/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "dependencies": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/protractor/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/protractor/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/protractor/node_modules/webdriver-manager": { + "version": "12.1.7", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz", + "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==", + "dev": true, + "dependencies": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "bin": { + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/purgecss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz", + "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==", + "dev": true, + "dependencies": { + "commander": "^8.0.0", + "glob": "^7.1.7", + "postcss": "^8.3.5", + "postcss-selector-parser": "^6.0.6" + }, + "bin": { + "purgecss": "bin/purgecss.js" + } + }, + "node_modules/purgecss/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "dev": true, + "dependencies": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + } + }, + "node_modules/reduce-css-calc/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/resolve-url-loader": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz", + "integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "3.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/resolve-url-loader/node_modules/emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "dependencies": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + } + }, + "node_modules/rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, + "node_modules/rework/node_modules/convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "node_modules/rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rollup": { + "version": "2.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz", + "integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz", + "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==", + "dev": true, + "dependencies": { + "chokidar": ">=2.0.0 <4.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/sass-loader": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.5.tgz", + "integrity": "sha512-2LqoNPtKkZq/XbXNQ4C64GFEleSEHKv6NPSI+bMC/l+jpEXGJhiRYkAQToO24MR7NU4JRY2RpLpJ/gjo2Uf13w==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/sass-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/sass-loader/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "dependencies": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/selenium-webdriver/node_modules/tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "dependencies": { + "semver": "^5.3.0" + } + }, + "node_modules/semver-dsl/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "dependencies": { + "semver": "^5.0.0" + } + }, + "node_modules/semver-intersect/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socket.io": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", + "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", + "dev": true, + "dependencies": { + "debug": "~4.1.0", + "engine.io": "~3.4.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "node_modules/socket.io-client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "dev": true, + "dependencies": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + } + }, + "node_modules/socket.io-client/node_modules/base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/socket.io-client/node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/socket.io-client/node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "node_modules/socket.io-client/node_modules/socket.io-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", + "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "dev": true, + "dependencies": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "node_modules/socket.io-client/node_modules/socket.io-parser/node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/socket.io-client/node_modules/socket.io-parser/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/socket.io-client/node_modules/socket.io-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/socket.io-parser": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", + "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", + "dev": true, + "dependencies": { + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" + } + }, + "node_modules/socket.io-parser/node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/socket.io-parser/node_modules/isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sockjs": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", + "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.10.0", + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" + } + }, + "node_modules/sockjs-client": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "dev": true, + "dependencies": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sockjs-client/node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "dependencies": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + }, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "dependencies": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.1.2.tgz", + "integrity": "sha512-bjf6eSENOYBX4JZDfl9vVLNsGAQ6Uz90fLmOazcmMcyDYOBFsGxPNn83jXezWLY9bJsVAo1ObztxPcV8HAbjVA==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "source-map": "^0.6.1", + "whatwg-mimetype": "^2.3.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/source-map-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/speed-measure-webpack-plugin": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.3.tgz", + "integrity": "sha512-2ljD4Ch/rz2zG3HsLsnPfp23osuPBS0qPuz9sGpkNXTN1Ic4M+W9xB8l8rS8ob2cO4b1L+WTJw/0AJwWYVgcxQ==", + "dev": true, + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": "^1 || ^2 || ^3 || ^4" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", + "dev": true, + "dependencies": { + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart/node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/style-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/stylehacks/node_modules/postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylehacks/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-4.1.1.tgz", + "integrity": "sha512-Vnm7J/nIs/P6swIrdwJW/dflhsCOiFmb1U3PeQ6phRtg1soPLN4uKnnL7AtGIJDe173elbtYIXVzmCyF493CfA==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.4", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "stylus": ">=0.52.4", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/stylus-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/stylus/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/stylus/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stylus/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/stylus/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/sweetalert2": { + "version": "10.16.11", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-10.16.11.tgz", + "integrity": "sha512-Rdfabv2G89Tr8vmUTb1auWCYYesKBEWnkYPSi7XaiCIW0ZXXGK8Nw1wYKPEMLU6O8gMSMJe5m6MRKqMQsAQy9A==", + "funding": { + "url": "https://sweetalert2.github.io/#donations" + } + }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tailwindcss": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-2.2.19.tgz", + "integrity": "sha512-6Ui7JSVtXadtTUo2NtkBBacobzWiQYVjYW0ZnKaP9S1ZCKQ0w7KVNz+YSDI/j7O7KCMHbOkz94ZMQhbT9pOqjw==", + "dev": true, + "dependencies": { + "arg": "^5.0.1", + "bytes": "^3.0.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "color": "^4.0.1", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.7", + "fs-extra": "^10.0.0", + "glob-parent": "^6.0.1", + "html-tags": "^3.1.0", + "is-color-stop": "^1.1.0", + "is-glob": "^4.0.1", + "lodash": "^4.17.21", + "lodash.topath": "^4.5.2", + "modern-normalize": "^1.1.0", + "node-emoji": "^1.11.0", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss-js": "^3.0.3", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.6", + "postcss-value-parser": "^4.1.0", + "pretty-hrtime": "^1.0.3", + "purgecss": "^4.0.3", + "quick-lru": "^5.1.1", + "reduce-css-calc": "^2.1.8", + "resolve": "^1.20.0", + "tmp": "^0.2.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "autoprefixer": "^10.0.2", + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/tailwindcss/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/tailwindcss/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/tailwindcss/node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/tailwindcss/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/tailwindcss/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/tailwindcss/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tailwindcss/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss/node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwindcss/node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/tailwindcss/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tailwindcss/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tailwindcss/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tailwindcss/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tapable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.1.1.tgz", + "integrity": "sha512-Wib1S8m2wdpLbmQz0RBEVosIyvb/ykfKXf3ZIDqvWoMg/zTNm6G/tDSuUM61J1kNCDXWJrLHGSFeMhAG+gAGpQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", + "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.7.tgz", + "integrity": "sha512-lJbKdfxWvjpV330U4PBZStCT9h3N9A4zZVA5Y4k9sCWXknrpdyxi1oMsRKLmQ/YDMDxSBKIh88v0SkdhdqX06w==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": "^10.0.0 || ^11.0.0 || ^12.0.0 || >=14.0.0" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tslint": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.2.tgz", + "integrity": "sha512-UyNrLdK3E0fQG/xWNqAFAC5ugtFyPO4JJR1KyyfQAyzR8W0fTRrC91A8Wej4BntFzcvETdCSDa/4PnNYJQLYiA==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.10.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/tslint/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", + "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universal-analytics": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", + "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "request": "^2.88.2", + "uuid": "^3.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "optional": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "dependencies": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", + "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", + "dev": true, + "dependencies": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.20", + "sockjs-client": "1.4.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/webpack-dev-server/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/webpack-dev-server/node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack-dev-server/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/webpack-dev-server/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/string-width/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/webpack-dev-server/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "dependencies": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-log/node_modules/ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-merge": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.2.0.tgz", + "integrity": "sha512-QBglJBg5+lItm3/Lopv8KDDK01+hjdg2azEwi/4vKJ8ZmGPdtJsTpjtNNOW3a4WiqzXdCATtTudOZJngE7RKkA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.0.1.tgz", + "integrity": "sha512-A9oYz7ANQBK5EN19rUXbvNgfdfZf5U2gP0769OXsj9CvYkCR6OHOsd6OKyEy4H38GGxpsQPKIL83NC64QY6Xmw==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.1.tgz", + "integrity": "sha512-uekbQ93PZ9e7BFB8Hl9cFIVYQyQqiXp2ExKk9Zv+qZfH/zHXHrCFAfw1VW0+NqWbTWrs/HnuDrto3+tiPXh//Q==", + "dev": true, + "dependencies": { + "webpack-sources": "^1.3.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 2.21.0 < 5", + "webpack": ">= 1.12.11 < 6" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack-subresource-integrity/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-subresource-integrity/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/webpack/node_modules/enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/webpack/node_modules/enhanced-resolve/node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/webpack/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/webpack/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/webpack/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "dependencies": { + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/worker-plugin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz", + "integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0" + }, + "peerDependencies": { + "webpack": ">= 4" + } + }, + "node_modules/worker-plugin/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/worker-plugin/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + } + }, + "dependencies": { + "@angular-builders/custom-webpack": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-11.1.1.tgz", + "integrity": "sha512-9l2yC9+QMwWj9IEsOpQtMIBcH87UMZdoR2+8DbIt53ypst/8aVMhMsKmR5n33wRkLlIJ6/ubyXldQymIHzoF1g==", + "dev": true, + "requires": { + "@angular-devkit/architect": ">=0.1100.0 < 0.1200.0", + "@angular-devkit/build-angular": ">=0.1100.0 < 0.1200.0", + "@angular-devkit/core": "^11.0.0", + "lodash": "^4.17.15", + "ts-node": "^9.0.0", + "tsconfig-paths": "^3.9.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } + }, + "@angular-devkit/architect": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1100.1.tgz", + "integrity": "sha512-DIAvTRRY+k7T2xHf4RVV06P16D0V7wSf1MSpGSDWVpfWcA3HNOSGfsk1F+COMlbFehXuKztwieXarv5rXbBCng==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.0.1", + "rxjs": "6.6.3" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@angular-devkit/build-angular": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1100.1.tgz", + "integrity": "sha512-w8NcoXuruOHio0D/JbX47iDl9FVH8X9k/OlZ/rSNVQ3uEpV6uxIaTm3fZ1ZSrKffi+97rKEwpHOf2N0DXl4XGQ==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/build-optimizer": "0.1100.1", + "@angular-devkit/build-webpack": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "@babel/core": "7.12.3", + "@babel/generator": "7.12.1", + "@babel/plugin-transform-runtime": "7.12.1", + "@babel/preset-env": "7.12.1", + "@babel/runtime": "7.12.1", + "@babel/template": "7.10.4", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "11.0.1", + "ansi-colors": "4.1.1", + "autoprefixer": "9.8.6", + "babel-loader": "8.1.0", + "browserslist": "^4.9.1", + "cacache": "15.0.5", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.0", + "copy-webpack-plugin": "6.2.1", + "core-js": "3.6.5", + "css-loader": "5.0.0", + "cssnano": "4.1.10", + "file-loader": "6.1.1", + "find-cache-dir": "3.3.1", + "glob": "7.1.6", + "inquirer": "7.3.3", + "jest-worker": "26.5.0", + "karma-source-map-support": "1.4.0", + "less": "3.12.2", + "less-loader": "7.0.2", + "license-webpack-plugin": "2.3.1", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "1.2.1", + "minimatch": "3.0.4", + "open": "7.3.0", + "ora": "5.1.0", + "parse5-html-rewriting-stream": "6.0.1", + "pnp-webpack-plugin": "1.6.4", + "postcss": "7.0.32", + "postcss-import": "12.0.1", + "postcss-loader": "4.0.4", + "raw-loader": "4.0.2", + "regenerator-runtime": "0.13.7", + "resolve-url-loader": "3.1.2", + "rimraf": "3.0.2", + "rollup": "2.32.1", + "rxjs": "6.6.3", + "sass": "1.27.0", + "sass-loader": "10.0.5", + "semver": "7.3.2", + "source-map": "0.7.3", + "source-map-loader": "1.1.2", + "source-map-support": "0.5.19", + "speed-measure-webpack-plugin": "1.3.3", + "style-loader": "2.0.0", + "stylus": "0.54.8", + "stylus-loader": "4.1.1", + "terser": "5.3.7", + "terser-webpack-plugin": "4.2.3", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "webpack": "4.44.2", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.11.0", + "webpack-merge": "5.2.0", + "webpack-sources": "2.0.1", + "webpack-subresource-integrity": "1.5.1", + "worker-plugin": "5.0.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + } + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.1.tgz", + "integrity": "sha512-PpqBmDd+/cmaMj9MURe5pSSudo+Qz6BrGdzvYB16ekSp8bSDYLUriv5NvE/bm+ODKwo3jHgFrwWLiwK65vQcxQ==", + "dev": true, + "requires": { + "loader-utils": "2.0.0", + "source-map": "0.7.3", + "tslib": "2.0.3", + "typescript": "4.0.5", + "webpack-sources": "2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "dev": true + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1100.1.tgz", + "integrity": "sha512-nfgsUfP6WyZ35rxgjqDYydB552Si/JdYLMtwy/kAFybW/6yTpw0sBOgCQoppyQ4mvVwyX9X0ZTQsMNhPOzy3sA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "rxjs": "6.6.3" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@angular-devkit/core": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.1.2.tgz", + "integrity": "sha512-V7zOMqL2l56JcwXVyswkG+7+t67r9XtkrVzRcG2Z5ZYwafU+iKWMwg5kBFZr1SX7fM1M9E4MpskxqtagQeUKng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "dependencies": { + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@angular-devkit/schematics": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.0.1.tgz", + "integrity": "sha512-rAOnAndcybEH398xf5wzmcUPCoCi0dKiOo/+1dkKU5aTxynw1OUnANt5K6A+ZZTGnJmfjtP0ovkZGYun9IUDxQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.0.1", + "ora": "5.1.0", + "rxjs": "6.6.3" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@angular/animations": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.0.0.tgz", + "integrity": "sha512-RGaAnZOI73bPnNWrJq/p8sc+hpUBhScq139M6r4qQjQPsPahazL6v6hHAgRhZNemqw164d1oE4K/22O/i0E3Tw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/cdk": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-11.2.7.tgz", + "integrity": "sha512-18h7dyXHl/h+rsXFoNpqxiFCDhqewXVPpLG/WWeiFXKdtHeIk1yzfoSjo7nBzclicFFN/A+M2IQSIt21doJ0aA==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.0.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + } + } + }, + "@angular/cli": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.0.1.tgz", + "integrity": "sha512-zB20jTLQxLpkJjhbYelhRyMcgGsjwbD8pSYYAO6QX656Tx1tCtJ2UskEtf4ePQvgzu0Ds2dnAEfco+tekIMRTA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1100.1", + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "@schematics/angular": "11.0.1", + "@schematics/update": "0.1100.1", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.2.0", + "ini": "1.3.5", + "inquirer": "7.3.3", + "npm-package-arg": "8.1.0", + "npm-pick-manifest": "6.1.0", + "open": "7.3.0", + "pacote": "9.5.12", + "resolve": "1.18.1", + "rimraf": "3.0.2", + "semver": "7.3.2", + "symbol-observable": "2.0.3", + "universal-analytics": "0.4.23", + "uuid": "8.3.1" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "resolve": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "dev": true, + "requires": { + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true + } + } + }, + "@angular/common": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-11.0.0.tgz", + "integrity": "sha512-chlbtxR7jpPs3Rc1ymdp3UfUzqEr57OFIxVMG6hROODclPQQk/7oOHdQB4hpUObaF9y4ZTLeKHKWiR/twi21Pg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/compiler": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.0.0.tgz", + "integrity": "sha512-I7wVhdqvhtBTQTtW61z0lwPb1LiQQ0NOwjsbfN5sAc7/uwxw7em+Kyb/XJgBwgaTKtAL8bZEzdoQGLdsSKQF2g==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/compiler-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.0.0.tgz", + "integrity": "sha512-zrd/cU9syZ8XuQ3ItfIGaKDn1ZBCWyiqdLVRH9VDmyNqQFiCc/VWQ9Th9z8qpLptgdpzE9+lKFgeZJTDtbcveQ==", + "dev": true, + "requires": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.0.0", + "yargs": "15.3.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "yargs": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", + "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.0" + } + } + } + }, + "@angular/core": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-11.0.0.tgz", + "integrity": "sha512-FNewyMwYy+kGdw1xWfrtaPD2cSQs3kDVFbl8mNMSzp933W5yMsHDvjXb0+nPFqEb8ywEIdm3MsBMK0y3iBWZQw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/forms": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.0.9.tgz", + "integrity": "sha512-DHi4puesP5iSBToT4FZVqLYZZpZDlAy2wgBe+OhCq7GCIqi8OLejB3bp9BnUd/WnNAHJd3zEjytexih6EPE0Xg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/language-service": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-11.0.9.tgz", + "integrity": "sha512-wmt/siAwHUMNIXeu4OCW3z6JtP/VoJLkiQXDfSnetuCfHwy401b72L4h+TWiX3x2ZLzeYwmi0sbqMb5UCctrIw==", + "dev": true + }, + "@angular/material": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-11.2.7.tgz", + "integrity": "sha512-mNIGKxBzZGlOEezprInTiQIwktiz9XSJuxZ2fp6rtJ7jqpSrUprCwBECRl6X62JWrDVwIFTDQO1FxS3mrBIZ2Q==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/platform-browser": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.0.9.tgz", + "integrity": "sha512-snuq8SaIRuVDYJLy80kYCEuVITZZbtG3PvxamATvzpgYpAzBskToc4/7LKJk0IEVSMvKzi8eSBCDaK2f2ZJB3A==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.9.tgz", + "integrity": "sha512-OCbXCXxPvpPu7vh3Ra1X+FfqA27TP2NcL/AlWhPTSGB+ggrEUgfdUjBSsULpMVPsD6pG/runGdM9CQjEK7g+DQ==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/router": { + "version": "11.0.9", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-11.0.9.tgz", + "integrity": "sha512-WopMMhOw4YT8cplDXxxnTS7ByaGop3+frLOkVirY9MKcpcqLwXPblVq4rNKn395XgBVjNK6hmU91RScBnAuVLQ==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@auth0/angular-jwt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-5.0.2.tgz", + "integrity": "sha512-rSamC9mu+gUxoR86AXcIo+KD7xRIro+/iu1F2Ld85YAZEVKlpB5vYG+g0yGaEOqjtQWP/i0H6fi6XMGPVHSYYQ==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/compat-data": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.12.tgz", + "integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ==", + "dev": true + }, + "@babel/core": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", + "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.1", + "@babel/parser": "^7.12.3", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", + "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz", + "integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.12.13", + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz", + "integrity": "sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.12", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.13.11", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz", + "integrity": "sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-split-export-declaration": "^7.12.13" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", + "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.12.13", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-define-map": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.13.12.tgz", + "integrity": "sha512-r9/bcpR9n3FHH4Iq9Pz96mvnBbV4D8aDYUW5HjkR8eaQhJmsGshRh1bfOalGKofWOB/3KVFtmLf0iJi7/6Lgfg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.12.13", + "@babel/types": "^7.13.12" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", + "integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-hoist-variables": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz", + "integrity": "sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g==", + "dev": true, + "requires": { + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.12" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-module-imports": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", + "dev": true, + "requires": { + "@babel/types": "^7.13.12" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-module-transforms": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz", + "integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.13", + "@babel/types": "^7.13.14" + }, + "dependencies": { + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-plugin-utils": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz", + "integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-wrap-function": "^7.13.0", + "@babel/types": "^7.13.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.13.12", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" + }, + "dependencies": { + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-simple-access": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", + "dev": true, + "requires": { + "@babel/types": "^7.13.12" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + }, + "dependencies": { + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz", + "integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helpers": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", + "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", + "dev": true, + "requires": { + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz", + "integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/traverse": { + "version": "7.13.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz", + "integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.13", + "@babel/types": "^7.13.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.13.14", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz", + "integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz", + "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", + "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", + "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", + "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", + "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", + "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.5.tgz", + "integrity": "sha512-UiAnkKuOrCyjZ3sYNHlRlfuZJbBHknMQ9VMwVeX97Ofwx7RpD6gS2HfqTCh8KNUQgcOm8IKt103oR4KIjh7Q8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", + "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", + "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", + "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", + "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", + "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", + "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", + "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", + "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", + "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", + "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-identifier": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + } + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", + "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", + "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", + "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", + "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", + "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", + "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", + "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", + "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", + "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.1", + "@babel/helper-compilation-targets": "^7.12.1", + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.1", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.1", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.1", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.1", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.1", + "core-js-compat": "^3.6.2", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", + "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + } + } + }, + "@babel/traverse": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz", + "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.5", + "@babel/types": "^7.12.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz", + "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.12.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz", + "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + } + } + }, + "@briebug/jest-schematic": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@briebug/jest-schematic/-/jest-schematic-2.1.1.tgz", + "integrity": "sha512-AZMjSWvfk8NcCR3LuIKuLSN3zHJYnKmWMoFoLR6WATWfRR+WYNKlDLz/OUEKLu8gqSTY0eH0e2WxE3QEICNDJw==", + "requires": { + "@angular-devkit/core": "^8.2.0", + "@angular-devkit/schematics": "^8.2.0", + "@schematics/angular": "^8.2.0", + "rxjs": "6.4.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.28.tgz", + "integrity": "sha512-tM0oPjzftJMdfuAuZF2EspVKtJyhtS2IQ02S7eKTZqkh5p/oVv710aND2D2IN5qdFrzpUSearx6D+Mr/Jo8jrA==", + "requires": { + "ajv": "6.10.2", + "fast-json-stable-stringify": "2.0.0", + "magic-string": "0.25.3", + "rxjs": "6.4.0", + "source-map": "0.7.3" + } + }, + "@angular-devkit/schematics": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.28.tgz", + "integrity": "sha512-WFktBtTynViexVrgHiQV9rKfNS2YNONpi25A8+5tQR5kGKuQyHI3aEN0UMNA2sztWnPQ9AI8xz2uciQsHljgDw==", + "requires": { + "@angular-devkit/core": "8.3.28", + "rxjs": "6.4.0" + } + }, + "@schematics/angular": { + "version": "8.3.28", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.28.tgz", + "integrity": "sha512-XS+eB/XwS+C97UW/WFQFvkrIzcPZF4qILOX3xZkJflJ3OtaM3q/WKoHxJVRDZWBJQlaNHv2X4UZZWN1LP3o7dw==", + "requires": { + "@angular-devkit/core": "8.3.28", + "@angular-devkit/schematics": "8.3.28" + } + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "requires": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + } + }, + "@ngneat/tailwind": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@ngneat/tailwind/-/tailwind-6.0.3.tgz", + "integrity": "sha512-LF0f2Z1+MkVu+M98miO7OaTNEAtGqvlu/UC+QqcaaVQWPIcD0gC6ETaGYb73fuCimEDrEhuXlZ10ktzcMybrXg==" + }, + "@ngrx/effects": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-10.0.0.tgz", + "integrity": "sha512-HHcQQ6mj1Cd0rQgnX5Wp3f7G8PKhh+Rk+jofsOsE6aHQPuuNhmnDwSA1U4PT4sXNv6JmFi5GjUqBz+tuw83oFQ==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngrx/router-store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-10.0.0.tgz", + "integrity": "sha512-naK+IlgTQNEWWlKndQIBS/EQZ2h3pRF4owF+4kVpn+OI5Il7+Nugf0spj+0IFGd21Z7YvBe9C54SQPOPP4HARg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngrx/schematics": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/schematics/-/schematics-10.0.0.tgz", + "integrity": "sha512-MAZaxTEzny92ISMmHPu1djQFZRDpC875mJ2WhBQrNe66EBXIkJq7feb9/26hH1mKmOqVR83k9TpXPsJA9YimgA==" + }, + "@ngrx/store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-10.0.0.tgz", + "integrity": "sha512-+mhTGJXjc+55KI1pWV5SSuP+JBAr35U1AbnBYJqqXuwJVXnJ8+n6gAr06qpPN+YMf+zRQDFwAIrqyFOfMqeJHg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngrx/store-devtools": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-10.0.0.tgz", + "integrity": "sha512-+7SSPW9H+IdGX04QYmfgqYOeFM++PLD6CxGRUkIIc+6jFovanMS6CVKw6V+WeerPwoZaRn43cMIDj9FChMQ4oA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngtools/webpack": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.0.1.tgz", + "integrity": "sha512-z62qQ4J5LhDxW68HjYYCRo+sDK/5yHwX4fCCY2iXngyTtA5cQbGI5WXr3+9B4foX64ft5WvV0WJkx8mjE/VR6w==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.0.1", + "enhanced-resolve": "5.3.1", + "webpack-sources": "2.0.1" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "@schematics/angular": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.0.1.tgz", + "integrity": "sha512-cYq3NhFn4DLSXXtbYYU2w0sginkMfN1w7pXjZLT/+etXXbtANQAXSPrPrDQql004ZNMbuDKuC0aoXjv8hgXOfw==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "jsonc-parser": "2.3.1" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + } + } + }, + "@schematics/update": { + "version": "0.1100.1", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1100.1.tgz", + "integrity": "sha512-EVcqdM/d5rC5L1UYnwhFMk/TjHlNgL5LGfroE13C38A+WpKKJquAjgOQLj4nPvJ5csdEZqn3Sui9yeEWc3hklQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.0.1", + "@angular-devkit/schematics": "11.0.1", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "npm-package-arg": "^8.0.0", + "pacote": "9.5.12", + "semver": "7.3.2", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.1.tgz", + "integrity": "sha512-ui3g7w/0SpU9oq8uwN9upR8Y1eOXZ+P2p3NyDydBrR7ZEfEkRLS1mhozN/ib8farrwK5N3kIIJxMb5t3187Hng==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@tailwindcss/aspect-ratio": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.2.0.tgz", + "integrity": "sha512-v5LyHkwXj/4lI74B06zUrmWEdmSqS43+jw717pkt3fAXqb7ALwu77A8t7j+Bej+ZbdlIIqNMYheGN7wSGV1A6w==", + "dev": true + }, + "@tailwindcss/forms": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.2.tgz", + "integrity": "sha512-aj2/rJsGb2whAZ/BQWHWWQRSbhH0r/l1ozOByiv+ZNjBD84GMvb5dhAyfpeasFky+EJrAwX5eaqft8NQMZFWvA==", + "dev": true, + "requires": { + "mini-svg-data-uri": "^1.2.3" + } + }, + "@tailwindcss/line-clamp": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.2.0.tgz", + "integrity": "sha512-+jXSdRK3/9V/BCPCr+iNpMMhxWMMv62vn/AS2b3/ClmueGuhCijW3bUwO1IiHnE7uCaF74Sli8jUCv9djwvpLg==", + "dev": true + }, + "@tailwindcss/typography": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.4.0.tgz", + "integrity": "sha512-3BfOYT5MYNEq81Ism3L2qu/HRP2Q5vWqZtZRQqQrthHuaTK9qpuPfbMT5WATjAM5J1OePKBaI5pLoX4S1JGNMQ==", + "dev": true, + "requires": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + } + }, + "@tinymce/tinymce-angular": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@tinymce/tinymce-angular/-/tinymce-angular-4.2.2.tgz", + "integrity": "sha512-zFAlEKlTVuUXea8bWKF+pM0MkQltQRKinO8Ej+kGZo8SoRMtHV2hC9DaRzC1DgLkQsiEqgVPAdj7Bdm8HAsreg==", + "requires": { + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.1.tgz", + "integrity": "sha512-eeSCVhBsgwHNS1FmaMu4zrLxfykCTWJMLFZv7lmyrZQjw7foUUXoPu4GukSN9v7JvUw7X+/aDH3kCaymirBSTg==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.8.tgz", + "integrity": "sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@types/luxon": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-1.11.1.tgz", + "integrity": "sha512-XBHQ7rzpOHyJudEQcMyoT67Np61FTb6S2jWqWQER/U7H2NAS+dpC8wv5T+6ygV5g/yJQdaojQbsJQiweool0Aw==" + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "12.12.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz", + "integrity": "sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz", + "integrity": "sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/webpack-sources": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "adjust-sourcemap-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz", + "integrity": "sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + } + }, + "adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "requires": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + } + }, + "browserstack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.0.tgz", + "integrity": "sha512-HJDJ0TSlmkwnt9RZ+v5gFpa1XZTBYTj0ywvLwJ3241J7vMw2jAsGNVhKHtmCOyg+VxeLZyaibO9UL71AsUeDIw==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + } + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz", + "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", + "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==", + "dev": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + } + } + }, + "codelyzer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.1.tgz", + "integrity": "sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g==", + "dev": true, + "requires": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "dependencies": { + "@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", + "dev": true + }, + "@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.4" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", + "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", + "dev": true, + "requires": { + "arity-n": "^1.0.4" + } + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.2.1.tgz", + "integrity": "sha512-VH2ZTMIBsx4p++Lmpg77adZ0KUyM5gFR/9cuTrbneNnJlcQXUFvsNariPqq2dq2kV3F2skHiDGPQCyKWy1+U0Q==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "dev": true + }, + "core-js-compat": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.7.0.tgz", + "integrity": "sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg==", + "dev": true, + "requires": { + "browserslist": "^4.14.6", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.0.0.tgz", + "integrity": "sha512-9g35eXRBgjvswyJWoqq/seWp+BOxvUl8IinVNTsUBFFxtwfEYvlmEn6ciyn0liXGbGh5HyJjPGCuobDSfqMIVg==", + "dev": true, + "requires": { + "camelcase": "^6.1.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.0.0", + "loader-utils": "^2.0.0", + "postcss": "^8.1.1", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "dev": true + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.1.0.tgz", + "integrity": "sha512-h+6w/W1WqXaJA4tb1dk7r5tVbOm97MsKxzwnvOR04UQ6GILroryjMWu3pmCCtL2mLaEStQ0fZgeGiy99mo7iyg==", + "dev": true, + "requires": { + "css-tree": "^1.0.0" + }, + "dependencies": { + "css-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.1.tgz", + "integrity": "sha512-WroX+2MvsYcRGP8QA0p+rxzOniT/zpAoQ/DTKDSJzh5T3IQKUkFHeIIfgIapm2uaP178GWY3Mime1qbk8GO/tA==", + "dev": true, + "requires": { + "mdn-data": "2.0.12", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.12.tgz", + "integrity": "sha512-ULbAlgzVb8IqZ0Hsxm6hHSlQl3Jckst2YEQS7fODu9ilNWy2LvcoSY7TRFIktABP2mdppBioc66va90T+NUs8Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.385", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.385.tgz", + "integrity": "sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", + "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "0.3.1", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", + "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.3.1.tgz", + "integrity": "sha512-G1XD3MRGrGfNcf6Hg0LVZG7GIKcYkbfHa5QMxt1HDUTdYoXH0JR1xXyg+MaKLF73E9A27uWNVxvFivNRYeUB6w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.0.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "fastq": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", + "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.1.1.tgz", + "integrity": "sha512-Klt8C4BjWSXYQAfhpYYkG4qHNTna4toMHEbWrI5IuVoxbU6uiDKeKAP99R8mmbJi3lvewn/jQBOgU4+NS3tDQw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", + "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.0.0.tgz", + "integrity": "sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + } + } + }, + "jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", + "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", + "dev": true, + "requires": { + "colors": "1.4.0" + } + }, + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true + }, + "jest-worker": { + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", + "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", + "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "karma": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz", + "integrity": "sha512-xAlOr5PMqUbiKXSv5PCniHWV3aiwj6wIZ0gUVcwpTCPVQm/qH2WAMFWxtnpM6KJqhkRWrIpovR4Rb0rn8GtJzQ==", + "dev": true, + "requires": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "flatted": "^2.0.2", + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.6", + "lodash": "^4.17.15", + "log4js": "^6.2.1", + "mime": "^2.4.5", + "minimatch": "^3.0.4", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^2.3.0", + "source-map": "^0.6.1", + "tmp": "0.2.1", + "ua-parser-js": "0.7.21", + "yargs": "^15.3.1" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz", + "integrity": "sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^3.0.2", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", + "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", + "dev": true, + "requires": { + "jasmine-core": "^3.6.0" + } + }, + "karma-jasmine-html-reporter": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.3.tgz", + "integrity": "sha512-ci0VrjuCaFj+9d1tYlTE3KIPUCp0rz874zWWU3JgCMqGIyw5ke+BXWFPOAGAqUdCJcrMwneyvp1zFXA74MiPUA==", + "dev": true + }, + "karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "dev": true + }, + "less": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/less/-/less-3.12.2.tgz", + "integrity": "sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q==", + "dev": true, + "requires": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "less-loader": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.0.2.tgz", + "integrity": "sha512-7MKlgjnkCf63E3Lv6w2FvAEgLMx3d/tNBExITcanAq7ys5U8VPWT3F6xcRjYmdNfkoQ9udoVFb1r2azSiTnD6w==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "license-webpack-plugin": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.1.tgz", + "integrity": "sha512-yhqTmlYIEpZWA122lf6E0G8+rkn0AzoQ1OpzUKKs/lXUqG1plmGnwmkuuPlfggzJR5y6DLOdot/Tv00CC51CeQ==", + "dev": true, + "requires": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.topath": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "dev": true, + "requires": { + "date-format": "^3.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.1", + "rfdc": "^1.1.4", + "streamroller": "^2.2.4" + } + }, + "loglevel": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", + "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "luxon": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.24.0.tgz", + "integrity": "sha512-PNeB5cFbBtmuS137OuEdaJnCMTMPS2vz9hnM1Zl6tUIuYdtUgEhMqfVZ7yxX0jHEGx6rp757ECe7cdZxDgq2Tg==" + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.2.1.tgz", + "integrity": "sha512-G3yw7/TQaPfkuiR73MDcyiqhyP8SnbmLhUbpC76H+wtQxA6wfKhMCQOCb6wnPK0dQbjORAeOILQqEesg4/wF7A==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "modern-normalize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.1.0.tgz", + "integrity": "sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-request": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz", + "integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==", + "dev": true, + "optional": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "ngx-material-timepicker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/ngx-material-timepicker/-/ngx-material-timepicker-5.5.3.tgz", + "integrity": "sha512-Ua6eNNNneHS8S1/3Tn2dUOnLdZ4k6MhQqvLM/eFVoeF0WF+q/uK1DAH8eAki3HW1ogq2oDWnVRSeXvvZGJldhQ==", + "requires": { + "@types/luxon": "1.11.1", + "luxon": "1.24.0", + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "ngx-multiple-dates": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/ngx-multiple-dates/-/ngx-multiple-dates-13.1.0.tgz", + "integrity": "sha512-k33tEKJ4jtV1X7nDD6v4lK7hLo3TnEw7wXg59rUhPCneVAQtNzY/n1BnGELzUNSGZFgs1lODoMPMedLTxPhS3w==", + "requires": { + "tslib": "^2.3.1" + } + }, + "ngx-progressbar": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ngx-progressbar/-/ngx-progressbar-6.1.1.tgz", + "integrity": "sha512-6FbCxbhy+lwX0hzfrr+pp4wAf0tX85664j1tnEdRd6LIfSTlUtXARiyUbGAEMyDS9MCbXhQhJyIylsJrB3gYOg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } + }, + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "requires": { + "semver": "^7.1.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", + "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz", + "integrity": "sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw==", + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "npm-registry-fetch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.7.tgz", + "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "JSONStream": "^1.3.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "oidc-client": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.11.5.tgz", + "integrity": "sha512-LcKrKC8Av0m/KD/4EFmo9Sg8fSQ+WFJWBrmtWd+tZkNn3WT/sQG3REmPANE9tzzhbjW6VkTNy4xhAXCfPApAOg==", + "requires": { + "acorn": "^7.4.1", + "base64-js": "^1.5.1", + "core-js": "^3.8.3", + "crypto-js": "^4.0.0", + "serialize-javascript": "^4.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "core-js": { + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==" + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz", + "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, + "ora": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz", + "integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.4.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "mute-stream": "0.0.8", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pacote": { + "version": "9.5.12", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.12.tgz", + "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^3.0.0", + "npm-registry-fetch": "^4.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "requires": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + } + }, + "parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz", + "integrity": "sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1", + "postcss": "^8.1.6" + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-loader": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.0.4.tgz", + "integrity": "sha512-pntA9zIR14drQo84yGTjQJg1m7T0DkXR4vXYHBngiRZdJtEeCrojL6lOpqUanMzG375lIJbT4Yug85zC/AJWGw==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-ng-tailwind-in-components": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/postcss-ng-tailwind-in-components/-/postcss-ng-tailwind-in-components-0.0.4.tgz", + "integrity": "sha512-AESphDCMXmE2WXxZRoIf5mgsSNO5WyYuMO65Fk0YnLEtusd9RhtIAOUUcdSWZKZ6p8Nch1y9Tt8HCgk5ebvmOw==", + "dev": true + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz", + "integrity": "sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + } + } + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, + "protractor": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "dev": true, + "requires": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "webdriver-manager": { + "version": "12.1.7", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz", + "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==", + "dev": true, + "requires": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + } + } + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "purgecss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz", + "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==", + "dev": true, + "requires": { + "commander": "^8.0.0", + "glob": "^7.1.7", + "postcss": "^8.3.5", + "postcss-selector-parser": "^6.0.6" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + } + } + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resolve-url-loader": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz", + "integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "3.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "2.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.1.tgz", + "integrity": "sha512-Op2vWTpvK7t6/Qnm1TTh7VjEZZkN8RWgf0DHbkKzQBwNf748YhXbozHVefqpPp/Fuyk/PQPAnYsBxAEtlMvpUw==", + "dev": true, + "requires": { + "fsevents": "~2.1.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz", + "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==", + "dev": true, + "requires": { + "chokidar": ">=2.0.0 <4.0.0" + } + }, + "sass-loader": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.5.tgz", + "integrity": "sha512-2LqoNPtKkZq/XbXNQ4C64GFEleSEHKv6NPSI+bMC/l+jpEXGJhiRYkAQToO24MR7NU4JRY2RpLpJ/gjo2Uf13w==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", + "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", + "dev": true, + "requires": { + "debug": "~4.1.0", + "engine.io": "~3.4.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "socket.io-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", + "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + } + } + }, + "socket.io-parser": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", + "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", + "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" + } + }, + "sockjs-client": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "dev": true, + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.1.2.tgz", + "integrity": "sha512-bjf6eSENOYBX4JZDfl9vVLNsGAQ6Uz90fLmOazcmMcyDYOBFsGxPNn83jXezWLY9bJsVAo1ObztxPcV8HAbjVA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "source-map": "^0.6.1", + "whatwg-mimetype": "^2.3.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "speed-measure-webpack-plugin": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.3.tgz", + "integrity": "sha512-2ljD4Ch/rz2zG3HsLsnPfp23osuPBS0qPuz9sGpkNXTN1Ic4M+W9xB8l8rS8ob2cO4b1L+WTJw/0AJwWYVgcxQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", + "dev": true, + "requires": { + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "stylus-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-4.1.1.tgz", + "integrity": "sha512-Vnm7J/nIs/P6swIrdwJW/dflhsCOiFmb1U3PeQ6phRtg1soPLN4uKnnL7AtGIJDe173elbtYIXVzmCyF493CfA==", + "dev": true, + "requires": { + "fast-glob": "^3.2.4", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "sweetalert2": { + "version": "10.16.11", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-10.16.11.tgz", + "integrity": "sha512-Rdfabv2G89Tr8vmUTb1auWCYYesKBEWnkYPSi7XaiCIW0ZXXGK8Nw1wYKPEMLU6O8gMSMJe5m6MRKqMQsAQy9A==" + }, + "symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "dev": true + }, + "tailwindcss": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-2.2.19.tgz", + "integrity": "sha512-6Ui7JSVtXadtTUo2NtkBBacobzWiQYVjYW0ZnKaP9S1ZCKQ0w7KVNz+YSDI/j7O7KCMHbOkz94ZMQhbT9pOqjw==", + "dev": true, + "requires": { + "arg": "^5.0.1", + "bytes": "^3.0.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "color": "^4.0.1", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.7", + "fs-extra": "^10.0.0", + "glob-parent": "^6.0.1", + "html-tags": "^3.1.0", + "is-color-stop": "^1.1.0", + "is-glob": "^4.0.1", + "lodash": "^4.17.21", + "lodash.topath": "^4.5.2", + "modern-normalize": "^1.1.0", + "node-emoji": "^1.11.0", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss-js": "^3.0.3", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.6", + "postcss-value-parser": "^4.1.0", + "pretty-hrtime": "^1.0.3", + "purgecss": "^4.0.3", + "quick-lru": "^5.1.1", + "reduce-css-calc": "^2.1.8", + "resolve": "^1.20.0", + "tmp": "^0.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "requires": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "tapable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.1.1.tgz", + "integrity": "sha512-Wib1S8m2wdpLbmQz0RBEVosIyvb/ykfKXf3ZIDqvWoMg/zTNm6G/tDSuUM61J1kNCDXWJrLHGSFeMhAG+gAGpQ==", + "dev": true + }, + "tar": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", + "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "terser": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.7.tgz", + "integrity": "sha512-lJbKdfxWvjpV330U4PBZStCT9h3N9A4zZVA5Y4k9sCWXknrpdyxi1oMsRKLmQ/YDMDxSBKIh88v0SkdhdqX06w==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + } + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + } + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true + }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "tslint": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.2.tgz", + "integrity": "sha512-UyNrLdK3E0fQG/xWNqAFAC5ugtFyPO4JJR1KyyfQAyzR8W0fTRrC91A8Wej4BntFzcvETdCSDa/4PnNYJQLYiA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.10.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + } + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", + "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universal-analytics": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", + "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "request": "^2.88.2", + "uuid": "^3.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", + "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.20", + "sockjs-client": "1.4.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.2.0.tgz", + "integrity": "sha512-QBglJBg5+lItm3/Lopv8KDDK01+hjdg2azEwi/4vKJ8ZmGPdtJsTpjtNNOW3a4WiqzXdCATtTudOZJngE7RKkA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.0.1.tgz", + "integrity": "sha512-A9oYz7ANQBK5EN19rUXbvNgfdfZf5U2gP0769OXsj9CvYkCR6OHOsd6OKyEy4H38GGxpsQPKIL83NC64QY6Xmw==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-subresource-integrity": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.1.tgz", + "integrity": "sha512-uekbQ93PZ9e7BFB8Hl9cFIVYQyQqiXp2ExKk9Zv+qZfH/zHXHrCFAfw1VW0+NqWbTWrs/HnuDrto3+tiPXh//Q==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "requires": { + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "worker-plugin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz", + "integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, + "zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c2bc238 --- /dev/null +++ b/package.json @@ -0,0 +1,72 @@ +{ + "name": "angular-folder-structure", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "~11.0.0", + "@angular/cdk": "^11.2.7", + "@angular/common": "~11.0.0", + "@angular/compiler": "~11.0.0", + "@angular/core": "~11.0.0", + "@angular/forms": "~11.0.0", + "@angular/material": "^11.2.7", + "@angular/platform-browser": "~11.0.0", + "@angular/platform-browser-dynamic": "~11.0.0", + "@angular/router": "~11.0.0", + "@auth0/angular-jwt": "5.0.2", + "@briebug/jest-schematic": "^2.1.1", + "@ngneat/tailwind": "^6.0.3", + "@ngrx/effects": "^10.0.0", + "@ngrx/router-store": "^10.0.0", + "@ngrx/schematics": "^10.0.0", + "@ngrx/store": "^10.0.0", + "@ngrx/store-devtools": "^10.0.0", + "@tinymce/tinymce-angular": "^4.2.2", + "ngx-material-timepicker": "^5.5.3", + "ngx-multiple-dates": "^13.1.0", + "ngx-progressbar": "^6.1.1", + "oidc-client": "^1.11.5", + "rxjs": "~6.6.3", + "sweetalert2": "^10.16.9", + "tslib": "^2.0.0", + "zone.js": "~0.10.2" + }, + "devDependencies": { + "@angular-builders/custom-webpack": "11.1.1", + "@angular-devkit/build-angular": "~0.1100.1", + "@angular/cli": "~11.0.1", + "@angular/compiler-cli": "~11.0.0", + "@angular/language-service": "~11.0.0", + "@tailwindcss/aspect-ratio": "0.2.0", + "@tailwindcss/forms": "0.3.2", + "@tailwindcss/line-clamp": "0.2.0", + "@tailwindcss/typography": "0.4.0", + "@types/jasmine": "~3.6.0", + "@types/jasminewd2": "~2.0.3", + "@types/node": "^12.11.1", + "autoprefixer": "^10.2.5", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", + "jasmine-spec-reporter": "~5.0.0", + "karma": "~5.1.1", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "postcss": "^8.2.9", + "postcss-ng-tailwind-in-components": "0.0.4", + "protractor": "~7.0.0", + "tailwindcss": "^2.0.4", + "ts-node": "~7.0.0", + "tslint": "~6.1.0", + "typescript": "~4.0.5" + } + } diff --git a/report.20210410.171439.4055.0.001.json b/report.20210410.171439.4055.0.001.json new file mode 100644 index 0000000..9ac5934 --- /dev/null +++ b/report.20210410.171439.4055.0.001.json @@ -0,0 +1,610 @@ + +{ + "header": { + "reportVersion": 2, + "event": "Allocation failed - JavaScript heap out of memory", + "trigger": "FatalError", + "filename": "report.20210410.171439.4055.0.001.json", + "dumpEventTime": "2021-04-10T17:14:39Z", + "dumpEventTimeStamp": "1618049679328", + "processId": 4055, + "threadId": null, + "cwd": "/Users/phet/Documents/angular/ru-manage-testing", + "commandLine": [ + "node", + "/usr/local/bin/ng", + "serve", + "--hmr" + ], + "nodejsVersion": "v12.16.3", + "wordSize": 64, + "arch": "x64", + "platform": "darwin", + "componentVersions": { + "node": "12.16.3", + "v8": "7.8.279.23-node.35", + "uv": "1.34.2", + "zlib": "1.2.11", + "brotli": "1.0.7", + "ares": "1.16.0", + "modules": "72", + "nghttp2": "1.40.0", + "napi": "5", + "llhttp": "2.0.4", + "http_parser": "2.9.3", + "openssl": "1.1.1g", + "cldr": "36.0", + "icu": "65.1", + "tz": "2019c", + "unicode": "12.1" + }, + "release": { + "name": "node", + "lts": "Erbium", + "headersUrl": "https://nodejs.org/download/release/v12.16.3/node-v12.16.3-headers.tar.gz", + "sourceUrl": "https://nodejs.org/download/release/v12.16.3/node-v12.16.3.tar.gz" + }, + "osName": "Darwin", + "osRelease": "19.6.0", + "osVersion": "Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64", + "osMachine": "x86_64", + "cpus": [ + { + "model": "Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz", + "speed": 1600, + "user": 2250440, + "nice": 0, + "sys": 736020, + "idle": 3175690, + "irq": 0 + }, + { + "model": "Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz", + "speed": 1600, + "user": 737160, + "nice": 0, + "sys": 304160, + "idle": 5120310, + "irq": 0 + }, + { + "model": "Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz", + "speed": 1600, + "user": 2222370, + "nice": 0, + "sys": 662170, + "idle": 3277080, + "irq": 0 + }, + { + "model": "Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz", + "speed": 1600, + "user": 683610, + "nice": 0, + "sys": 263420, + "idle": 5214590, + "irq": 0 + } + ], + "networkInterfaces": [ + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "127.0.0.1", + "netmask": "255.0.0.0", + "family": "IPv4" + }, + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "::1", + "netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + "family": "IPv6", + "scopeid": 0 + }, + { + "name": "lo0", + "internal": true, + "mac": "00:00:00:00:00:00", + "address": "fe80::1", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 1 + }, + { + "name": "en3", + "internal": false, + "mac": "ac:de:48:00:11:22", + "address": "fe80::aede:48ff:fe00:1122", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 4 + }, + { + "name": "en0", + "internal": false, + "mac": "38:f9:d3:36:7e:22", + "address": "fe80::14f5:1b7f:bb09:1775", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 6 + }, + { + "name": "en0", + "internal": false, + "mac": "38:f9:d3:36:7e:22", + "address": "192.168.43.131", + "netmask": "255.255.255.0", + "family": "IPv4" + }, + { + "name": "awdl0", + "internal": false, + "mac": "4e:9c:55:57:0a:fa", + "address": "fe80::4c9c:55ff:fe57:afa", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 11 + }, + { + "name": "llw0", + "internal": false, + "mac": "4e:9c:55:57:0a:fa", + "address": "fe80::4c9c:55ff:fe57:afa", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 12 + }, + { + "name": "utun0", + "internal": false, + "mac": "00:00:00:00:00:00", + "address": "fe80::ba73:9d23:3603:769c", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 13 + }, + { + "name": "utun1", + "internal": false, + "mac": "00:00:00:00:00:00", + "address": "fe80::f5dd:88c5:68a8:9f21", + "netmask": "ffff:ffff:ffff:ffff::", + "family": "IPv6", + "scopeid": 14 + } + ], + "host": "Phet" + }, + "javascriptStack": { + "message": "No stack.", + "stack": [ + "Unavailable." + ] + }, + "nativeStack": [ + { + "pc": "0x0000000100164e03", + "symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__1::basic_string, std::__1::allocator > const&, v8::Local) [/usr/local/bin/node]" + }, + { + "pc": "0x000000010008645a", + "symbol": "node::OnFatalError(char const*, char const*) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100187c07", + "symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100187ba7", + "symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100315955", + "symbol": "v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001003171ca", + "symbol": "v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100313bfc", + "symbol": "v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001003119fe", + "symbol": "v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100311f63", + "symbol": "v8::internal::Heap::CollectAllAvailableGarbage(v8::internal::GarbageCollectionReason) [/usr/local/bin/node]" + }, + { + "pc": "0x000000010031d98e", + "symbol": "v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001002e9fed", + "symbol": "v8::internal::Factory::NewFixedArrayWithFiller(v8::internal::RootIndex, int, v8::internal::Object, v8::internal::AllocationType) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100465fe4", + "symbol": "v8::internal::(anonymous namespace)::ElementsAccessorBase >::GrowCapacity(v8::internal::Handle, unsigned int) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100617f74", + "symbol": "v8::internal::Runtime_GrowArrayElements(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]" + }, + { + "pc": "0x000000010097cc39", + "symbol": "Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/bin/node]" + } + ], + "javascriptHeap": { + "totalMemory": 2188132352, + "totalCommittedMemory": 2166641768, + "usedMemory": 2104702952, + "availableMemory": 43201536, + "memoryLimit": 2197815296, + "heapSpaces": { + "read_only_space": { + "memorySize": 262144, + "committedMemory": 33088, + "capacity": 32808, + "used": 32808, + "available": 0 + }, + "new_space": { + "memorySize": 33554432, + "committedMemory": 12589720, + "capacity": 16759296, + "used": 0, + "available": 16759296 + }, + "old_space": { + "memorySize": 1998987264, + "committedMemory": 1998855896, + "capacity": 1953173384, + "used": 1953173384, + "available": 0 + }, + "code_space": { + "memorySize": 3837952, + "committedMemory": 3673184, + "capacity": 3442176, + "used": 3442176, + "available": 0 + }, + "map_space": { + "memorySize": 6819840, + "committedMemory": 6819160, + "capacity": 3669760, + "used": 3669760, + "available": 0 + }, + "large_object_space": { + "memorySize": 144048128, + "committedMemory": 144048128, + "capacity": 143840280, + "used": 143840280, + "available": 0 + }, + "code_large_object_space": { + "memorySize": 622592, + "committedMemory": 622592, + "capacity": 544544, + "used": 544544, + "available": 0 + }, + "new_large_object_space": { + "memorySize": 0, + "committedMemory": 0, + "capacity": 16759296, + "used": 0, + "available": 16759296 + } + } + }, + "resourceUsage": { + "userCpuSeconds": 518.762, + "kernelCpuSeconds": 24.5595, + "cpuConsumptionPercent": 47.4516, + "maxRss": 2293747417088, + "pageFaults": { + "IORequired": 182, + "IONotRequired": 4483845 + }, + "fsActivity": { + "reads": 0, + "writes": 0 + } + }, + "libuv": [ + ], + "workers": [ + ], + "environmentVariables": { + "TERM_PROGRAM": "vscode", + "TERM": "xterm-256color", + "SHELL": "/bin/bash", + "TMPDIR": "/var/folders/qh/0k2vch4538v3skzch3k_dlgc0000gn/T/", + "TERM_PROGRAM_VERSION": "1.55.1", + "ORIGINAL_XDG_CURRENT_DESKTOP": "undefined", + "USER": "phet", + "COMMAND_MODE": "unix2003", + "SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.b4OjLajf0w/Listeners", + "__CF_USER_TEXT_ENCODING": "0x1F5:0x0:0x0", + "PATH": "/Users/phet/Documents/flutter/flutter/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Users/phet/Documents/flutter/flutter/bin", + "LaunchInstanceID": "F7C2A2FF-30F8-4F7F-9022-8959AF9ADAA8", + "PWD": "/Users/phet/Documents/angular/ru-manage-testing", + "LANG": "en_US.UTF-8", + "XPC_FLAGS": "0x0", + "XPC_SERVICE_NAME": "0", + "SHLVL": "2", + "HOME": "/Users/phet", + "VSCODE_GIT_ASKPASS_MAIN": "/Users/phet/Desktop/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass-main.js", + "LOGNAME": "phet", + "VSCODE_GIT_IPC_HANDLE": "/var/folders/qh/0k2vch4538v3skzch3k_dlgc0000gn/T/vscode-git-df91da68cd.sock", + "VSCODE_GIT_ASKPASS_NODE": "/Users/phet/Desktop/Visual Studio Code.app/Contents/Frameworks/Code Helper (Renderer).app/Contents/MacOS/Code Helper (Renderer)", + "GIT_ASKPASS": "/Users/phet/Desktop/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass.sh", + "SECURITYSESSIONID": "186a6", + "COLORTERM": "truecolor", + "_": "/usr/local/bin/ng", + "BROWSERSLIST_IGNORE_OLD_DATA": "1", + "WEBPACK_DEV_SERVER": "true" + }, + "userLimits": { + "core_file_size_blocks": { + "soft": 0, + "hard": "unlimited" + }, + "data_seg_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "file_size_blocks": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_locked_memory_bytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_memory_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "open_files": { + "soft": 10240, + "hard": "unlimited" + }, + "stack_size_bytes": { + "soft": 8388608, + "hard": 67104768 + }, + "cpu_time_seconds": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_user_processes": { + "soft": 1392, + "hard": 2088 + }, + "virtual_memory_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + } + }, + "sharedObjects": [ + "/usr/local/bin/node", + "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", + "/usr/lib/libSystem.B.dylib", + "/usr/lib/libc++.1.dylib", + "/usr/lib/libobjc.A.dylib", + "/usr/lib/libfakelink.dylib", + "/usr/lib/libDiagnosticMessagesClient.dylib", + "/usr/lib/libicucore.A.dylib", + "/usr/lib/libz.1.dylib", + "/usr/lib/libc++abi.dylib", + "/usr/lib/system/libcache.dylib", + "/usr/lib/system/libcommonCrypto.dylib", + "/usr/lib/system/libcompiler_rt.dylib", + "/usr/lib/system/libcopyfile.dylib", + "/usr/lib/system/libcorecrypto.dylib", + "/usr/lib/system/libdispatch.dylib", + "/usr/lib/system/libdyld.dylib", + "/usr/lib/system/libkeymgr.dylib", + "/usr/lib/system/liblaunch.dylib", + "/usr/lib/system/libmacho.dylib", + "/usr/lib/system/libquarantine.dylib", + "/usr/lib/system/libremovefile.dylib", + "/usr/lib/system/libsystem_asl.dylib", + "/usr/lib/system/libsystem_blocks.dylib", + "/usr/lib/system/libsystem_c.dylib", + "/usr/lib/system/libsystem_configuration.dylib", + "/usr/lib/system/libsystem_coreservices.dylib", + "/usr/lib/system/libsystem_darwin.dylib", + "/usr/lib/system/libsystem_dnssd.dylib", + "/usr/lib/system/libsystem_featureflags.dylib", + "/usr/lib/system/libsystem_info.dylib", + "/usr/lib/system/libsystem_m.dylib", + "/usr/lib/system/libsystem_malloc.dylib", + "/usr/lib/system/libsystem_networkextension.dylib", + "/usr/lib/system/libsystem_notify.dylib", + "/usr/lib/system/libsystem_sandbox.dylib", + "/usr/lib/system/libsystem_secinit.dylib", + "/usr/lib/system/libsystem_kernel.dylib", + "/usr/lib/system/libsystem_platform.dylib", + "/usr/lib/system/libsystem_pthread.dylib", + "/usr/lib/system/libsystem_symptoms.dylib", + "/usr/lib/system/libsystem_trace.dylib", + "/usr/lib/system/libunwind.dylib", + "/usr/lib/system/libxpc.dylib", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices", + "/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics", + "/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO", + "/System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis", + "/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", + "/System/Library/PrivateFrameworks/FontServices.framework/libFontParser.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate", + "/System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface", + "/usr/lib/libxml2.2.dylib", + "/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork", + "/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation", + "/System/Library/PrivateFrameworks/WatchdogClient.framework/Versions/A/WatchdogClient", + "/usr/lib/libcompression.dylib", + "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration", + "/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay", + "/System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator", + "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", + "/System/Library/Frameworks/Metal.framework/Versions/A/Metal", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders", + "/System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport", + "/System/Library/Frameworks/Security.framework/Versions/A/Security", + "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", + "/usr/lib/libbsm.0.dylib", + "/usr/lib/liblzma.5.dylib", + "/usr/lib/libauto.dylib", + "/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration", + "/usr/lib/libarchive.2.dylib", + "/usr/lib/liblangid.dylib", + "/usr/lib/libCRFSuite.dylib", + "/usr/lib/libenergytrace.dylib", + "/usr/lib/system/libkxld.dylib", + "/System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression", + "/usr/lib/libcoretls.dylib", + "/usr/lib/libcoretls_cfhelpers.dylib", + "/usr/lib/libpam.2.dylib", + "/usr/lib/libsqlite3.dylib", + "/usr/lib/libxar.1.dylib", + "/usr/lib/libbz2.1.0.dylib", + "/usr/lib/libiconv.2.dylib", + "/usr/lib/libcharset.1.dylib", + "/usr/lib/libnetwork.dylib", + "/usr/lib/libpcap.A.dylib", + "/usr/lib/libapple_nghttp2.dylib", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList", + "/System/Library/Frameworks/NetFS.framework/Versions/A/NetFS", + "/System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth", + "/System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport", + "/System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC", + "/System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP", + "/System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities", + "/usr/lib/libmecabra.dylib", + "/usr/lib/libmecab.dylib", + "/usr/lib/libgermantok.dylib", + "/usr/lib/libThaiTokenizer.dylib", + "/usr/lib/libChineseTokenizer.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib", + "/System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling", + "/System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji", + "/System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData", + "/System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon", + "/usr/lib/libcmph.dylib", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory", + "/System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS", + "/System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation", + "/usr/lib/libutil.dylib", + "/System/Library/PrivateFrameworks/CoreServicesStore.framework/Versions/A/CoreServicesStore", + "/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement", + "/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement", + "/usr/lib/libxslt.1.dylib", + "/System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler", + "/System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment", + "/System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSCore.framework/Versions/A/MPSCore", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSImage.framework/Versions/A/MPSImage", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSNDArray.framework/Versions/A/MPSNDArray", + "/System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools", + "/System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary", + "/System/Library/PrivateFrameworks/CoreAnalytics.framework/Versions/A/CoreAnalytics", + "/System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce", + "/usr/lib/libMobileGestalt.dylib", + "/System/Library/PrivateFrameworks/AppleSystemInfo.framework/Versions/A/AppleSystemInfo", + "/usr/lib/libIOReport.dylib", + "/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage", + "/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL", + "/System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer", + "/System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore", + "/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL", + "/usr/lib/libFosl_dynamic.dylib", + "/System/Library/PrivateFrameworks/OTSVG.framework/Versions/A/OTSVG", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib", + "/usr/lib/libate.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib", + "/usr/lib/libexpat.1.dylib", + "/System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG", + "/System/Library/PrivateFrameworks/FontServices.framework/libhvf.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib", + "/usr/lib/libncurses.5.4.dylib", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATSUI.framework/Versions/A/ATSUI", + "/usr/lib/libcups.2.dylib", + "/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos", + "/System/Library/Frameworks/GSS.framework/Versions/A/GSS", + "/usr/lib/libresolv.9.dylib", + "/System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal", + "/System/Library/Frameworks/Kerberos.framework/Versions/A/Libraries/libHeimdalProxy.dylib", + "/usr/lib/libheimdal-asn1.dylib", + "/System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth", + "/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio", + "/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox", + "/System/Library/PrivateFrameworks/AssertionServices.framework/Versions/A/AssertionServices", + "/System/Library/PrivateFrameworks/AudioToolboxCore.framework/Versions/A/AudioToolboxCore", + "/System/Library/PrivateFrameworks/caulk.framework/Versions/A/caulk", + "/System/Library/PrivateFrameworks/BaseBoard.framework/Versions/A/BaseBoard", + "/System/Library/PrivateFrameworks/RunningBoardServices.framework/Versions/A/RunningBoardServices", + "/System/Library/PrivateFrameworks/PersistentConnection.framework/Versions/A/PersistentConnection", + "/System/Library/PrivateFrameworks/ProtocolBuffer.framework/Versions/A/ProtocolBuffer", + "/System/Library/PrivateFrameworks/CommonUtilities.framework/Versions/A/CommonUtilities", + "/System/Library/PrivateFrameworks/Bom.framework/Versions/A/Bom", + "/usr/lib/libAudioToolboxUtility.dylib", + "/System/Library/PrivateFrameworks/CoreServicesInternal.framework/Versions/A/CoreServicesInternal", + "/Users/phet/Documents/angular/ru-manage-testing/node_modules/webpack-dev-server/node_modules/fsevents/build/Release/fse.node", + "/Users/phet/Documents/angular/ru-manage-testing/node_modules/fsevents/fsevents.node" + ] +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000..b297408 --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,613 @@ +import { NgModule } from "@angular/core"; +import { Routes, RouterModule } from "@angular/router"; +import { MainLayoutComponent } from "./layout/main-layout/main-layout.component"; +import { AuthGuard } from "./core/guards/auth.guard"; +import { settingFinanceRoutes } from "./feature/settings-finance/routes"; +import { examRegisterRoutes } from "./feature/exam-register/routes"; + +const routes: Routes = [ + { + path: "", + pathMatch: "full", + redirectTo: "/setting-exam", + }, + { + path: "auth", + loadChildren: () => + import("./feature/auth-callback/auth-callback.module").then( + (x) => x.AuthCallbackModule + ), + }, + { + path: "", + component: MainLayoutComponent, + canActivate: [AuthGuard], + canActivateChild: [AuthGuard], + children: [ + ...settingFinanceRoutes, + ...examRegisterRoutes, + { + path: "home", + loadChildren: () => + import("./feature/default/default.module").then((m) => m.DefaultModule), + }, + { + path: "change-exam-room", + loadChildren: () => + import("./feature/change-exam-room/change-exam-room.module").then((m) => m.ChangeExamRoomModule), + data: { + menu: 'ย้ายห้องสอบ', + } + }, + { + path: "change-password", + loadChildren: () => + import("./feature/change-password/change-password.module").then((m) => m.ChangePasswodModule), + }, + { + path: "report", + loadChildren: () => + import("./feature/report/report.module").then((m) => m.ReportModule), + data: { + menu: 'รายงาน', + } + }, + { + path: "import-payment", + loadChildren: () => + import("./feature/manage-payment/import/import.module").then( + (m) => m.ImportModule + ), + data: { + menu: 'จัดการรายการชำระเงิน', + sub_menu: 'นำเข้ารายการชำระเงิน' + } + }, + { + path: "confirm-payment", + loadChildren: () => + import("./feature/manage-payment/confirm/confirm.module").then( + (m) => m.ConfirmModule + ), + data: { + menu: 'จัดการรายการชำระเงิน', + sub_menu: 'ยืนยันรายการชำระเงิน' + } + }, + { + path: "manage-exam-officer", + loadChildren: () => + import( + "./feature/exam-setting/manage-exam-officer/manage-exam-officer.module" + ).then((m) => m.ManageExamOfficerModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'กำหนดกรรมการคุมสอบ' + } + }, + { + path: "create-user", + loadChildren: () => + import( + "./feature/set-permission/create-user/create-user.module" + ).then((m) => m.CreateUserModule), + data: { + menu: 'กำหนดสิทธิ์', + sub_menu: 'สร้าง User' + } + }, + { + path: "set-user", + loadChildren: () => + import("./feature/set-permission/set-user/set-user.module").then( + (m) => m.SetUserModule + ), + data: { + menu: 'กำหนดสิทธิ์', + sub_menu: 'User ผู้ใช้งาน' + } + }, + { + path: "set-role", + loadChildren: () => + import("./feature/set-permission/set-role/set-role.module").then( + (m) => m.SetRoleModule + ), + data: { + menu: 'กำหนดสิทธิ์', + sub_menu: 'กลุ่มสิทธิ์' + } + }, + { + path: "change-exam-day", + loadChildren: () => + import("./feature/change-exam-day/change-exam-day.module").then( + (m) => m.ChangeExamDayModule + ), + data: { + menu: 'ขออนุมัติเปลี่ยนวันสอบ' + } + }, + { + path: "testing-field", + loadChildren: () => + import("./feature/settings/testing-field/testing-field.module").then( + (m) => m.TestingFieldModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'จัดการสนามสอบ' + } + }, + { + path: "candidate-list", + loadChildren: () => + import("./feature/candidate-list/candidate-list/candidate-list.module").then( + (m) => m.CandidateListModule + ), + data: { + menu: 'จัดการรายชื่อผู้เข้าสอบ', + sub_menu: 'ข้อมูลผู้สอบ' + } + }, + { + path: "check-candidate-list", + loadChildren: () => + import("./feature/candidate-list/check-candidate-list/check-candidate-list.module").then( + (m) => m.CheckCandidateListModule + ), + data: { + menu: 'จัดการรายชื่อผู้เข้าสอบ', + sub_menu: 'สร้างข้อสอบ' + } + }, + { + path: "approve-examination", + loadChildren: () => + import("./feature/approve-examination/approve-examination.module").then( + (m) => m.ApproveExaminationModule + ), + data: { + menu: 'ปล่อยข้อสอบ' + } + }, + { + path: "change-exam-information", + loadChildren: () => + import( + "./feature/exam-setting/change-exam-information/change-exam-information.module" + ).then((m) => m.ChangeExamInformationModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'ขยายรอบสอบ' + } + }, + { + path: "grade-summary", + loadChildren: () => + import( + "./feature/exam-setting/grade-summary/grade-summary.module" + ).then((m) => m.GradeSummaryModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'กำหนดเกณฑ์คะแนน' + } + }, + { + path: "random-questions", + loadChildren: () => + import( + "./feature/exam-setting/random-questions/random-questions.module" + ).then((m) => m.RandomQuestionsModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'สร้างเงื่อนไขการสุ่มคำถาม' + } + }, + { + path: "academic-semesters", + loadChildren: () => + import( + "./feature/settings/academic-semesters/academic-semesters.module" + ).then((m) => m.AcademicSemestersModule), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ภาคการศึกษา' + } + }, + { + path: "department", + loadChildren: () => + import( + "./feature/settings/department/department.module" + ).then((m) => m.DepartmentModule), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'สร้างภาควิชา' + } + }, + { + path: "academic-years", + loadChildren: () => + import( + "./feature/settings/academic-years/academic-years.module" + ).then((m) => m.AcademicYearsModule), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ปีการศึกษา' + } + }, + { + path: "testing-vdos", + loadChildren: () => + import( + "./feature/settings/testing-vdos/testing-vdos.module" + ).then((m) => m.TestingVdosModule), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'วิดีโอ' + } + }, + { + path: "faculties", + loadChildren: () => + import("./feature/settings/faculties/faculties.module").then( + (m) => m.FacultiesModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ข้อมูลหน่วยงานคณะ' + } + }, + { + path: "subject-type", + loadChildren: () => + import("./feature/settings/typesubject/typesubject.module").then( + (m) => m.TypesubjectModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ประเภทวิชา' + } + }, + { + path: "calendars", + loadChildren: () => + import("./feature/settings/calendars/calendars.module").then( + (m) => m.CalendarsModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'รายการปฎิทิน' + } + }, + { + path: "branch", + loadChildren: () => + import("./feature/settings/testcenter/testcenter.module").then( + (m) => m.TestcenterModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'สร้างศูนย์สอบ' + } + }, + { + path: "online-counter", + loadChildren: () => + import("./feature/settings/online-counter/online-counter.module").then( + (m) => m.OnlineCounterModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ชื่อเค้าเตอร์รับเงินออนไลน์' + } + }, + { + path: "signature", + loadChildren: () => + import("./feature/settings/signature/signature.module").then( + (m) => m.SignatureModule + ), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ลายเซ็นผู้รับเงิน' + } + }, + { + path: "candidate-payment-status", + loadChildren: () => + import("./feature/candidate-payment-status/candidate-payment-status.module").then( + (m) => m.CandidatePaymentStatusModule + ), + data: { + menu: 'จัดการรายชื่อผู้เข้าสอบ', + sub_menu: 'สถานะการชำระค่าสมัคร' + } + }, + { + path: "education-type", + loadChildren: () => + import( + "./feature/settings/education-type/education-type.module" + ).then((m) => m.EducationTypeModule), + data: { + menu: 'ตั้งค่าข้อมูลตั้งต้น', + sub_menu: 'ข้อมูลระดับการศึกษา' + } + }, + { + path: "setting-exam", + loadChildren: () => + import("./feature/setting-exam/setting-exam.module").then( + (m) => m.SettingExamModule + ), + data: { + menu: 'กำหนดรายวิชาสอบ', + } + }, + { + path: "manage-test-center", + loadChildren: () => + import("./feature/manage-test-center/manage-test-center.module").then( + (m) => m.ManageTestCenterModule + ), + data: { + menu: 'การจัดการศูนย์สอบ' + } + }, + { + path: "exam-information", + loadChildren: () => + import( + "./feature/set-exam-information/set-exam-information.module" + ).then((m) => m.SetExamInformationModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'ตรวจสอบข้อมูลรอบสอบ' + } + }, + { + path: "approve-exam", + loadChildren: () => + import( + "./feature/create-exam/approve-exam/approve-exam.module" + ).then((m) => m.ApproveExamModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'เปิดรอบสอบ' + } + }, + { + path: "reject-exam", + loadChildren: () => + import( + "./feature/create-exam/reject-exam/reject-exam.module" + ).then((m) => m.RejectExamModule), + data: { + menu: 'กำหนดข้อมูลการสอบ', + sub_menu: 'ปิดรอบสอบ' + } + }, + { + path: "user-counter", + loadChildren: () => + import( + "./feature/set-permission/user-couter/user-couter.module" + ).then((m) => m.UserCouterModule), + data: { + menu: 'กำหนดสิทธิ์', + sub_menu: 'User Counter รับสมัคร' + } + }, + { + path: "print-exam-card", + loadChildren: () => + import( + "./feature/print-exam-card/print-exam-card.module" + ).then((m) => m.PrintExamCardModule), + data: { + menu: 'พิมพ์บัตรเข้าห้องสอบ' + } + }, + { + path: "setting-print-card", + loadChildren: () => + import( + "./feature/setting-print-card/setting-print-card.module" + ).then((m) => m.SettingPrintCardModule), + data: { + menu: 'ตั้งค่าเวลาพิมพ์บัตร' + } + }, + { + path: "print-exam-result", + loadChildren: () => + import( + "./feature/print-exam-result/print-exam-result.module" + ).then((m) => m.PrintExamResultModule), + data: { + menu: 'พิมพ์ผลสอบ' + } + }, + { + path: "student-info", + loadChildren: () => + import( + "./feature/upload-student/upload-student.module" + ).then((m) => m.UploadStudentModule), + data: { + menu: 'อัพโหลดข้อมูลผู้เข้าสอบ' + } + }, + { + path: "check-student-info", + loadChildren: () => + import( + "./feature/student-info/student-info.module" + ).then((m) => m.StudentInfoModule), + data: { + menu: 'ตรวจสอบข้อมูลผู้สมัคร' + } + }, + { + path: "create-exam-seat", + loadChildren: () => + import( + "./feature/create-exam-seat/create-exam-seat.module" + ).then((m) => m.CreatExamSeatModule), + data: { + menu: 'สร้างเลขที่นั่งสอบ' + } + }, + { + path: "notification-check-exam", + loadChildren: () => + import( + "./feature/notification-check-exam/notification-check-exam.module" + ).then((m) => m.NotificationCheckExamModule), + data: { + menu: 'แจ้งเตือนการตรวจสอบ' + } + }, + { + path: "create-exam-information", + loadChildren: () => + import( + "./feature/create-exam/create-exam-information/create-exam-information.module" + ).then((m) => m.CreateExamInformationModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'ข้อมูลพื้นฐาน' + } + }, + { + path: "create-exam-subject", + loadChildren: () => + import( + "./feature/create-exam/create-exam-subject/create-exam-subject.module" + ).then((m) => m.CreateExamSubjectModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'กำหนดวิชาสอบ' + } + }, + { + path: "create-exam-room", + loadChildren: () => + import( + "./feature/create-exam/create-exam-room/create-exam-room.module" + ).then((m) => m.CreateExamRoomModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'กำหนดห้องสอบ' + } + }, + { + path: "create-exam-condition", + loadChildren: () => + import( + "./feature/create-exam/create-exam-condition/create-exam-condition.module" + ).then((m) => m.CreateExamConditionModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'กำหนดเงื่อนไข' + } + }, + { + path: "create-exam-calendar", + loadChildren: () => + import( + "./feature/create-exam/create-exam-calendar/create-exam-calendar.module" + ).then((m) => m.CreateExamCalendarModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'กำหนดปฏิทิน' + } + }, + { + path: "seat-change", + loadChildren: () => + import( + "./feature/candidate-list/seat-change/seat-change.module" + ).then((m) => m.SeatChangeModule), + data: { + menu: 'จัดการที่นั่งสอบกับห้องสอบ', + sub_menu: 'ย้ายวันสอบ' + } + }, + { + path: 'daily-summary-ttb', + loadChildren: () => + import('./feature/exam-register/daily-summary-ttb/daily-summary-ttb.module').then( + (m) => m.DailySummaryTtbModule + ), + data: { + menu: 'ลงทะเบียนสอบ', + sub_menu: 'รายงานรับเงิน TTB', + }, + }, + { + path: "special-period", + loadChildren: () => + import( + "./feature/create-exam/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.module" + ).then((m) => m.CreateExamSetupPeriodBySubjectModule), + data: { + menu: 'กำหนดข้อมูลรอบสอบ', + sub_menu: 'กำหนดวันสอบของวิชา' + } + }, + { + path: "online-summary", + loadChildren: () => + import( + "./feature/online-summary/online-summary.module" + ).then((m) => m.OnlineSummaryModule), + data: { + menu: 'ลงทะเบียนสอบ', + sub_menu: 'รายงานรับเงินออนไลน์' + } + }, + { + path: 'register-cancel', + loadChildren: () => + import( + "./feature/exam-register/register-cancel/register-cancel.module" + ).then((m) => m.RegisterCancelModule), + data: { + menu: 'ลงทะเบียนสอบ', + sub_menu: 'ยกเลิกรายการสมัคร' + } + }, + { + path: 'extend-information-date', + loadChildren: () => + import( + './feature/extend-information/extend-information-date/extend-information-date.module' + ).then((m) => m.ExtendInformationDateModule), + data: { + menu: 'ขยายรอบสอบ(ที่เปิดแล้ว)', + sub_menu: 'ขยายวันที่สอบ' + } + }, + { + path: 'extend-information-room', + loadChildren: () => + import( + './feature/extend-information/extend-information-room/extend-information-room.module' + ).then((m) => m.ExtendInformationRoomModule), + data: { + menu: 'ขยายรอบสอบ(ที่เปิดแล้ว)', + sub_menu: 'จัดการห้องสอบ' + } + }, + ], + }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes, { relativeLinkResolution: "legacy" })], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..0680b43 --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1 @@ + diff --git a/src/app/app.component.scss b/src/app/app.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000..b4775db --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,35 @@ +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + RouterTestingModule + ], + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'angular-folder-structure'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('angular-folder-structure'); + }); + + it('should render title in a h1 tag', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to angular-folder-structure!'); + }); +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..e62a09e --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = 'angular-folder-structure'; +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..3e95331 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,53 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { CoreModule } from './core/core.module'; +import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store'; +import { appReducers } from './state/app-reducer'; +import { environment } from '../environments/environment.prod'; +import { EffectsModule } from '@ngrx/effects'; +import { StoreDevtoolsModule } from '@ngrx/store-devtools'; +import { StoreRouterConnectingModule } from '@ngrx/router-store'; +import { MainLayoutComponent } from './layout/main-layout/main-layout.component'; +import { MenuComponent } from './layout/menu/menu/menu.component'; +import { ToolbarComponent } from './layout/toolbar/toolbar/toolbar.component'; +import { SharedModule } from './shared/shared.module'; +// for debugging +export function debug(reducer: ActionReducer): ActionReducer { + return function(state, action) { + // console.log('state', state); + return reducer(state, action); + }; +} + +export const metaReducers: MetaReducer[] = [debug]; +@NgModule({ + declarations: [ + AppComponent, + MainLayoutComponent, + MenuComponent, + ToolbarComponent, + ], + imports: [ + BrowserModule, + AppRoutingModule, + CoreModule, + SharedModule, + BrowserAnimationsModule, + StoreModule.forRoot(appReducers, { + metaReducers, + runtimeChecks: { + strictStateImmutability: false, + strictActionImmutability: false, + } + }), + EffectsModule.forRoot([]), + StoreDevtoolsModule.instrument({maxAge: 25, logOnly: environment.production}), + StoreRouterConnectingModule.forRoot(), + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/src/app/core/base/base-form-uid.ts b/src/app/core/base/base-form-uid.ts new file mode 100644 index 0000000..a788df8 --- /dev/null +++ b/src/app/core/base/base-form-uid.ts @@ -0,0 +1,93 @@ +import { environment } from 'src/environments/environment'; +import { Router, ActivatedRoute } from '@angular/router'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { tap } from 'rxjs/operators'; +import { Location } from '@angular/common'; +import { Directive } from '@angular/core'; +@Directive() +export class BaseFormUid { + tinyMCE; + isHideForm: boolean = environment.hideForm + form: FormGroup + state: string + id: number + constructor( + public _router:Router, + public _activeRouter: ActivatedRoute, + public fb: FormBuilder, + public location: Location + ){ + this.form = this.createForm() + this._activeRouter.params.pipe( + tap(x => x.id ? this.state = 'edit' : this.state = 'add'), + tap(x => x.id ? this.id = x.id : this.id = null) + ).subscribe() + this.mce() + } + + + back(){ + // if(this.state == 'add') { + // this._router.navigate(['../'],{relativeTo: this._activeRouter}) + // return + // } + this.location.back() + // this._router.navigate(['../'],{relativeTo: this._activeRouter}) + + } + + createForm(){ + return this.fb.group({}) + } + + + + mce(){ + return this.tinyMCE = { + plugins: [ + 'advlist autolink lists link image charmap print preview hr anchor pagebreak', + 'searchreplace visualblocks visualchars code fullscreen', + 'insertdatetime media nonbreaking save table directionality', + 'emoticons template paste textpattern autoresize', + ], + + document_base_url: 'test', + video_template_callback: function(data) { + return ''; + }, + relative_urls: false, + remove_script_host: true, + forced_root_block: false, + force_br_newlines: true, + force_p_newlines: false, + branding: false, + toolbar: + 'media image code link', + image_advtab: true, + file_picker_callback: function (cb, value, meta) { + var input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/* audio/* video/*'); + input.onchange = function() { + let file = input.files[0]; + let reader = new FileReader(); + const formData: FormData = new FormData(); + formData.append('file', file, file.name) + reader.readAsDataURL(file); + } + input.click(); + } + } + } + +} + +export var sortByProperty = function (property) { + + return function (x, y) { + + return ((x[property] === y[property]) ? 0 : ((x[property] > y[property]) ? 1 : -1)); + + }; + +}; diff --git a/src/app/core/base/base-form.ts b/src/app/core/base/base-form.ts new file mode 100644 index 0000000..cc369ce --- /dev/null +++ b/src/app/core/base/base-form.ts @@ -0,0 +1,95 @@ +import { environment } from 'src/environments/environment'; +import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { filter, startWith, switchMap, tap } from 'rxjs/operators'; +import { Location } from '@angular/common'; +import { Directive } from '@angular/core'; +@Directive() +export class BaseForm { + tinyMCE; + isHideForm: boolean = environment.hideForm + form: FormGroup + state: string + id: any + role; + constructor( + public _router:Router, + public _activeRouter: ActivatedRoute, + public fb: FormBuilder, + public location: Location + ){ + this.form = this.createForm() + this._activeRouter.params.pipe( + tap(x => x.id ? this.state = 'edit' : this.state = 'add'), + tap(x => x.id ? this.id = x.id : this.id = null) + ).subscribe() + this._router.events.pipe( + filter(r => r instanceof NavigationEnd), + tap(x => this.role = this._activeRouter.snapshot.parent.data) + ).subscribe() + this.mce() + } + + + back(){ + // if(this.state == 'add') { + // this._router.navigate(['../'],{relativeTo: this._activeRouter}) + // return + // } + this.location.back() + // this._router.navigate(['../'],{relativeTo: this._activeRouter}) + + } + + createForm(){ + return this.fb.group({}) + } + + mce(){ + return this.tinyMCE = { + plugins: [ + 'advlist autolink lists link image charmap print preview hr anchor pagebreak', + 'searchreplace visualblocks visualchars code fullscreen', + 'insertdatetime media nonbreaking save table directionality', + 'emoticons template paste textpattern autoresize', + ], + + document_base_url: 'test', + video_template_callback: function(data) { + return ''; + }, + relative_urls: false, + remove_script_host: true, + forced_root_block: false, + force_br_newlines: true, + force_p_newlines: false, + branding: false, + toolbar: + 'media image code link', + image_advtab: true, + file_picker_callback: function (cb, value, meta) { + var input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/* audio/* video/*'); + input.onchange = function() { + let file = input.files[0]; + let reader = new FileReader(); + const formData: FormData = new FormData(); + formData.append('file', file, file.name) + reader.readAsDataURL(file); + } + input.click(); + } + } + } +} + +export var sortByProperty = function (property) { + + return function (x, y) { + + return ((x[property] === y[property]) ? 0 : ((x[property] > y[property]) ? 1 : -1)); + + }; + +}; diff --git a/src/app/core/base/base-list-role.ts b/src/app/core/base/base-list-role.ts new file mode 100644 index 0000000..f300966 --- /dev/null +++ b/src/app/core/base/base-list-role.ts @@ -0,0 +1,39 @@ +import { Directive, ViewChild } from '@angular/core'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { ActivatedRoute, NavigationEnd, NavigationStart, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { filter, startWith, switchMap, tap } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +import { AppTokenService } from '../service/security/app-token.service'; +@Directive() +export class BaseListRole { + isProduction = environment.production + @ViewChild(MatSort,{ static: true }) sort: MatSort; + @ViewChild(MatPaginator,{ static: true }) paginator: MatPaginator; + role; + protected updateMatTable(res: any){ + res = new MatTableDataSource(res) + res.paginator = this.paginator + res.sort = this.sort + return res + + } + + constructor( + public router: Router, + public activeRoute: ActivatedRoute, + public apptokenSV: AppTokenService + ){ + this.router.events.pipe( + filter(r => r instanceof NavigationEnd), + startWith(this.router), + // tap(x => console.log(this.activeRoute.firstchild.data)), + switchMap(r => this.activeRoute.data), + // tap(x => console.log(x)), + tap(x => this.role = this.apptokenSV.getPerm(x.role)) + ).subscribe() + } + +} diff --git a/src/app/core/base/base-list.ts b/src/app/core/base/base-list.ts new file mode 100644 index 0000000..2b0381f --- /dev/null +++ b/src/app/core/base/base-list.ts @@ -0,0 +1,98 @@ +// import { Directive, ViewChild } from '@angular/core'; +// import { MatPaginator } from '@angular/material/paginator'; +// import { MatSort } from '@angular/material/sort'; +// import { MatTableDataSource } from '@angular/material/table'; +// import { environment } from 'src/environments/environment'; +// @Directive() +// export class BaseList { +// isProduction = environment.production +// @ViewChild(MatSort,{ static: true }) sort: MatSort; +// @ViewChild(MatPaginator,{ static: true }) paginator: MatPaginator; +// protected updateMatTable(res: any){ +// res = new MatTableDataSource(res) +// res.paginator = this.paginator +// res.sort = this.sort +// return res +// } + +// getIndex(i){ +// return this.paginator.pageIndex * this.paginator.pageSize + i + 1 +// } +// } + +import { Observable } from 'rxjs'; +import { Directive, Output, ViewChild, EventEmitter } from '@angular/core'; +import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { environment } from 'src/environments/environment'; +import { map, startWith } from 'rxjs/operators'; + + + +export interface ResultPageEvent { + results: T[]; + current_page: number; + page_count: number; + page_size: number; + row_count: number; + first_row_on_page: number; + last_row_on_page: number; +} + +export interface CustomeEventPage extends PageEvent { + queryStringPage?: string, + paginator?: MatPaginator +} + +@Directive() +export class BaseList { + protected INT_PAGING:CustomeEventPage = { + length: 0, + pageIndex: 0, + pageSize: 5, + previousPageIndex: null, + queryStringPage: `0/5`, + } + isProduction = environment.production + @ViewChild(MatSort,{ static: true }) sort: MatSort; + @ViewChild(MatPaginator,{ static: true }) paginator: MatPaginator; + @Output() onPaginatorPageChange = new EventEmitter() + + protected updateMatTable(res: any){ + + if(res instanceof Array){ + res = new MatTableDataSource(res) + res.paginator = this.paginator + res.sort = this.sort + return res + } + return res + } + + protected updatePagingMatabe(data: ResultPageEvent){ + this.paginator.length = data.row_count + return data.results + } + + + + protected getEventPage(): Observable { + return this.paginator.page.pipe( + startWith(this.INT_PAGING), + map( event => { + return { + ...event, + paginator: this.paginator, + queryStringPage: `${event.pageIndex + 1}/${event.pageSize}` + } + }) + ) + } + + getIndex(i){ + return this.paginator.pageIndex * this.paginator.pageSize + i + 1 + } + +} + diff --git a/src/app/core/base/base-openid-service.ts b/src/app/core/base/base-openid-service.ts new file mode 100644 index 0000000..19665de --- /dev/null +++ b/src/app/core/base/base-openid-service.ts @@ -0,0 +1,92 @@ +import { HttpClient, HttpEventType } from '@angular/common/http'; + +import { Observable, of } from 'rxjs'; +import { map, catchError } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; + +export interface IapiResponse{ + apiResponse:{ + id:number, + desc:string, + }, + data:Array +} + +export class OpenidService { + + host:string = `${environment.openidPath}` + protected prefix:string = `${this.host}/openid` + protected fullUrl:string = '' + + constructor( + endpoint:string, + protected http: HttpClient + ) { + this.fullUrl = this.prefix + endpoint + } + + // callService(action: string, data?: any[]): Observable> { + // const body = { + // apiRequest: { + // action: action + // } + // , data: data || [] + // }; + // return this.http.post>(this.fullUrl, body) + // } + uploadDocument(target: FormData){ + return this.http.post(this.fullUrl,target,{ + reportProgress: true, + observe:'events' + }).pipe( + map((event) => { + switch(event.type){ + case HttpEventType.UploadProgress: + const progress = Math.round(100 * event.loaded / event.total); + return { status: 'progress', message: `${progress}` }; + case HttpEventType.Response: + return { status: 'success', message: event.body }; + default: + return `Unhandled event: ${event.type}`; + } + } + ), + catchError(err => { + return of({ status: 'error', message: `${err.message}` }) + }) + ) + } + + getAll(): Observable{ + return this.http.get(this.fullUrl) + } + + add(data: T): Observable { + return this.http.post(this.fullUrl,data) + } + + get(id: any): Observable { + return this.http.get(`${this.fullUrl}/${id}`) + } + + update(id: number,data: T): Observable{ + return this.http.put(`${this.fullUrl}/${id}`,data) + } + + update2(data:T): Observable{ + return this.http.put(this.fullUrl,data) + } + + deleteData(id: number): Observable { + return this.http.delete(`${this.fullUrl}/${id}`) + } + + query(query: string): Observable { + return this.http.get(`${this.fullUrl}/${query}`) + } + + search(query: string): Observable { + return this.http.get(`${this.fullUrl}${query}`) + } +} + diff --git a/src/app/core/base/base-service.ts b/src/app/core/base/base-service.ts new file mode 100644 index 0000000..e3a02ab --- /dev/null +++ b/src/app/core/base/base-service.ts @@ -0,0 +1,93 @@ +import {HttpClient, HttpEventType} from '@angular/common/http'; + +import {Observable, of} from 'rxjs'; +import {map, catchError} from 'rxjs/operators'; +import {environment} from 'src/environments/environment'; + +export interface IapiResponse { + apiResponse: { + id: number, + desc: string, + }, + data: Array +} + + +export class BaseService { + // host:string = 'https://ru.71dev.com/etest-admin' + host: string = `${environment.adminApi}` + protected prefix: string = `${this.host}/api` + protected fullUrl: string = '' + + constructor( + endpoint: string, + protected http: HttpClient + ) { + this.fullUrl = this.prefix + endpoint + } + + // callService(action: string, data?: any[]): Observable> { + // const body = { + // apiRequest: { + // action: action + // } + // , data: data || [] + // }; + // return this.http.post>(this.fullUrl, body) + // } + uploadDocument(target: FormData) { + return this.http.post(this.fullUrl, target, { + reportProgress: true, + observe: 'events' + }).pipe( + map((event) => { + switch (event.type) { + case HttpEventType.UploadProgress: + const progress = Math.round(100 * event.loaded / event.total); + return {status: 'progress', message: `${progress}`}; + case HttpEventType.Response: + return {status: 'success', message: event.body}; + default: + return `Unhandled event: ${event.type}`; + } + } + ), + catchError(err => { + return of({status: 'error', message: `${err.message}`}) + }) + ) + } + + getAll(): Observable { + return this.http.get(this.fullUrl) + } + + add(data: T): Observable { + return this.http.post(this.fullUrl, data) + } + + get(id: any): Observable { + return this.http.get(`${this.fullUrl}/${id}`) + } + + update(id: number, data: T): Observable { + return this.http.put(`${this.fullUrl}/${id}`, data) + } + + update2(data: T): Observable { + return this.http.put(this.fullUrl, data) + } + + deleteData(id: number): Observable { + return this.http.delete(`${this.fullUrl}/${id}`) + } + + query(query: string): Observable { + return this.http.get(`${this.fullUrl}/${query}`) + } + + search(query: string): Observable { + return this.http.get(`${this.fullUrl}${query}`) + } +} + diff --git a/src/app/core/base/base-sub-list.ts b/src/app/core/base/base-sub-list.ts new file mode 100644 index 0000000..542acde --- /dev/null +++ b/src/app/core/base/base-sub-list.ts @@ -0,0 +1,36 @@ +import { Router, ActivatedRoute } from '@angular/router'; +import { tap } from 'rxjs/operators'; +import { Directive, ViewChild } from '@angular/core'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +@Directive() +export class BaseSubList { + state: string + id: number + constructor( + public _activeRouter: ActivatedRoute, + ){ + this._activeRouter.params.pipe( + tap(x => x.id ? this.state = 'edit' : this.state = 'add'), + tap(x => x.id ? this.id = x.id : this.id = null) + ).subscribe() + } + + @ViewChild(MatSort,{ static: true }) sort: MatSort; + @ViewChild(MatPaginator,{ static: true }) paginator: MatPaginator; + + protected updateMatTable(res: any){ + if(res instanceof Array){ + res = new MatTableDataSource(res) + res.paginator = this.paginator + res.sort = this.sort + return res + } + return res + } + + getIndex(i){ + return this.paginator.pageIndex * this.paginator.pageSize + i + 1 + } +} diff --git a/src/app/core/base/tinymce.ts b/src/app/core/base/tinymce.ts new file mode 100644 index 0000000..dbcb29a --- /dev/null +++ b/src/app/core/base/tinymce.ts @@ -0,0 +1,49 @@ +export class BaseTiny { + tinyMCE + protected id: number + protected state: string + constructor( + + ) { + this.tinyMCE = { + plugins: [ + 'advlist autolink lists link image charmap print preview hr anchor pagebreak', + 'searchreplace visualblocks visualchars code fullscreen', + 'insertdatetime media nonbreaking save table directionality', + 'emoticons template paste textpattern autoresize', + ], + + document_base_url: 'test', + video_template_callback: function(data) { + return ''; + }, + relative_urls: false, + remove_script_host: true, + forced_root_block: false, + force_br_newlines: true, + force_p_newlines: false, + branding: false, + toolbar: + 'media image code link', + image_advtab: true, + file_picker_callback: function (cb, value, meta) { + var input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/* audio/* video/*'); + input.onchange = function() { + let file = input.files[0]; + let reader = new FileReader(); + const formData: FormData = new FormData(); + formData.append('file', file, file.name); + // uploadSV.uploadDocument(formData).subscribe((x: any) => { + // if (x.status === 'success'){ + // cb(x.message[0].file_name) + // } + // }); + reader.readAsDataURL(file); + } + input.click(); + } + } + } + } diff --git a/src/app/core/configs/config.ts b/src/app/core/configs/config.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts new file mode 100644 index 0000000..9c2e4ba --- /dev/null +++ b/src/app/core/core.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; +import { TokenIntercepterInterceptor } from './intercepter/token-intercepter.interceptor'; +import { AuthGuard } from './guards/auth.guard'; + + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + HttpClientModule, + ], + exports: [ + CommonModule, + HttpClientModule, + ], + providers: [ + AuthGuard, + { provide: HTTP_INTERCEPTORS, useClass: TokenIntercepterInterceptor, multi: true }, + ] +}) +export class CoreModule { } diff --git a/src/app/core/enum/role.ts b/src/app/core/enum/role.ts new file mode 100644 index 0000000..e4ab3d3 --- /dev/null +++ b/src/app/core/enum/role.ts @@ -0,0 +1,76 @@ +export enum OBJECT { + SET_SUB_EXAM = 'SET-SUB-EXAM', + SET_INFO_EXAM = 'SET-INFO-EXAM', + MN_EXAM_BRANCH = 'MN-EXAM-BRANCH', + EXAM_REG = 'EXAM-REG', + CHK_EXM_INFO = 'CHK-EXAMINEE-INFO', + CHK_CAD_LIST = 'CHK-CANDIDATE-LIST', + PERM = 'PERM', + SETTINGS = 'SETTINGS', + PAYMENT = 'PAYMENT', + CH_EX_DAY_PERM = 'CH-EXAM-DAY-PERM', + PRINT_EXAM_CARD = 'PRINT-EX-CARD', + SET_PRINT_CARD = 'SET-PRINT-CARD', + PRINT_EXAM_RESULT = 'PRINT-EXAM-RESULT', + STUDENT_INFO = 'STUDENT-INFO', + CHECK_STUDENT_INFO = 'CHECK-STUDENT-INFO', + MANAGE_PAYMENT = 'MANAGE-PAYMENT', + REPORT = 'REPORT', + CRE_EX_INFO = 'CRE-EX-INFO', + MN_EX_OFF = 'MN-EX-OFF', + CHG_EX_INFO = 'CHG-EX-INFO', + RANDOM_QUESTIONS = 'RANDOM-QUESTIONS', + GRADE_SUMMARY = 'GRADE-SUMMARY', + REGISTER_SUMMARY = 'REGISTER-SUMMARY', + MANAGE_RECEIPT = 'MANAGE-RECEIPT', + PERIOD_SUMMARY = 'PERIOD-SUMMARY', + DAILY_SUMMARY = 'DAILY-SUMMARY', + DAILY_SUMMARY_TTB = 'DAILY_SUMMARY_TTB', + IMPORT_PAYMENT = 'IMPORT-PAYMENT', + CONFIRM_PAYMENT = 'CONFIRM-PAYMENT', + PERM_GROUP = 'PERM-GROUP', + CREATE_USER = 'CREATE-USER', + SET_USER = 'SET-USER', + USER_COUNTER = 'USER-COUNTER', + CALENDAR = 'CALENDAR', + BRANCH = 'BRANCH', + TESTING_FIELD = 'TESTING-FIELD', + FACULTY = 'FACULTY', + EDUCATION_TYPE = 'EDUCATION-TYPE', + ACADEMIC_YEAR = 'ACADEMIC-YEAR', + ACADEMIC_SEMESTER = 'ACADEMIC-SEMESTER', + SUBJECT_TYPE = 'SUBJECT-TYPE', + SET_EX_FINANCE = 'SET-EX-FINANCE', + SET_TEA_FINANCE = 'SET-TEA-FINANCE', + SET_INV_FINANCE = 'SET-INV-FINANCE', + CON_EX = 'CON-EX', + RES_EX = 'RES-EX', + TAB_EX = 'TAB-EX', + CHK_EX = 'CHK-EX', + CREATE_EXAM_SEAT = 'CREATE-EXAM-SEAT', + NOTI_CHECK_EXAM = 'NOTI-CHECK-EXAM', + CHANGE_EXAM_ROOM = 'CHANGE-EXAM-ROOM', + SET_TESTING_INFO_EXAM = 'SET-TESTING-INFO-EXAM', + SET_TESTING_INFO_EXAM_BASIC = 'SET-TESTING-INFO-EXAM-BASIC', + SET_TESTING_INFO_EXAM_CALENDAR = 'SET-TESTING-INFO-EXAM-CALENDAR', + SET_TESTING_INFO_EXAM_SUBJECT = 'SET-TESTING-INFO-EXAM-SUBJECT', + SET_TESTING_INFO_EXAM_ROOM = 'SET-TESTING-INFO-EXAM-ROOM', + SET_TESTING_INFO_EXAM_COND = 'SET-TESTING-INFO-EXAM-COND', + APPROVE_EXAM = 'APPROVE-EXAM', + REJECT_EXAM = 'REJECT-EXAM', + SEAT_CHANGE = 'SEAT-CHANGE', + SPECIAL_PERIOD = 'SPECIAL-PERIOD', + MANAGE_EXAM_ROOM_AND_SEAT = 'MANAGE-EXAM-ROOM-AND-SEAT', + EXTEND_INFORMATION_DATE = 'EXTEND_INFORMATION_DATE', + EXTEND_INFORMATION_ROOM = 'EXTEND_INFORMATION_ROOM', + ONLINE_SUMMARY = 'ONLINE-SUMMARY', + CREATE_EXAM = 'CREATE-EXAM', + CANDIDATE_PAYMENT_STATUS = 'CANDIDATE-PAYMENT-STATUS', + RECIPIENT_SIGNATURE = 'RECIPIENT-SIGNATURE', + ONLINE_COUNTER = 'ONLINE-COUNTER', + REGISTER_CANCEL = 'REGISTER_CANCEL', + CANCEL_TIME = 'CANCEL_TIME', + UPLOAD_VIDEO = 'UPLOAD_VIDEO', + DEPARTMENT = 'DEPARTMENT', + MANAGE_CANDIDATE_LIST = 'MANAGE-CANDIDATE-LIST' +} diff --git a/src/app/core/guards/auth.guard.spec.ts b/src/app/core/guards/auth.guard.spec.ts new file mode 100644 index 0000000..68889d2 --- /dev/null +++ b/src/app/core/guards/auth.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuthGuard } from './auth.guard'; + +describe('AuthGuard', () => { + let guard: AuthGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(AuthGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/core/guards/auth.guard.ts b/src/app/core/guards/auth.guard.ts new file mode 100644 index 0000000..4d30485 --- /dev/null +++ b/src/app/core/guards/auth.guard.ts @@ -0,0 +1,29 @@ +import { Injectable } from "@angular/core"; +import { CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from "@angular/router"; +import { Observable } from "rxjs"; +import { OidcAuthService } from "../service/oidc/oidc.service"; +@Injectable() +export class AuthGuard implements CanActivate,CanActivateChild { + + constructor( + private odicSV: OidcAuthService + ){ + + } + canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable | Promise { + return this.canActivate(childRoute,state) + } + + canActivate( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable | Promise | boolean | UrlTree { + if (this.odicSV.isLoggedIn()) { + return true + } + + this.odicSV.startAuthentication() + return false; + } + +} diff --git a/src/app/core/intercepter/token-intercepter.interceptor.spec.ts b/src/app/core/intercepter/token-intercepter.interceptor.spec.ts new file mode 100644 index 0000000..7816b44 --- /dev/null +++ b/src/app/core/intercepter/token-intercepter.interceptor.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { TokenIntercepterInterceptor } from './token-intercepter.interceptor'; + +describe('TokenIntercepterInterceptor', () => { + beforeEach(() => TestBed.configureTestingModule({ + providers: [ + TokenIntercepterInterceptor + ] + })); + + it('should be created', () => { + const interceptor: TokenIntercepterInterceptor = TestBed.inject(TokenIntercepterInterceptor); + expect(interceptor).toBeTruthy(); + }); +}); diff --git a/src/app/core/intercepter/token-intercepter.interceptor.ts b/src/app/core/intercepter/token-intercepter.interceptor.ts new file mode 100644 index 0000000..6bee533 --- /dev/null +++ b/src/app/core/intercepter/token-intercepter.interceptor.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor +} from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError, finalize } from 'rxjs/operators'; +import { OidcAuthService } from '../service/oidc/oidc.service'; +import { AppTokenService } from '../service/security/app-token.service'; +import { Router } from '@angular/router'; +import { NgProgress } from 'ngx-progressbar'; +// import { NgProgress } from 'ngx-progressbar'; +// import { AppTokenService } from '../service/security/app-token.service'; + +@Injectable() +export class TokenIntercepterInterceptor implements HttpInterceptor { + + constructor( private odicOpenService: OidcAuthService, + public appTokenService : AppTokenService, + private router: Router, + private progress: NgProgress + ) { + + } + + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + const customReq = request.clone({ + setHeaders:{ + Authorization: request.url.includes('app_tokens') ? this.odicOpenService.getAuthorizationHeaderValue() : `Bearer ${this.appTokenService.getToken()}` + } + }) + + this.progress.ref('home-progress').start() + return next.handle(customReq).pipe( + finalize(() => this.progress.ref('home-progress').complete()) + ); + } +} diff --git a/src/app/core/service/TestingCenter/testing-center.service.spec.ts b/src/app/core/service/TestingCenter/testing-center.service.spec.ts new file mode 100644 index 0000000..8740625 --- /dev/null +++ b/src/app/core/service/TestingCenter/testing-center.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { TestingCenterService } from './testing-center.service'; + +describe('TestingCenterService', () => { + let service: TestingCenterService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(TestingCenterService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/service/TestingCenter/testing-center.service.ts b/src/app/core/service/TestingCenter/testing-center.service.ts new file mode 100644 index 0000000..62d21fb --- /dev/null +++ b/src/app/core/service/TestingCenter/testing-center.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingCenterService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/testing_centers', http); + } + + getByBrandID(BrandID){ + return this.http.get(`${this.fullUrl}?branch_uid=${BrandID}`); + } + + getByFiledID(FieldID){ + return this.http.get(`${this.fullUrl}?testing_field_uid=${FieldID}`); + } + + getAvailableSeat(data){ + return this.http.get(`${this.prefix}/v1/setting/testing_center_chk_seat/${data.testing_center_uid}/${data.from_date}/${data.to_date}`); + } +} diff --git a/src/app/core/service/app.service.spec.ts b/src/app/core/service/app.service.spec.ts new file mode 100644 index 0000000..3a3b746 --- /dev/null +++ b/src/app/core/service/app.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AppService } from './app.service'; + +describe('AppService', () => { + let service: AppService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AppService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/service/app.service.ts b/src/app/core/service/app.service.ts new file mode 100644 index 0000000..4aebd47 --- /dev/null +++ b/src/app/core/service/app.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class AppService { + + constructor() { } +} diff --git a/src/app/core/service/card-print/card-printing-time.service.ts b/src/app/core/service/card-print/card-printing-time.service.ts new file mode 100644 index 0000000..1506f2b --- /dev/null +++ b/src/app/core/service/card-print/card-printing-time.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CardPrintingTimeService extends BaseService { + + constructor( + public http : HttpClient + ) { + super('/v1/information/testing_periods',http) + } + + getTime(id){ + return this.http.get(`${this.prefix}/v1/information/testing_period_list_by_infomation/${id}`); + } + + changeTime(data){ + return this.http.put(`${this.prefix}/v1/information/list_testing_period`,data); + } +} diff --git a/src/app/core/service/card-print/card-printing.service.ts b/src/app/core/service/card-print/card-printing.service.ts new file mode 100644 index 0000000..54e1df1 --- /dev/null +++ b/src/app/core/service/card-print/card-printing.service.ts @@ -0,0 +1,16 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {BaseService} from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CardPrintingService extends BaseService { + studentList: any = []; + + constructor( + public http: HttpClient + ) { + super('/v1/information/card_printing', http) + } +} diff --git a/src/app/core/service/card-print/testing-score.service.ts b/src/app/core/service/card-print/testing-score.service.ts new file mode 100644 index 0000000..d31ac6e --- /dev/null +++ b/src/app/core/service/card-print/testing-score.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingScoreService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_score',http) + } +} diff --git a/src/app/core/service/enrollment-api/candidate-type.service.ts b/src/app/core/service/enrollment-api/candidate-type.service.ts new file mode 100644 index 0000000..103534d --- /dev/null +++ b/src/app/core/service/enrollment-api/candidate-type.service.ts @@ -0,0 +1,17 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {environment} from 'src/environments/environment'; +import {BaseService} from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidateTypeService extends BaseService { + + constructor( + public http: HttpClient + ) { + super(`/${environment.apiVersion}/enrollment/candidate_types`, http) + super.fullUrl = `${environment.enrollmentApi}/api/${environment.apiVersion}/enrollment/candidate_types` + } +} diff --git a/src/app/core/service/enrollment-api/testing-register-enrollment.service.ts b/src/app/core/service/enrollment-api/testing-register-enrollment.service.ts new file mode 100644 index 0000000..1567b0f --- /dev/null +++ b/src/app/core/service/enrollment-api/testing-register-enrollment.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRegisterEnrollmentService extends BaseService { + constructor( + public http: HttpClient + ) { + super(`/${environment.apiVersion}/enrollment/testing_registers`,http); + super.fullUrl = `${environment.enrollmentApi}/api/${environment.apiVersion}/enrollment`; + } + + paid(registerUid){ + return this.http.put(`${this.fullUrl}/cancle/${registerUid}`,null); + } + + cancle(registerUid){ + return this.http.put(`${this.fullUrl}/cancel/${registerUid}`,null); + } + + cancleAdmin(registerUid){ + return this.http.put(`${this.prefix}/v1/register/cancel_testing_receipts/${registerUid}`,null); + } + + deleteAdmin(registerUid){ + return this.http.delete(`${this.prefix}/v1/register/testing_registers/${registerUid}`); + } +} + + diff --git a/src/app/core/service/oidc/oidc.service.ts b/src/app/core/service/oidc/oidc.service.ts new file mode 100644 index 0000000..8fbd9d1 --- /dev/null +++ b/src/app/core/service/oidc/oidc.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from "@angular/core"; +import { User, UserManager, UserManagerSettings } from "oidc-client"; +import { environment } from "src/environments/environment"; + +export function getClientSettings() :UserManagerSettings { + return environment.clientSettings +} +@Injectable({ + providedIn: 'root' +}) +export class OidcAuthService { + + public manager = new UserManager(getClientSettings()) + + public user: User = null + + constructor() { + this.manager.getUser().then(user => { + this.user = user; + }); + } + + isLoggedIn(): boolean { + return this.user != null && !this.user.expired; + } + + getClaims(): any { + return this.user.profile; + } + + getAuthorizationHeaderValue(): string { + return `${this.user.token_type} ${this.user.access_token}`; + } + + startAuthentication(): Promise { + return this.manager.signinRedirect(); + } + + completeAuthentication(): Promise { + return this.manager.signinRedirectCallback().then(user => { + // console.log(user) + this.user = user; + }).catch(err => { + // console.log('error') + }); + } + + logout(){ + this.manager.signoutRedirect( + {id_token_hint: this.user.id_token} + ).then(res => console.log(res)) + } + + +} diff --git a/src/app/core/service/openid/user.service.ts b/src/app/core/service/openid/user.service.ts new file mode 100644 index 0000000..febf23a --- /dev/null +++ b/src/app/core/service/openid/user.service.ts @@ -0,0 +1,30 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { OpenidService } from '../../base/base-openid-service'; + +@Injectable({ + providedIn: 'root' +}) +export class UserOpenidService extends OpenidService { + + constructor( + public http: HttpClient + ) { + super('/user',http) + } + changePassword(uid,data){ + return this.http.put(`${this.prefix}/password/${uid}`,data) + } + + active(uid){ + return this.http.put(`${this.prefix}/user/active/${uid}`,null) + } + + inactive(uid){ + return this.http.put(`${this.prefix}/user/inactive/${uid}`,null) + } + + searchUser(uid){ + return this.http.get(`${this.prefix}/search_user${uid}`) + } +} diff --git a/src/app/core/service/permission/user-counter-login.service.ts b/src/app/core/service/permission/user-counter-login.service.ts new file mode 100644 index 0000000..e74bff7 --- /dev/null +++ b/src/app/core/service/permission/user-counter-login.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class UserCounterLoginService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/permission/counter_login', http); + } + + checkpin(pin){ + return this.http.post(`${this.fullUrl}/${pin}`,null); + } +} diff --git a/src/app/core/service/permission/user-counters.service.ts b/src/app/core/service/permission/user-counters.service.ts new file mode 100644 index 0000000..93e2df5 --- /dev/null +++ b/src/app/core/service/permission/user-counters.service.ts @@ -0,0 +1,27 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class UserCountersService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/permission/counters', http) + } + + getByInfo(id){ + return this.http.get(`${this.fullUrl}_by_information/${id}`) + } + + getCounterSummary(CounterNo, CounterId, Period){ + return this.http.get(`${this.prefix}/v1/permission/counter_summary_by_period/${CounterNo}/${CounterId}/${Period}`) + } + + logout(pin){ + return this.http.put(`${this.prefix}/v1/permission/counter_logout/${pin}`, null); + } +} diff --git a/src/app/core/service/province/provice.service.ts b/src/app/core/service/province/provice.service.ts new file mode 100644 index 0000000..159409a --- /dev/null +++ b/src/app/core/service/province/provice.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ProviceService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/provinces',http) + } +} diff --git a/src/app/core/service/question/question-category.service.ts b/src/app/core/service/question/question-category.service.ts new file mode 100644 index 0000000..49e31b1 --- /dev/null +++ b/src/app/core/service/question/question-category.service.ts @@ -0,0 +1,35 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class QuestionCategoryService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('v1/question/question_category',http) + super.fullUrl = `${environment.storeApi}/api/question/question_category` + } + + getSubject(id){ + return this.http.get(`${this.fullUrl}_detail?subject_uid=${id}`) + } + + getAllSubject(id){ + return this.http.get(`${this.fullUrl}_detail2?subject_uid=${id}`) + } + + getSubjectWithInstructor(id){ + return this.http.get(`${this.fullUrl}_detail3?subject_uid=${id}`) + } + + getCategoryType(subject,category){ + return this.http.get(`${this.fullUrl}_detail2_one_cat?subject_uid=${subject}&question_category_master_uid=${category}`) + } + +} + diff --git a/src/app/core/service/region/region.service.ts b/src/app/core/service/region/region.service.ts new file mode 100644 index 0000000..e52a3a4 --- /dev/null +++ b/src/app/core/service/region/region.service.ts @@ -0,0 +1,14 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +@Injectable({ + providedIn: 'root' +}) +export class RegionService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/regions',http) + } +} diff --git a/src/app/core/service/report/candidate-registered-by-center/candidate-registered-by-center.service.ts b/src/app/core/service/report/candidate-registered-by-center/candidate-registered-by-center.service.ts new file mode 100644 index 0000000..68c4040 --- /dev/null +++ b/src/app/core/service/report/candidate-registered-by-center/candidate-registered-by-center.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidateRegisteredByCenterService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/candidates_registered_by_center', http) + } + + getPdfReport(academic_year_uid, academic_semester_uid, branch_uid, testing_field_uid, testing_center_uid , subject_uid) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${subject_uid}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(academic_year_uid, academic_semester_uid, branch_uid, testing_field_uid, testing_center_uid , subject_uid) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${subject_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/candidate-registered-by-subject/candidate-registered-by-subject.service.ts b/src/app/core/service/report/candidate-registered-by-subject/candidate-registered-by-subject.service.ts new file mode 100644 index 0000000..11128cf --- /dev/null +++ b/src/app/core/service/report/candidate-registered-by-subject/candidate-registered-by-subject.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidateRegisteredBySubjectService extends BaseService{ + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/candidates_registered_by_subject', http) + } + + getPdfReport(subject_uid,academic_year_uid,academic_semester_uid) { + this.requestUrl = `${this.fullUrl}/${subject_uid}/${academic_year_uid}/${academic_semester_uid}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(subject_uid,academic_year_uid,academic_semester_uid) { + this.requestUrl = `${this.fullUrl}/${subject_uid}/${academic_year_uid}/${academic_semester_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/candidate-subject/candidate-subject.service.ts b/src/app/core/service/report/candidate-subject/candidate-subject.service.ts new file mode 100644 index 0000000..516f8b0 --- /dev/null +++ b/src/app/core/service/report/candidate-subject/candidate-subject.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidateSubjectService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/candidate_registered_by_subject', http) + } + + getPdfReport(academic_year_uid, academic_semester_uid, subject_uid) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${subject_uid}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(academic_year_uid, academic_semester_uid, subject_uid) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${subject_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/candidate/candidate.service.ts b/src/app/core/service/report/candidate/candidate.service.ts new file mode 100644 index 0000000..eb0142d --- /dev/null +++ b/src/app/core/service/report/candidate/candidate.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidateService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/application', http) + } + + getPdfReport(informationUid, academicyearUid, academicsemesterUid, fromdate, todate) { + // console.log(this.fullUrl); + this.requestUrl = `${this.fullUrl}/${informationUid}/${academicyearUid}/${academicsemesterUid}/${fromdate}/${todate}/pdf`; + // console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(informationUid, academicyearUid, academicsemesterUid, fromdate, todate) { + this.requestUrl = `${this.fullUrl}/${informationUid}/${academicyearUid}/${academicsemesterUid}/${fromdate}/${todate}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/daily-register/daily-register-payment-total.service.ts b/src/app/core/service/report/daily-register/daily-register-payment-total.service.ts new file mode 100644 index 0000000..0501178 --- /dev/null +++ b/src/app/core/service/report/daily-register/daily-register-payment-total.service.ts @@ -0,0 +1,31 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DailyRegisterPaymentTotalService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/payment/print/total_daily_register_payment', http) + } + + etest102(data) { + return (`${this.fullUrl}/${data.date}/${data.counter_no}/view/${data.period}`) + } + + etest102Online(data) { + return (`${this.fullUrl}_online/${data.date}/view`) + } + + etest102Information(data) { + return (`${this.fullUrl}_testing_information/${data.testing_information_uid}/${data.date}/${data.counter_no}/view/${data.period}`) + } + + etest102InformationOnline(data) { + return (`${this.fullUrl}_online_testing_information/${data.testing_information_uid}/${data.date}/view`) + } +} diff --git a/src/app/core/service/report/daily-register/daily-register-payment.service.ts b/src/app/core/service/report/daily-register/daily-register-payment.service.ts new file mode 100644 index 0000000..3568152 --- /dev/null +++ b/src/app/core/service/report/daily-register/daily-register-payment.service.ts @@ -0,0 +1,31 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DailyRegisterPaymentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/payment/print/daily_register_payment', http) + } + + etest101(data) { + return (`${this.fullUrl}/${data.counter_no}/${data.date}/${data.period}/view`) + } + + etest101Online(data) { + return (`${this.fullUrl}_online/${data.date}/view?is_cash=${data.is_cash}/is_credit_card=${data.is_credit_card}/is_qrcode=${data.is_payin}/is_qrcode=${data.is_payin}`) + } + + etest101Information(data) { + return (`${this.fullUrl}_testing_information/${data.testing_information_uid}/${data.counter_no}/${data.date}/${data.period}/view`) + } + + etest101InformationOnline(data) { + return (`${this.fullUrl}_testing_information_online/${data.testing_information_uid}/${data.date}/view?is_cash=${data.is_cash}/is_credit_card=${data.is_credit_card}/is_qrcode=${data.is_payin}/is_qrcode=${data.is_payin}`) + } +} diff --git a/src/app/core/service/report/eligible_candidate/eligible-candidate.service.ts b/src/app/core/service/report/eligible_candidate/eligible-candidate.service.ts new file mode 100644 index 0000000..2521200 --- /dev/null +++ b/src/app/core/service/report/eligible_candidate/eligible-candidate.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class EligibleCandidateService extends BaseService { + + requestUrl; + + constructor( + public http: HttpClient + ) { + super('/report/eligible_candidate', http) + } + + getReportWithTestInforUid(tsetInUid){ + this.requestUrl = `${this.fullUrl}?testing_information_uid=${tsetInUid}`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/exam-card-print/testing-card.service.ts b/src/app/core/service/report/exam-card-print/testing-card.service.ts new file mode 100644 index 0000000..f8fcb29 --- /dev/null +++ b/src/app/core/service/report/exam-card-print/testing-card.service.ts @@ -0,0 +1,21 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { map } from 'rxjs/operators'; +import { BaseService } from 'src/app/core/base/base-service'; +import { SweetalertService } from '../../sweetalert/sweetalert'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingCardService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/registration/print/testing_card',http) + } + + print(id){ + return (`${this.fullUrl}/${id}/view`) + } +} diff --git a/src/app/core/service/report/exam-result-print/exam-result-print.service.ts b/src/app/core/service/report/exam-result-print/exam-result-print.service.ts new file mode 100644 index 0000000..5839fcb --- /dev/null +++ b/src/app/core/service/report/exam-result-print/exam-result-print.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ExamResultPrintService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/registration/print/testing_grade',http) + } + + print(id){ + return (`${this.fullUrl}/${id}/view`) + } +} diff --git a/src/app/core/service/report/exam-result-subject/exam-result-subject.service.ts b/src/app/core/service/report/exam-result-subject/exam-result-subject.service.ts new file mode 100644 index 0000000..41049c2 --- /dev/null +++ b/src/app/core/service/report/exam-result-subject/exam-result-subject.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; +import {environment} from '../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class ExamResultSubjectService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report//Test/exam_result_subject', http) + super.fullUrl = `${environment.storeApi}/api/report/Test/exam_result_subject` + } + // ${this.fullUrl} + getPdfReport(subject_uid,testing_information_uid,period_id,test_date) { + this.requestUrl = `${this.fullUrl}/${period_id}/${test_date}/${subject_uid}/${testing_information_uid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(subject_uid,testing_information_uid,period_id,test_date){ + this.requestUrl = `${this.fullUrl}/${period_id}/${test_date}/${subject_uid}/${testing_information_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/exam_total/exam-total.service.ts b/src/app/core/service/report/exam_total/exam-total.service.ts new file mode 100644 index 0000000..803e4ac --- /dev/null +++ b/src/app/core/service/report/exam_total/exam-total.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; +import {environment} from '../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class ExamTotalService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/Test/exam_result_subject', http) + super.fullUrl = `${environment.storeApi}/api/report/Test/exam_total` + } + // ${this.fullUrl} + getPdfReport(testing_information_uid) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid){ + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/excel-all-test/excel-all-test.service.ts b/src/app/core/service/report/excel-all-test/excel-all-test.service.ts new file mode 100644 index 0000000..a68990e --- /dev/null +++ b/src/app/core/service/report/excel-all-test/excel-all-test.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../../base/base-service'; +import {HttpClient} from '@angular/common/http'; +import {environment} from '../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class ExcelAllTestService extends BaseService { + requestUrl; + + constructor( + public http: HttpClient + ) { + super('/tests/export/excel_all_test', http) + super.fullUrl = `${environment.storeApi}/api/tests/export/excel_all_test` + } + + + getExcelReport(testing_information_code){ + this.requestUrl = `${this.fullUrl}/${testing_information_code}`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/invigilator-cost/report-invigilator-cost.service.ts b/src/app/core/service/report/invigilator-cost/report-invigilator-cost.service.ts new file mode 100644 index 0000000..6fbf7e3 --- /dev/null +++ b/src/app/core/service/report/invigilator-cost/report-invigilator-cost.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ReportInvigilatorCostService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/invigilator_cost', http) + } + + report(uid){ + return (`${this.fullUrl}_export/${uid}`) + } +} diff --git a/src/app/core/service/report/payment-and-application-by-center/payment-and-application-by-center.service.ts b/src/app/core/service/report/payment-and-application-by-center/payment-and-application-by-center.service.ts new file mode 100644 index 0000000..1bf3f93 --- /dev/null +++ b/src/app/core/service/report/payment-and-application-by-center/payment-and-application-by-center.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class PaymentAndApplicationByCenterService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/payment_and_application_by_center', http) + } + + getPdfReport(academic_year_uid,academic_semester_uid,branch_uid,testing_field_uid,testing_center_uid,subject_uid,from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${subject_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(academic_year_uid,academic_semester_uid,branch_uid,testing_field_uid,testing_center_uid,subject_uid,from_date,to_date) { + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/payment-and-application-by-subject/payment-and-application-by-subject.service.ts b/src/app/core/service/report/payment-and-application-by-subject/payment-and-application-by-subject.service.ts new file mode 100644 index 0000000..9d62c86 --- /dev/null +++ b/src/app/core/service/report/payment-and-application-by-subject/payment-and-application-by-subject.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class PaymentAndApplicationBySubjectService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/payment_and_application_by_subject', http) + } + + getPdfReport(academic_year_uid,academic_semester_uid,subject_uid,from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${subject_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(academic_year_uid,academic_semester_uid,subject_uid,from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${subject_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/period-register/period-register-payment-online.service.ts b/src/app/core/service/report/period-register/period-register-payment-online.service.ts new file mode 100644 index 0000000..8e3546d --- /dev/null +++ b/src/app/core/service/report/period-register/period-register-payment-online.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class PeriodRegisterPaymentOnlineService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/payment/print/period_register_payment_online',http) + } + + etest103Online(data){ + return (`${this.fullUrl}/${data.start_date}/${data.end_date}/view`) + } + + etest103InformationOnline(data) { + return (`${this.fullUrl}_testing_information/${data.testing_information_uid}/${data.start_date}/${data.end_date}/view`) + } +} diff --git a/src/app/core/service/report/period-register/period-register-payment.service.ts b/src/app/core/service/report/period-register/period-register-payment.service.ts new file mode 100644 index 0000000..f57dd52 --- /dev/null +++ b/src/app/core/service/report/period-register/period-register-payment.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class PeriodRegisterPaymentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/report/payment/print/period_register_payment', http) + } + + etest103(data) { + return (`${this.fullUrl}/${data.start_date}/${data.end_date}/view`) + } + + etest103Information(data) { + return (`${this.fullUrl}_testing_information/${data.testing_information_uid}/${data.start_date}/${data.end_date}/view`) + } +} diff --git a/src/app/core/service/report/receipt-by-payment-code/receipt-by-payment-code.service.ts b/src/app/core/service/report/receipt-by-payment-code/receipt-by-payment-code.service.ts new file mode 100644 index 0000000..c3aa75f --- /dev/null +++ b/src/app/core/service/report/receipt-by-payment-code/receipt-by-payment-code.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class ReceiptByPaymentCodeService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/print/receipt_by_payment_code', http) + } + + getPDF(paymentcode){ + return this.http.get(`https://ru.71dev.com/etest-admin/api/report/print/receipt_by_payment_code/256400052/pdf`); + } + + getPdfReport(paymentcode) { + this.requestUrl = `${this.fullUrl}/${paymentcode}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getPdfReportRealUat(registeruid) { + // this.requestUrl = `${this.fullUrl}/${registeruid}/pdf`; + this.requestUrl = `${environment.adminApi}/api/report/print/receipt_form_for_all/${registeruid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getPdfReportReceiptForAll(registeruid) { + // this.requestUrl = `${this.fullUrl}/${registeruid}/pdf`; + this.requestUrl = `${environment.adminApi}/api/report/print/receipt_for_all/${registeruid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getPdfReportCopy(paymentcode) { + this.requestUrl = `${environment.adminApi}/api/report/print/receipt_copy_by_payment_code/${paymentcode}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getPdfReportCopyRealUat(registeruid) { + this.requestUrl = `${environment.adminApi}/api/report/print/receipt_copy_for_all/${registeruid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + // return this.http.get(`${environment.adminApi}/api/v1/register/testing_receipts_paymant/${paymentcode}`); + +} diff --git a/src/app/core/service/report/receiptAll/receipt-all.service.ts b/src/app/core/service/report/receiptAll/receipt-all.service.ts new file mode 100644 index 0000000..9e4d7a7 --- /dev/null +++ b/src/app/core/service/report/receiptAll/receipt-all.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class ReceiptAllService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/print/receipt_form_for_all', http) + } + + getPdfReport(registeruid) { + this.requestUrl = `${this.fullUrl}/${registeruid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } +} diff --git a/src/app/core/service/report/reciept/reciept.service.ts b/src/app/core/service/report/reciept/reciept.service.ts new file mode 100644 index 0000000..eeb6d5f --- /dev/null +++ b/src/app/core/service/report/reciept/reciept.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class RecieptService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/print/receipt', http) + } + + getPdfReport(registeruid) { + this.requestUrl = `${this.fullUrl}/${registeruid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } +} diff --git a/src/app/core/service/report/register-by-payment/register-by-payment.service.ts b/src/app/core/service/report/register-by-payment/register-by-payment.service.ts new file mode 100644 index 0000000..fac8712 --- /dev/null +++ b/src/app/core/service/report/register-by-payment/register-by-payment.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class RegisterByPaymentService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/register_by_payment', http) + } + + getPdfReport(testing_information_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/separated-by-exam-center/separated-by-exam-center.service.ts b/src/app/core/service/report/separated-by-exam-center/separated-by-exam-center.service.ts new file mode 100644 index 0000000..bb001d0 --- /dev/null +++ b/src/app/core/service/report/separated-by-exam-center/separated-by-exam-center.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; +import {environment} from '../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class SeparatedByExamCenterService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report//Test/separated_by_exam_center', http) + super.fullUrl = `${environment.storeApi}/api/report/Test/separated_by_exam_center` + } + + getPdfReport(testing_information_uid, subject_uid, branch_uid,start_date,end_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${subject_uid}/${branch_uid}/${start_date}/${end_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid, subject_uid, branch_uid,start_date,end_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${subject_uid}/${branch_uid}/${start_date}/${end_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/setting-testing-center/setting-testing-center.service.ts b/src/app/core/service/report/setting-testing-center/setting-testing-center.service.ts new file mode 100644 index 0000000..e0d4289 --- /dev/null +++ b/src/app/core/service/report/setting-testing-center/setting-testing-center.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SettingTestingCenterService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/setting_testing_center', http) + } + + getPdfReport(testing_information_uid,academic_year_uid,academic_semester_uid,from_date,to_date) { + this.requestUrl = + `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid,academic_year_uid,academic_semester_uid,from_date,to_date) { + this.requestUrl = + `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/setting-testing-room/setting-testing-room.service.ts b/src/app/core/service/report/setting-testing-room/setting-testing-room.service.ts new file mode 100644 index 0000000..cb05e8f --- /dev/null +++ b/src/app/core/service/report/setting-testing-room/setting-testing-room.service.ts @@ -0,0 +1,66 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import { environment } from 'src/environments/environment'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SettingTestingRoomService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/setting_testing_room', http) + } + + getPdfReport(testing_information_uid,academic_year_uid,academic_semester_uid,branch_uid,testing_field_uid,testing_center_uid,from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid,academic_year_uid,academic_semester_uid,branch_uid,testing_field_uid,testing_center_uid,from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } + + getPdfReport16(subject_uid,testing_information_uid) { + this.requestUrl = `${environment.storeApi}/api/report/Test/exam_result_subject/${subject_uid}/${testing_information_uid}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport16(subject_uid,testing_information_uid) { + this.requestUrl = `${environment.storeApi}/api/report/Test/exam_result_subject/${subject_uid}/${testing_information_uid}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } + + getPdfReport17(testing_information_uid,academic_year_code,academic_semester_code,branch_uid,testing_center_uid,room_name_th) { + this.requestUrl = `${environment.storeApi}/api/report/Test/summary_candidates_absentees_passers/${testing_center_uid}/${academic_year_code}/${branch_uid}/${testing_information_uid}/${academic_semester_code}/${room_name_th}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport17(testing_information_uid,academic_year_code,academic_semester_code,branch_uid,testing_center_uid,room_name_th) { + this.requestUrl = `${environment.storeApi}/api/report/Test/summary_candidates_absentees_passers/${testing_center_uid}/${academic_year_code}/${branch_uid}/${testing_information_uid}/${academic_semester_code}/${room_name_th}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/signature-examination/signature-examination.service.ts b/src/app/core/service/report/signature-examination/signature-examination.service.ts new file mode 100644 index 0000000..48602d5 --- /dev/null +++ b/src/app/core/service/report/signature-examination/signature-examination.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SignatureExaminationService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/signature_examination', http) + } + + getPdfReport(testing_information_uid,branch_uid,testing_field_uid,testing_center_uid,period_id,test_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${period_id}/${test_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid,branch_uid,testing_field_uid,testing_center_uid,period_id,test_date){ + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${branch_uid}/${testing_field_uid}/${testing_center_uid}/${period_id}/${test_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/summary-candidate/summary-candidate.service.ts b/src/app/core/service/report/summary-candidate/summary-candidate.service.ts new file mode 100644 index 0000000..87d98ae --- /dev/null +++ b/src/app/core/service/report/summary-candidate/summary-candidate.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../../base/base-service'; +import {HttpClient} from '@angular/common/http'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SummaryCandidateService extends BaseService { + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/candidate/print/summary_application', http) + } + + getPdfReport(academic_year_uid, academic_semester_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(academic_year_uid, academic_semester_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/summary-candidates-absentees-passers/summary-candidates-absentees-passers.service.ts b/src/app/core/service/report/summary-candidates-absentees-passers/summary-candidates-absentees-passers.service.ts new file mode 100644 index 0000000..8bbe10a --- /dev/null +++ b/src/app/core/service/report/summary-candidates-absentees-passers/summary-candidates-absentees-passers.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {environment} from '../../../../../environments/environment'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class SummaryCandidatesAbsenteesPassersService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/Test/summary_candidates_absentees_passers', http) + super.fullUrl = `${environment.storeApi}/api/report/Test/summary_candidates_absentees_passers` + } + + getPdfReport(testing_information_uid,academic_year_code,academic_semester_code,branch_uid,testing_center_uid,room_name_th) { + this.requestUrl = `${this.fullUrl}/${testing_center_uid}/${academic_year_code}/${branch_uid}/${testing_information_uid}/${academic_semester_code}/${room_name_th}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } +} diff --git a/src/app/core/service/report/testing-center-information/testing-center-information.service.ts b/src/app/core/service/report/testing-center-information/testing-center-information.service.ts new file mode 100644 index 0000000..9a1766a --- /dev/null +++ b/src/app/core/service/report/testing-center-information/testing-center-information.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingCenterInformationService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/testing_center_information', http) + } + + getPdfReport(testing_information_uid, subject_uid, academic_year_uid,academic_semester_uid,from_date, to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${subject_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid, subject_uid, academic_year_uid,academic_semester_uid,from_date, to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${subject_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } + +} diff --git a/src/app/core/service/report/testing-registration/testing-registration.service.ts b/src/app/core/service/report/testing-registration/testing-registration.service.ts new file mode 100644 index 0000000..3a1ea88 --- /dev/null +++ b/src/app/core/service/report/testing-registration/testing-registration.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {BaseService} from "../../../base/base-service"; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRegistrationService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/testing_registration', http) + } + + getPdfReport(testing_information_uid,academic_year_uid, academic_semester_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid,academic_year_uid, academic_semester_uid, from_date,to_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${academic_year_uid}/${academic_semester_uid}/${from_date}/${to_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } + +} diff --git a/src/app/core/service/report/testing-room/testing-room.service.ts b/src/app/core/service/report/testing-room/testing-room.service.ts new file mode 100644 index 0000000..91783b9 --- /dev/null +++ b/src/app/core/service/report/testing-room/testing-room.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import {map} from 'rxjs/operators'; +import {BaseService} from '../../../base/base-service'; +import {HttpClient} from '@angular/common/http'; +import {environment} from '../../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRoomService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/testing_room', http) + } + + getPdfReport(testing_information_uid) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid){ + this.requestUrl = `${this.fullUrl}/${testing_information_uid}`; + window.open(this.requestUrl); + return this.requestUrl; + } + +} diff --git a/src/app/core/service/report/testing-seat-and-room/testing-seat-and-room.service.ts b/src/app/core/service/report/testing-seat-and-room/testing-seat-and-room.service.ts new file mode 100644 index 0000000..bae4b6e --- /dev/null +++ b/src/app/core/service/report/testing-seat-and-room/testing-seat-and-room.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from '@angular/common/http'; +import {BaseService} from '../../../base/base-service'; +import {map} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingSeatAndRoomService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/registration/print/testing_seat_room', http) + } + + getPdfReport(testing_information_uid,branch_uid,period_id, test_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${branch_uid}/${period_id}/${test_date}/pdf`; + console.log(this.requestUrl); + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid,branch_uid,period_id, test_date) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/${branch_uid}/${period_id}/${test_date}/xls`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/report/testing-subject/tesing-subject.service.ts b/src/app/core/service/report/testing-subject/tesing-subject.service.ts new file mode 100644 index 0000000..5d8596c --- /dev/null +++ b/src/app/core/service/report/testing-subject/tesing-subject.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {map} from 'rxjs/operators'; +import {BaseService} from '../../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class TesingSubjectService extends BaseService { + + requestUrl; + constructor( + public http: HttpClient + ) { + super('/report/testing_subject', http) + } + + getPdfReport(testing_information_uid) { + this.requestUrl = `${this.fullUrl}/${testing_information_uid}/pdf`; + return this.http.get(this.requestUrl, { responseType: 'blob', observe: 'response'}).pipe( + map((res: any) => { + return new Blob([res.body], { type: 'application/pdf' }); + }) + ); + } + + getExcelReport(testing_information_uid){ + this.requestUrl = `${this.fullUrl}/${testing_information_uid}`; + window.open(this.requestUrl); + return this.requestUrl; + } +} diff --git a/src/app/core/service/ru-student/ru-student-registers.service.ts b/src/app/core/service/ru-student/ru-student-registers.service.ts new file mode 100644 index 0000000..80fb2b8 --- /dev/null +++ b/src/app/core/service/ru-student/ru-student-registers.service.ts @@ -0,0 +1,16 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class RuStudentRegistersService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/ru_student_registers',http) + } + +} diff --git a/src/app/core/service/ru-student/ru-student.service.ts b/src/app/core/service/ru-student/ru-student.service.ts new file mode 100644 index 0000000..0b651bf --- /dev/null +++ b/src/app/core/service/ru-student/ru-student.service.ts @@ -0,0 +1,27 @@ +import { HttpClient, HttpEventType } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { of } from 'rxjs'; +import { map } from 'rxjs/internal/operators/map'; +import { catchError } from 'rxjs/operators'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class RuStudentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/ru',http) + } + + uploadStudent(target: FormData){ + return this.http.post(`${this.fullUrl}/student_upload`,target) + } + + registerUpload(code,target: FormData){ + return this.http.post(`${this.fullUrl}/register_upload/${code}`,target) + } + +} diff --git a/src/app/core/service/security/app-object.service.ts b/src/app/core/service/security/app-object.service.ts new file mode 100644 index 0000000..05e30e0 --- /dev/null +++ b/src/app/core/service/security/app-object.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AppObjectService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/security/app_objects',http) + } +} diff --git a/src/app/core/service/security/app-permission.service.ts b/src/app/core/service/security/app-permission.service.ts new file mode 100644 index 0000000..b39dd31 --- /dev/null +++ b/src/app/core/service/security/app-permission.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AppPermissionService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/security/app_permissions',http) + } +} diff --git a/src/app/core/service/security/app-role.service.ts b/src/app/core/service/security/app-role.service.ts new file mode 100644 index 0000000..9148670 --- /dev/null +++ b/src/app/core/service/security/app-role.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AppRoleService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/security/app_roles',http) + } +} diff --git a/src/app/core/service/security/app-token.service.ts b/src/app/core/service/security/app-token.service.ts new file mode 100644 index 0000000..ca2cf2e --- /dev/null +++ b/src/app/core/service/security/app-token.service.ts @@ -0,0 +1,72 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { JwtHelperService } from '@auth0/angular-jwt'; + +import { tap } from 'rxjs/operators'; +import { BaseService } from '../../base/base-service'; + +export interface Right { + obj: string; + perm: string; + filter: string; +} + +export interface UserToken { + login: string; + display: string; + token: string; + rights: Right[]; + user_uid: string; +} + +export interface ExtractUser { + // งานหลักสูตร|ALL: string; + user_uid: string; + login_name: string; + display_name: string; + agency_uid: string; + exp: number; + iss: string; + aud: string; +} + +@Injectable({ + providedIn: 'root' +}) +export class AppTokenService extends BaseService { + + user: UserToken + + constructor(public http : HttpClient) { + super('/security/app_tokens',http); + } + + exchangeToken(){ + return this.http.get(`${this.fullUrl}`,{}).pipe( + // tap(x => console.log(x)), + tap(res => this.user = {...res}) + ) + } + + getDataTokens(){ + return this.http.get(`${this.fullUrl}`) + } + + getToken() { + return this.user?.token + } + + getPerm(role){ + // console.log(role) + // console.log(this.user) + return this.user.rights.find(obj => obj.obj == role)?.perm + } + + decodeToken(): ExtractUser { + const helper = new JwtHelperService(); + const decodedToken = helper.decodeToken(this.user?.token); + // console.log(decodedToken) + return decodedToken + } + +} diff --git a/src/app/core/service/security/app-user.service.ts b/src/app/core/service/security/app-user.service.ts new file mode 100644 index 0000000..0daa751 --- /dev/null +++ b/src/app/core/service/security/app-user.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AppUserService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/security/app_users',http) + } +} diff --git a/src/app/core/service/settingPayment/insturctor-payment-accout.service.ts b/src/app/core/service/settingPayment/insturctor-payment-accout.service.ts new file mode 100644 index 0000000..f952276 --- /dev/null +++ b/src/app/core/service/settingPayment/insturctor-payment-accout.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class InsturctorPaymentAccoutService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/instructor_payment_accounts', http) + } +} diff --git a/src/app/core/service/settingPayment/invigilator-cost.service.ts b/src/app/core/service/settingPayment/invigilator-cost.service.ts new file mode 100644 index 0000000..c2abaae --- /dev/null +++ b/src/app/core/service/settingPayment/invigilator-cost.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class invigilatorCostService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/invigilator_costs', http) + } +} diff --git a/src/app/core/service/settings/academic-semester.service.ts b/src/app/core/service/settings/academic-semester.service.ts new file mode 100644 index 0000000..df2abe1 --- /dev/null +++ b/src/app/core/service/settings/academic-semester.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AcademicSemesterService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/academic_semesters', http) + } +} diff --git a/src/app/core/service/settings/academic-year.service.ts b/src/app/core/service/settings/academic-year.service.ts new file mode 100644 index 0000000..eaee2f3 --- /dev/null +++ b/src/app/core/service/settings/academic-year.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class AcademicYearService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/academic_years', http) + } +} diff --git a/src/app/core/service/settings/branch.service.ts b/src/app/core/service/settings/branch.service.ts new file mode 100644 index 0000000..5fe6046 --- /dev/null +++ b/src/app/core/service/settings/branch.service.ts @@ -0,0 +1,20 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class BranchService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/branchs', http); + } + + getAllStatus1(){ + return this.http.get(`${this.fullUrl}?status_id=1`); + } +} + diff --git a/src/app/core/service/settings/calendar-type.service.ts b/src/app/core/service/settings/calendar-type.service.ts new file mode 100644 index 0000000..a6350ac --- /dev/null +++ b/src/app/core/service/settings/calendar-type.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CalendarTypeService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/calendar_types', http) + } +} diff --git a/src/app/core/service/settings/department.service.ts b/src/app/core/service/settings/department.service.ts new file mode 100644 index 0000000..5596e28 --- /dev/null +++ b/src/app/core/service/settings/department.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DepartmentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/departments', http); + } +} diff --git a/src/app/core/service/settings/education-types.service.ts b/src/app/core/service/settings/education-types.service.ts new file mode 100644 index 0000000..9aeb051 --- /dev/null +++ b/src/app/core/service/settings/education-types.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class EducationTypesService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/education_types', http) + } +} diff --git a/src/app/core/service/settings/facultys.service.ts b/src/app/core/service/settings/facultys.service.ts new file mode 100644 index 0000000..7485fbf --- /dev/null +++ b/src/app/core/service/settings/facultys.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class FacultysService extends BaseService{ + + constructor( + public http: HttpClient + ) { + super('/v1/setting/facultys', http) + } +} diff --git a/src/app/core/service/settings/online-counters.service.ts b/src/app/core/service/settings/online-counters.service.ts new file mode 100644 index 0000000..082121a --- /dev/null +++ b/src/app/core/service/settings/online-counters.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class OnlineCountersService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/online_counters', http) + } +} diff --git a/src/app/core/service/settings/recipient-signature.service.ts b/src/app/core/service/settings/recipient-signature.service.ts new file mode 100644 index 0000000..b69a6cf --- /dev/null +++ b/src/app/core/service/settings/recipient-signature.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class RecipientSignatureService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/recipient_signature', http) + } +} diff --git a/src/app/core/service/settings/subject-types.service.ts b/src/app/core/service/settings/subject-types.service.ts new file mode 100644 index 0000000..8dee7b2 --- /dev/null +++ b/src/app/core/service/settings/subject-types.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class SubjectTypesService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/subject_types', http) + } +} diff --git a/src/app/core/service/settings/subjects.service.ts b/src/app/core/service/settings/subjects.service.ts new file mode 100644 index 0000000..48a5938 --- /dev/null +++ b/src/app/core/service/settings/subjects.service.ts @@ -0,0 +1,27 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class SubjectsService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/subjects', http) + } + + upload(data){ + return this.http.post(`${this.fullUrl}/upload`,data) + } + + getSubjectReady(){ + return this.http.get(`${this.fullUrl}?status_id=1`); + } + + check(uid){ + return this.http.get(`${this.prefix}/v1/setting/check_subjects/${uid}`) + } +} diff --git a/src/app/core/service/settings/testing-field.service.ts b/src/app/core/service/settings/testing-field.service.ts new file mode 100644 index 0000000..c0d4309 --- /dev/null +++ b/src/app/core/service/settings/testing-field.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingFieldService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/setting/testing_fields', http); + } + + getByBrandID(BrandID){ + return this.http.get(`${this.fullUrl}?branch_uid=${BrandID}`); + } + +} diff --git a/src/app/core/service/settings/testing-vdos.service.ts b/src/app/core/service/settings/testing-vdos.service.ts new file mode 100644 index 0000000..bb607e8 --- /dev/null +++ b/src/app/core/service/settings/testing-vdos.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; +@Injectable({ + providedIn: 'root' +}) +export class TestingVdosService extends BaseService{ + + constructor( + public http: HttpClient + ) { + super('/v1/setting/testing_vdos', http); + } +} diff --git a/src/app/core/service/store-api/subject-information.service.ts b/src/app/core/service/store-api/subject-information.service.ts new file mode 100644 index 0000000..22ec736 --- /dev/null +++ b/src/app/core/service/store-api/subject-information.service.ts @@ -0,0 +1,17 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class SubjectInformationService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('v1/question/question_category',http) + super.fullUrl = `${environment.storeApi}/api/question/subject_information` + } +} diff --git a/src/app/core/service/store-api/sync.service.ts b/src/app/core/service/store-api/sync.service.ts new file mode 100644 index 0000000..ef6531a --- /dev/null +++ b/src/app/core/service/store-api/sync.service.ts @@ -0,0 +1,22 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class SyncStoreService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('',http) + super.fullUrl = `${environment.storeApi}/api/sync` + } + + deleteTest(uid,subject){ + return this.http.delete(`${this.fullUrl}/delete_test/${uid}?subject_uid=${subject}`) + } + +} diff --git a/src/app/core/service/student-payment/student-payment-confirm.service.ts b/src/app/core/service/student-payment/student-payment-confirm.service.ts new file mode 100644 index 0000000..fb9abf1 --- /dev/null +++ b/src/app/core/service/student-payment/student-payment-confirm.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentPaymentConfirmService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student_payment/student_payment_confirm',http) + } + + getByDate(date){ + return this.http.get(`${this.fullUrl}/${date}`) + } +} diff --git a/src/app/core/service/student-payment/student-payment-not-paid.service.ts b/src/app/core/service/student-payment/student-payment-not-paid.service.ts new file mode 100644 index 0000000..dced16b --- /dev/null +++ b/src/app/core/service/student-payment/student-payment-not-paid.service.ts @@ -0,0 +1,19 @@ +import {HttpClient, HttpHeaders} from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentPaymentNotPaidService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student_payment/student_payment_not_paid',http) + } + + putNotPaids(data){ + return this.http.put(`${this.prefix}/v1/student_payment/cancel_payment_not_paid`,data) + } +} diff --git a/src/app/core/service/student-payment/student-payment.service.ts b/src/app/core/service/student-payment/student-payment.service.ts new file mode 100644 index 0000000..e3698c0 --- /dev/null +++ b/src/app/core/service/student-payment/student-payment.service.ts @@ -0,0 +1,31 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentPaymentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student_payment/bill_receivable_item',http) + } + + getByDate(date){ + return this.http.get(`${this.fullUrl}_by_date/${date}`) + } + + confirmPayment(data){ + return this.http.put(`${this.prefix}/v1/student_payment/confirm_list_payment`,data) + } + + deletePayment(data){ + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + body: data + } + return this.http.delete(`${this.prefix}/v1/student_payment/delete_list_payment`,httpOptions) + } +} diff --git a/src/app/core/service/student-payment/student-upload.service.ts b/src/app/core/service/student-payment/student-upload.service.ts new file mode 100644 index 0000000..ccc21ca --- /dev/null +++ b/src/app/core/service/student-payment/student-upload.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from 'src/app/core/base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentPaymentUploadService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student_payment/upload',http) + } + + confirm(data){ + return this.http.post(`${this.fullUrl}/confirm`,data) + } +} diff --git a/src/app/core/service/student/delete-import-student.service.ts b/src/app/core/service/student/delete-import-student.service.ts new file mode 100644 index 0000000..469b4bd --- /dev/null +++ b/src/app/core/service/student/delete-import-student.service.ts @@ -0,0 +1,31 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DeleteImportStudentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student',http) + } + + deleteImportType2(data){ + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + body: data + } + return this.http.delete(`${this.fullUrl}/delete_import_students`,httpOptions); + } + + deleteImportType1(uid,data){ + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + body: data + } + return this.http.delete(`${this.fullUrl}/delete_ru_import_students/${uid}`,httpOptions); + } +} diff --git a/src/app/core/service/student/generate-group-seat-detail.service.ts b/src/app/core/service/student/generate-group-seat-detail.service.ts new file mode 100644 index 0000000..d48041c --- /dev/null +++ b/src/app/core/service/student/generate-group-seat-detail.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class GenerateGroupSeatDetailService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/generate_group_seat_detail',http) + } + + getDetail(data){ + return this.http.get(`${this.fullUrl}/${data.testing_information_uid}/${data.branch_uid}/${data.testing_field_uid}/${data.testing_center_uid}/${data.testing_date}/${data.section}`); + } +} diff --git a/src/app/core/service/student/generate-group.service.ts b/src/app/core/service/student/generate-group.service.ts new file mode 100644 index 0000000..be2deb1 --- /dev/null +++ b/src/app/core/service/student/generate-group.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class GenerateGroupService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/student_generate_group',http) + } + + getDetail(data){ + return this.http.get(`${this.fullUrl}/${data.testing_information_uid}/${data.branch_uid}/${data.testing_field_uid}/${data.testing_center_uid}/${data.testing_date}/${data.section}`); + } +} diff --git a/src/app/core/service/student/getstudent.service.ts b/src/app/core/service/student/getstudent.service.ts new file mode 100644 index 0000000..406c2c6 --- /dev/null +++ b/src/app/core/service/student/getstudent.service.ts @@ -0,0 +1,14 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +@Injectable({ + providedIn: 'root' +}) +export class GetstudentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/get_student',http) + } +} diff --git a/src/app/core/service/student/reset-seat.service.ts b/src/app/core/service/student/reset-seat.service.ts new file mode 100644 index 0000000..4d3b8eb --- /dev/null +++ b/src/app/core/service/student/reset-seat.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ResetSeatService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/reset_seat',http) + } + + reset(data){ + return this.http.put(`${this.fullUrl}/${data.testing_information_uid}/${data.branch_code}/${data.testing_field_code}/${data.testing_room_code}/${data.testing_date}/${data.section}`,data); + } +} diff --git a/src/app/core/service/student/student-generate-register.service.ts b/src/app/core/service/student/student-generate-register.service.ts new file mode 100644 index 0000000..886688d --- /dev/null +++ b/src/app/core/service/student/student-generate-register.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentGenerateRegisterService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/student_generate_register',http) + } + + register(uid,data){ + return this.http.post(`${this.fullUrl}/${uid}`,data); + } + + registerSeat(uid,isGenerateSeat,data){ + return this.http.post(`${this.fullUrl}/${uid}/${isGenerateSeat}`,data); + } +} diff --git a/src/app/core/service/student/student-generate-seat.service.ts b/src/app/core/service/student/student-generate-seat.service.ts new file mode 100644 index 0000000..a4cc05c --- /dev/null +++ b/src/app/core/service/student/student-generate-seat.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentGenerateSeatService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/student_generate_seat',http) + } + + createSeat(data){ + return this.http.post(`${this.fullUrl}/${data.testing_information_uid}/${data.branch_uid}/${data.testing_field_uid}/${data.testing_center_uid}/${data.testing_date}/${data.section}`,null); + } +} diff --git a/src/app/core/service/student/student-upload.service.ts b/src/app/core/service/student/student-upload.service.ts new file mode 100644 index 0000000..1c53184 --- /dev/null +++ b/src/app/core/service/student/student-upload.service.ts @@ -0,0 +1,48 @@ +import { HttpClient, HttpEventType } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { of } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentUploadService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/upload',http) + } + + // uploadStudent(target: FormData,uid){ + // return this.http.post(`${this.fullUrl}/${uid}`,target,{ + // reportProgress: true, + // observe:'events' + // }).pipe( + // map((event) => { + // switch(event.type){ + // case HttpEventType.UploadProgress: + // const progress = Math.round(100 * event.loaded / event.total); + // return { status: 'progress', message: `${progress}` }; + // case HttpEventType.Response: + // return { status: 'success', message: event.body }; + // default: + // return `Unhandled event: ${event.type}`; + // } + // } + // ), + // catchError(err => { + // return of({ status: 'error', message: `${err.message}` }) + // }) + // ) + // } + + uploadStudent(target: FormData,uid){ + return this.http.post(`${this.fullUrl}/${uid}`,target) + } + + uploadStudentWord(target: FormData,uid){ + return this.http.post(`${this.fullUrl}_word/${uid}`,target) + } +} diff --git a/src/app/core/service/student/student.service.ts b/src/app/core/service/student/student.service.ts new file mode 100644 index 0000000..f88b6aa --- /dev/null +++ b/src/app/core/service/student/student.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class StudentService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student/students',http) + } + + addStudent(data){ + return this.http.post(`${this.prefix}/v1/student/student_for_generate`,data) + } + + checkStudentCode(studentCode, testInforUID){ + return this.http.get(`${this.prefix}/v1/student/check_student/${studentCode}/${testInforUID}`); + } +} diff --git a/src/app/core/service/sweetalert/sweetalert.ts b/src/app/core/service/sweetalert/sweetalert.ts new file mode 100644 index 0000000..ce0f497 --- /dev/null +++ b/src/app/core/service/sweetalert/sweetalert.ts @@ -0,0 +1,274 @@ +import {X} from '@angular/cdk/keycodes'; +import {Injectable} from '@angular/core'; +import {from, Observable, of} from 'rxjs'; +import {map} from 'rxjs/operators'; +import Swal, {SweetAlertResult} from 'sweetalert2'; + +@Injectable({ + providedIn: 'root' +}) +export class SweetalertService { + + constructor() { + } + + saveSuccess(msg: string = 'บันทึกสำเร็จแล้ว') { + Swal.fire({ + icon: 'success', + text: msg, + heightAuto: false + }) + } + + saveSuccessCustom(title: string = 'บันทึกสำเร็จแล้ว', text) { + console.log(text) + Swal.fire({ + icon: 'success', + title: title, + html: `pass: ${text.pass}  ` + `fail: ${text.fail}`, + text: text.toString(), + heightAuto: false + }) + } + + + save(msg: string = 'บันทึกสำเร็จแล้ว', confirmButtonText: string = 'ตกลง'): Observable> { + let dialog = Swal.fire({ + icon: 'success', + title: `${msg}`, + heightAuto: false, + showCancelButton: false, + confirmButtonText: `${confirmButtonText}`, + }) + return from(dialog) + } + + updateSuccess(msg: string = 'อัพเดตสำเร็จแล้ว') { + Swal.fire({ + icon: 'success', + text: msg, + heightAuto: false + }) + } + + removeSuccess(msg: string = 'ลบรายการสำเร็จแล้ว') { + Swal.fire({ + icon: 'success', + text: msg, + heightAuto: false + }) + } + + error(msg: string = 'ผิดพลาด') { + Swal.fire({ + icon: 'error', + text: msg, + heightAuto: false + }) + } + + errorBig(msg: string = 'ผิดพลาด') { + Swal.fire({ + icon: 'error', + title: msg, + heightAuto: false + }) + } + + confirmOpenExam(msg: string = 'ต้องการเปิดรอบสอบนี้ไหม?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + confirm(msg: string = 'ต้องการจะลบข้อมูลนี้ไหม?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + confirmWithSubtext(msg: string = 'ต้องการจะลบข้อมูลนี้ไหม?', text: string = '', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + html: `${text}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + confirmText(text: string, confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${text}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + confirmSubject(msg: string = 'ต้องการเปลี่ยนแปลงวิชาหรือไม่?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + text: 'ทุกครั้งที่มีการเปลี่ยนแปลงวิชากรุณาตรวจสอบ ห้องสอบ อีกครั้ง', + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + recieve(msg: string = 'ต้องการเปลี่ยนสถานะข้อมูลนี้ไหม?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + recieveMoney(msg: string = 'ยืนยันการรับเงินนี้ไหม?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + success(text: string) { + Swal.fire({ + title: text, + icon: 'success', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + } + + recieve2(msg: string = 'ต้องการเปลี่ยนสถานะข้อมูลนี้ไหม?', confirmButtonText: string = 'ตกลง', cancelButtonText: string = 'ยกเลิก'): Observable> { + let dialog = Swal.fire({ + icon: 'warning', + title: `${msg}`, + heightAuto: false, + showCancelButton: true, + confirmButtonText: `${confirmButtonText}`, + cancelButtonText: `${cancelButtonText}`, + }) + return from(dialog) + } + + successThen(text: string): Observable> { + const dialog = Swal.fire({ + title: text, + icon: 'success', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + return from(dialog) + } + + + err() { + Swal.fire({ + title: 'เกิดข้อผิดพลาด', + icon: 'error', + confirmButtonText: 'ตกลง', + }) + } + + errText(text: string) { + Swal.fire({ + title: text, + icon: 'error', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + } + + + errTextAndDetail(title: string, textsub: string) { + Swal.fire({ + title: title, + text: `สาเหตุ : ${textsub}`, + icon: 'error', + confirmButtonText: 'รับทราบ', + heightAuto: false + }) + } + + errTextandSub(text: string, subText: string) { + Swal.fire({ + title: text, + text: subText, + icon: 'error', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + } + + + errOpenExamDetailText(text: string) { + Swal.fire({ + title: 'เปิดการสอบไม่ได้', + text: `สาเหตุ : ${text}`, + icon: 'info', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + } + + errCloseExamDetailText(text: string) { + Swal.fire({ + title: 'ปิดการสอบไม่ได้', + text: `สาเหตุ : ${text}`, + icon: 'info', + confirmButtonText: 'ตกลง', + heightAuto: false + }) + } + + loadingStart(text: string = 'กำลังโหลดข้อมูล ...') { + Swal.fire({ + title: `${text}`, + didOpen() { + Swal.showLoading() + }, + onAfterClose() { + Swal.hideLoading() + }, + allowOutsideClick: false, + allowEscapeKey: false, + }) + } + + close() { + Swal.close() + } + + +} diff --git a/src/app/core/service/sync/sync.service.ts b/src/app/core/service/sync/sync.service.ts new file mode 100644 index 0000000..657b942 --- /dev/null +++ b/src/app/core/service/sync/sync.service.ts @@ -0,0 +1,25 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class SyncService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('',http) + super.fullUrl = `${environment.storeApi}/api/sync` + } + + sync_all(query){ + return this.http.get(`${this.fullUrl}/sync_all${query}`) + } + + deleteTestInforUid(uid){ + return this.http.delete(`${this.fullUrl}/delete_test/${uid}`); + } +} diff --git a/src/app/core/service/testing-information/exam-notification.service.ts b/src/app/core/service/testing-information/exam-notification.service.ts new file mode 100644 index 0000000..77d7a7e --- /dev/null +++ b/src/app/core/service/testing-information/exam-notification.service.ts @@ -0,0 +1,80 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient, HttpHeaders} from '@angular/common/http'; +import {environment} from '../../../../environments/environment'; +import {catchError, concatMap, filter, map, tap} from 'rxjs/operators'; +import {SweetalertService} from '../sweetalert/sweetalert'; +import {throwError} from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class ExamNotificationService extends BaseService { + requestUrl; + constructor( + public http: HttpClient, + private swSV: SweetalertService, + ) { + super('/v1/information/testing_results_count_waitting', http); + } + + getByUid(testUid){ + return this.http.get(`${this.fullUrl}?testing_information_uid=${testUid}`); + } + + getSendUpdateNotiDate(data) { + return this.http.put(`${this.prefix}/v1/information/exam_notification/${data.testing_information_uid}/${data.subject_uid}/${data.testing_datetime}/${data.period_id}`, null); + } + + sendMail(data) { + // return this.http.post(`${environment.storeApi}/api/sentmail/sentmail/${email}/${body}/${topic}`, null); + return this.http.post(`${environment.storeApi}/api/sentmail/sentmail`, data); + } + + getInstructorEmail(subject_uid){ + return this.http.get(`${this.prefix}/information/instructor_email/${subject_uid}`) + } + + sendNotfi() { + return this.http.get(`https://uat.ru.ac.th/etest/sendmail.jsp`); + } + + sendNotfiGet() { + console.log('get') + // const httpHeaders: HttpHeaders = new HttpHeaders({ + // 'Access-Control-Allow-Headers': 'Content-Type', + // 'Access-Control-Allow-Methods': 'POST', + // 'Connection': 'keep-alive', + // 'Content-Type': 'text/html;charset=UTF-8', + // }); + const httpHeaders = new HttpHeaders() + .set('Content-Type', 'text/html;charset=UTF-8') + .set('mode', 'no-cors'); + return this.http.get(`https://uat.ru.ac.th/etest/sendmail.jsp` ,{headers: httpHeaders}); + + + } + + sendNotiTest(){ + this.swSV.confirmText('ยืนยันการอัพเดทการแจ้งเตือน').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return fetch(`https://uat.ru.ac.th/etest/sendmail.jsp`, { + method: 'GET', + headers: { + 'Content-Type': 'text/html;charset=UTF-8', + }, + mode: 'no-cors' + }) + .then(response => response.text()) + .then(response => this.swSV.updateSuccess()) + .then(result => console.log(result)) + .catch(error => console.log('error', error)); + }) + ).subscribe(); + } + + sendNotfiPost() { + return this.http.post(`https://uat.ru.ac.th/etest/sendmail.jsp`, null); + } +} diff --git a/src/app/core/service/testing-information/grading.service.ts b/src/app/core/service/testing-information/grading.service.ts new file mode 100644 index 0000000..ac248ea --- /dev/null +++ b/src/app/core/service/testing-information/grading.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class GradingService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/information/gradings',http) + } +} diff --git a/src/app/core/service/testing-information/random-questions.service.ts b/src/app/core/service/testing-information/random-questions.service.ts new file mode 100644 index 0000000..94f2ff8 --- /dev/null +++ b/src/app/core/service/testing-information/random-questions.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class RandomQuestionsService extends BaseService { + infoid; + constructor( + public http: HttpClient + ) { + super('/v1/information/random_questions',http) + } +} diff --git a/src/app/core/service/testing-information/room-invigilators.service.ts b/src/app/core/service/testing-information/room-invigilators.service.ts new file mode 100644 index 0000000..2c5f8aa --- /dev/null +++ b/src/app/core/service/testing-information/room-invigilators.service.ts @@ -0,0 +1,28 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class RoomInvigilatorsService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/information/room_invigilators', http) + } + + getToday(){ + var todaysDate = new Date(); + return this.http.get(`${this.fullUrl}?start_time=${todaysDate}`); + } + + getByTestInfoID(id){ + return this.http.get(`${this.fullUrl}_by_testing_information/${id}`); + } + + putMany(form){ + return this.http.put(`${this.prefix}/v1/information/list_room_invigilators`,form); + } +} diff --git a/src/app/core/service/testing-information/testing-controls.service.ts b/src/app/core/service/testing-information/testing-controls.service.ts new file mode 100644 index 0000000..148c748 --- /dev/null +++ b/src/app/core/service/testing-information/testing-controls.service.ts @@ -0,0 +1,26 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingControlsService extends BaseService { + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_control_no_room_status_get_paged',http) + } + + getNoRoomStatus(query){ + return this.http.get(`${this.prefix}/v1/information/testing_control_no_room_status${query}`); + } + + getNoRoomPage(query, testUid){ + return this.http.get(`${this.prefix}/v1/information/testing_control_no_room_status_get_paged/${query}?testing_information_uid=${testUid}`); + } + + getPage(query){ + return this.http.get(`${this.prefix}/v1/information/testing_information_for_chk_status_get_paged/${query}`); + } +} diff --git a/src/app/core/service/testing-information/testing-fee.service.ts b/src/app/core/service/testing-information/testing-fee.service.ts new file mode 100644 index 0000000..0d24c39 --- /dev/null +++ b/src/app/core/service/testing-information/testing-fee.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingFeeService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_fees', http) + } +} diff --git a/src/app/core/service/testing-information/testing-information.service.ts b/src/app/core/service/testing-information/testing-information.service.ts new file mode 100644 index 0000000..2209253 --- /dev/null +++ b/src/app/core/service/testing-information/testing-information.service.ts @@ -0,0 +1,124 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +import {environment} from '../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingInformationService extends BaseService { + info; + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_informations', http) + } + getDatatype(){ + return this.http.get(`${environment.enrollmentApi}/api/v1/enrollment/candidate_types`); + } + + getAlltoday(){ + return this.http.get(`${this.fullUrl}_compare_with_today`); + } + + getMaintrue(){ + return this.http.get(`${this.fullUrl}?is_main=true`); + } + + getMaintrueAndTestInforUid(uid){ + return this.http.get(`${this.fullUrl}?is_main=true&testing_information_uid=${uid}`); + } + + getMaintrueANDOpenNull(){ + return this.http.get(`${this.prefix}/v1/information/testing_information_is_open`); + } + + getOpenandMaintrue(){ + return this.http.get(`${this.fullUrl}?is_main=true&is_open=true`); + } + + getCloseandMaintrue(){ + return this.http.get(`${this.fullUrl}?is_main=true&is_open=null`); + } + + getisOpenNullandMaintrue(){ + return this.http.get(`${this.fullUrl}?is_main=true&is_open=null`); + } + + searchisOpenNullFalseandMaintrue(data){ + return this.http.get(`${this.fullUrl}${data}?is_main=true&is_open=null`); + } + + getForCountSeat(){ + return this.http.get(`${this.prefix}/v1/information/testing_information_for_chk_statuss`); + } + + getPage(query){ + return this.http.get(`${this.prefix}/v1/information/testing_information_for_chk_status_get_paged/${query}`); + } + + getSearchForCountSeat(query){ + return this.http.get(`${this.prefix}/v1/information/testing_information_for_chk_statuss/${query}`); + } + + getMaintrueandCounte(){ + return this.http.get(`${this.fullUrl}?is_main=true&is_counter=true`); + } + + getMainfalse(data?){ + return this.http.get(`${this.fullUrl}?is_main=false`); + } + + searchFalse(data){ + return this.http.get(`${this.fullUrl}${data}&is_main=false`); + } + + getCheckmaintrue(mainID){ + return this.http.get(`${this.fullUrl}?main_testing_information_uid=${mainID}`); + } + + querytypeofexaminee(typeofexam){ + return this.http.get(`${this.fullUrl}_compare_with_today?type_of_examinee=${typeofexam}&is_counter=true`); + } + + querytypeofexamineeUid(uid){ + return this.http.get(`${this.fullUrl}_compare_with_today?candidate_type_uid=${uid}&is_counter=true&is_open=true`); + } + + querytypeofexamineeiscouter(typeofexam){ + return this.http.get(`${this.fullUrl}_compare_with_today?type_of_examinee=${typeofexam}`); + } + + approveExam(TestingInforUid , periodId , date){ + return this.http.post(`${this.prefix}/v1/information/release_exam/${TestingInforUid}/${periodId}/${date}`, null); + } + + approveExamAPIstore(TestingInforUid , periodId , date){ + return this.http.post(`${environment.storeApi}/api/tests/release_exam_tests/${periodId}/${TestingInforUid}/${date}`, null); + } + + getAllForSeat(){ + return this.http.get(`${this.prefix}/v1/information/testing_information_for_generate_seat`); + } + + searchForSeat(query: string) { + return this.http.get(`${this.prefix}/v1/information/testing_information_for_generate_seat${query}`) + } + + checkandopentest(TestingInforUid){ + return this.http.post(`${this.prefix}/v1/information/open_testing_information/${TestingInforUid}`, null); + } + + checkBeforeSync(TestingInforUid){ + return this.http.post(`${this.prefix}/v1/information/check_before_sync/${TestingInforUid}`, null); + + } + + checkandclosetest(TestingInforUid){ + return this.http.post(`${this.prefix}/v1/information/close_testing_information/${TestingInforUid}`, null); + } + + getSummarySubject(TestingInforUid, date){ + return this.http.get(`${this.prefix}/v1/information/summary_by_subject/${TestingInforUid}/${date}`); + } +} diff --git a/src/app/core/service/testing-information/testing-period.service.ts b/src/app/core/service/testing-information/testing-period.service.ts new file mode 100644 index 0000000..4ea96e8 --- /dev/null +++ b/src/app/core/service/testing-information/testing-period.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +import {environment} from '../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingPeriodService extends BaseService { + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_periods', http) + } +} diff --git a/src/app/core/service/testing-information/testing-subject-add-date.service.ts b/src/app/core/service/testing-information/testing-subject-add-date.service.ts new file mode 100644 index 0000000..92573bf --- /dev/null +++ b/src/app/core/service/testing-information/testing-subject-add-date.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingSubjectAddDateService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/information/testing_subject_add_dates', http) + } + + FindbyTestSubjectUidandTestInforUid(){ + return this.http.get(`${this.fullUrl}?is_main=true`); + } + + FindLimitPeriod(testInforId, date, subjectCode){ + return this.http.get(`${this.fullUrl}?testing_information_uid=${testInforId}&testing_date=${date}&subject_code=${subjectCode}`); + } +} diff --git a/src/app/core/service/testing-register/candidate-payment-status.service.ts b/src/app/core/service/testing-register/candidate-payment-status.service.ts new file mode 100644 index 0000000..f64d26e --- /dev/null +++ b/src/app/core/service/testing-register/candidate-payment-status.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CandidatePaymentStatusService extends BaseService { + constructor( + public http: HttpClient + ) { + super('/v1/register/candidate_payment_status', http) + } + +} diff --git a/src/app/core/service/testing-register/change-testing-date.service.ts b/src/app/core/service/testing-register/change-testing-date.service.ts new file mode 100644 index 0000000..4ce0cf8 --- /dev/null +++ b/src/app/core/service/testing-register/change-testing-date.service.ts @@ -0,0 +1,25 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +import {environment} from "../../../../environments/environment"; + +@Injectable({ + providedIn: 'root' +}) +export class ChangeTestingDateService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/manage_testings',http) + // super.fullUrl = `${environment.storeApi}/api/question/question_category_detail` + } + + approve(data){ + return this.http.put(`${this.prefix}/v1/register/change_testing_date`,data) + } + + reject(data){ + return this.http.put(`${this.prefix}/v1/register/no_room_available/${data}`,data) + } +} diff --git a/src/app/core/service/testing-register/change-testing-room-and-date.service.ts b/src/app/core/service/testing-register/change-testing-room-and-date.service.ts new file mode 100644 index 0000000..c23bfad --- /dev/null +++ b/src/app/core/service/testing-register/change-testing-room-and-date.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ChangeTestingRoomAndDateService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/change_testing_room_and_date',http) + } + + changeRoomAndDate(data){ + return this.http.put(`${this.fullUrl}`,data) + } +} diff --git a/src/app/core/service/testing-register/change-testing-room.service.ts b/src/app/core/service/testing-register/change-testing-room.service.ts new file mode 100644 index 0000000..f4a62d6 --- /dev/null +++ b/src/app/core/service/testing-register/change-testing-room.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class ChangeTestingRoomService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/change_testing_room', http); + } +} diff --git a/src/app/core/service/testing-register/check-available-room-and-period.service.ts b/src/app/core/service/testing-register/check-available-room-and-period.service.ts new file mode 100644 index 0000000..c11e4fb --- /dev/null +++ b/src/app/core/service/testing-register/check-available-room-and-period.service.ts @@ -0,0 +1,23 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CheckAvailableRoomAndPeriodService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/check_available_room_and_period', http); + } + + checkAvalroom(data){ + return this.http.post(`${this.fullUrl}/${data.testing_information_uid}/${data.subject_uid}/${data.testing_date}`, data) + } + + checkAvalroomWithQuery(data,query,date){ + return this.http.post(`${this.fullUrl}/${data.testing_information_uid}/${data.subject_uid}/${date}/?${query}`, data) + } +} diff --git a/src/app/core/service/testing-register/check-available-room-no-condition.service.ts b/src/app/core/service/testing-register/check-available-room-no-condition.service.ts new file mode 100644 index 0000000..1d32940 --- /dev/null +++ b/src/app/core/service/testing-register/check-available-room-no-condition.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CheckAvailableRoomNoConditionService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/check_available_room_no_condition', http); + } + + checkAvalroom(data){ + return this.http.post(`${this.fullUrl}`,data) + } +} diff --git a/src/app/core/service/testing-register/check-available-room.service.ts b/src/app/core/service/testing-register/check-available-room.service.ts new file mode 100644 index 0000000..c3aa669 --- /dev/null +++ b/src/app/core/service/testing-register/check-available-room.service.ts @@ -0,0 +1,14 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +@Injectable({ + providedIn: 'root' +}) +export class CheckAvailableRoomService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/check_available_room', http); + } +} diff --git a/src/app/core/service/testing-register/check-available-seat.service.ts b/src/app/core/service/testing-register/check-available-seat.service.ts new file mode 100644 index 0000000..d410075 --- /dev/null +++ b/src/app/core/service/testing-register/check-available-seat.service.ts @@ -0,0 +1,21 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class CheckAvailableSeatService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/check_available_seats', http); + } + + + checkAval(data){ + return this.http.post(`${this.fullUrl}_no_condition`,data) + } + +} diff --git a/src/app/core/service/testing-register/check-subject-and-date.service.ts b/src/app/core/service/testing-register/check-subject-and-date.service.ts new file mode 100644 index 0000000..e0d6c69 --- /dev/null +++ b/src/app/core/service/testing-register/check-subject-and-date.service.ts @@ -0,0 +1,15 @@ +import {Injectable} from '@angular/core'; +import {BaseService} from "../../base/base-service"; +import {HttpClient} from "@angular/common/http"; + +@Injectable({ + providedIn: 'root' +}) +export class CheckSubjectAndDateService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/check_subject_and_date', http); + } +} diff --git a/src/app/core/service/testing-register/daily-summary-ttb.service.ts b/src/app/core/service/testing-register/daily-summary-ttb.service.ts new file mode 100644 index 0000000..3d840fd --- /dev/null +++ b/src/app/core/service/testing-register/daily-summary-ttb.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DailySummaryTtbService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/student_payment/ttbcc_report', http) + } + + searchDaily(date){ + return this.http.get(`${this.fullUrl}/${date}`); + } +} diff --git a/src/app/core/service/testing-register/daily-summary.service.ts b/src/app/core/service/testing-register/daily-summary.service.ts new file mode 100644 index 0000000..8c5b00f --- /dev/null +++ b/src/app/core/service/testing-register/daily-summary.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class DailySummaryService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/daily_summaries', http) + } + + searchDaily(date){ + return this.http.get(`${this.fullUrl}/${date}`); + } +} diff --git a/src/app/core/service/testing-register/enrollment-counter-payments.service.ts b/src/app/core/service/testing-register/enrollment-counter-payments.service.ts new file mode 100644 index 0000000..d6674ae --- /dev/null +++ b/src/app/core/service/testing-register/enrollment-counter-payments.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class EnrollmentCounterPaymentsService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/enrollment_counter_payments', http) + } + + postRecieve(userRegisterUid, counterNo, counterPin, counterPeriod){ + return this.http.post(`${this.fullUrl}/${userRegisterUid}/${counterNo}/${counterPin}/${counterPeriod}`,null); + } +} diff --git a/src/app/core/service/testing-register/period-summary.service.ts b/src/app/core/service/testing-register/period-summary.service.ts new file mode 100644 index 0000000..0fe7fc6 --- /dev/null +++ b/src/app/core/service/testing-register/period-summary.service.ts @@ -0,0 +1,21 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class PeriodSummaryService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/period_summaries', http) + } + + searchSummary(data){ + return this.http.get(`${this.fullUrl}/${data.payment_date}/${data.period}/${data.counter_no}`); + } +} + + diff --git a/src/app/core/service/testing-register/shared-usercouter.service.ts b/src/app/core/service/testing-register/shared-usercouter.service.ts new file mode 100644 index 0000000..42e580d --- /dev/null +++ b/src/app/core/service/testing-register/shared-usercouter.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class SharedUsercouterService { + + couterdata: any[]; + constructor() { } + + + get data(): any{ + return this.couterdata; + } + + set data(val: any){ + console.log(val) + this.couterdata = val; + console.log(this.couterdata); + } +} diff --git a/src/app/core/service/testing-register/testing-reciept.service.ts b/src/app/core/service/testing-register/testing-reciept.service.ts new file mode 100644 index 0000000..6efa9c2 --- /dev/null +++ b/src/app/core/service/testing-register/testing-reciept.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; +import {environment} from "../../../../environments/environment"; +import {Observable} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRecieptService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/testing_receipts', http); + + } + + Paid(id){ + console.log(id); + const body = { testing_register_uid: id }; + console.log(body); + // @ts-ignore + return this.http.put(`${environment.storeApi}/api/v1/enrollment/paid/${id}`); + } + + getByPaymentCode(paymentcode): Observable{ + return this.http.get(`${environment.adminApi}/api/v1/register/testing_receipts_paymant${paymentcode}`); + + } + +} diff --git a/src/app/core/service/testing-register/testing-register-is-pay.service.ts b/src/app/core/service/testing-register/testing-register-is-pay.service.ts new file mode 100644 index 0000000..91f0b59 --- /dev/null +++ b/src/app/core/service/testing-register/testing-register-is-pay.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRegisterIsPayService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/testing_register_is_pay', http); + } + + recievedMoney(registeruid){ + return this.http.put(`${this.fullUrl}/${registeruid}`, null); + } +} diff --git a/src/app/core/service/testing-register/testing-register.service.ts b/src/app/core/service/testing-register/testing-register.service.ts new file mode 100644 index 0000000..2252cd4 --- /dev/null +++ b/src/app/core/service/testing-register/testing-register.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class TestingRegisterService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/testing_registers', http); + } + + getAllbyUsercouter(user){ + return this.http.get(`${this.fullUrl}?user_name=${user}`); + } + +} diff --git a/src/app/core/service/testing-register/update-testing-seat.service.ts b/src/app/core/service/testing-register/update-testing-seat.service.ts new file mode 100644 index 0000000..7ee0467 --- /dev/null +++ b/src/app/core/service/testing-register/update-testing-seat.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class UpdateTestingSeatService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/v1/register/update_testing_seat', http); + } + + updateSeat(data){ + return this.http.put(`${this.fullUrl}`, data); + } +} diff --git a/src/app/core/service/testing-register/v-eligible-candidates.service.ts b/src/app/core/service/testing-register/v-eligible-candidates.service.ts new file mode 100644 index 0000000..fc641cd --- /dev/null +++ b/src/app/core/service/testing-register/v-eligible-candidates.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; +import {BaseService} from '../../base/base-service'; +import {HttpClient} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class VEligibleCandidatesService extends BaseService{ + + constructor( + public http: HttpClient + ) { + super('/v1/register/eligible_candidates', http); + } + + candidateCheckStatus(query: string){ + return this.http.get(`${this.fullUrl}_chk_status${query}`); + } + + getPage(query){ + return this.http.get(`${this.fullUrl}_chk_status_get_paged/${query}`) + } + + getAllByTestinUid(tsetInUid){ + return this.http.get(`${this.fullUrl}?testing_information_uid=${tsetInUid}`); + } + +} diff --git a/src/app/core/service/upload/upload.service.ts b/src/app/core/service/upload/upload.service.ts new file mode 100644 index 0000000..0ea470c --- /dev/null +++ b/src/app/core/service/upload/upload.service.ts @@ -0,0 +1,17 @@ +import {HttpClient} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {environment} from 'src/environments/environment'; +import {BaseService} from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class UploadService extends BaseService { + + constructor( + public http: HttpClient + ) { + super('/upload/upload', http) + super.fullUrl = `${environment.uploadApi}/api/upload/upload` + } +} diff --git a/src/app/core/service/user/user.service.ts b/src/app/core/service/user/user.service.ts new file mode 100644 index 0000000..5f9e0c3 --- /dev/null +++ b/src/app/core/service/user/user.service.ts @@ -0,0 +1,17 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { BaseService } from '../../base/base-service'; + +@Injectable({ + providedIn: 'root' +}) +export class UserService extends BaseService { + + constructor( + public http: HttpClient + ) { + super(`/${environment.apiVersion}/enrollment/users`, http); + super.fullUrl = `${environment.enrollmentApi}/api/${environment.apiVersion}/enrollment/users` + } +} diff --git a/src/app/feature/approve-examination/approve-examination.module.ts b/src/app/feature/approve-examination/approve-examination.module.ts new file mode 100644 index 0000000..accb993 --- /dev/null +++ b/src/app/feature/approve-examination/approve-examination.module.ts @@ -0,0 +1,37 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ApproveExaminationRouter } from './router/approve-examination-router'; +import { ApproveExaminationContainer } from './container/approve-examination/approve-examination.container'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ApproveExaminationSearchComponent } from './feature/search/approve-examination-search/approve-examination-search.component'; +import { ApproveExaminationListComponent } from './feature/list/approve-examination-list/approve-examination-list.component'; +import { ApproveDialogComponent } from './feature/dialog/approve-dialog/approve-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: ApproveExaminationRouter, + children: [ + { + path: '', + component: ApproveExaminationContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ApproveExaminationRouter, + ApproveExaminationContainer, + ApproveExaminationSearchComponent, + ApproveExaminationListComponent, + ApproveDialogComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ApproveExaminationModule { } diff --git a/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.html b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.html new file mode 100644 index 0000000..b0be3bb --- /dev/null +++ b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.html @@ -0,0 +1,6 @@ + + + + diff --git a/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.scss b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.scss new file mode 100644 index 0000000..bc8b39e --- /dev/null +++ b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.scss @@ -0,0 +1,15 @@ +.color1{ + background:#fbeafc +} + +.color1{ + background:#fbeafc +} + +.color1{ + background:#fbeafc +} + +.color1{ + background:#fbeafc +} diff --git a/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.spec.ts b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.spec.ts new file mode 100644 index 0000000..2bc8913 --- /dev/null +++ b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExaminationContainer } from './approve-examination.container'; + +describe('ApproveExaminationContainer', () => { + let component: ApproveExaminationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExaminationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExaminationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.ts b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.ts new file mode 100644 index 0000000..9359a6b --- /dev/null +++ b/src/app/feature/approve-examination/container/approve-examination/approve-examination.container.ts @@ -0,0 +1,30 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {Observable} from 'rxjs'; + +@Component({ + selector: 'app-approve-examination', + templateUrl: './approve-examination.container.html', + styleUrls: ['./approve-examination.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExaminationContainer implements OnInit { + subjectList$ = new Observable(); + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrue(); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } +} diff --git a/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.html b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.html new file mode 100644 index 0000000..376112e --- /dev/null +++ b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.html @@ -0,0 +1,28 @@ +

เลือกศูนย์สอบที่ต้องการปล่อยข้อสอบ

+
+
+
+
+
+ + +
+
+ + + + + + + + + +
+
+
+
+
+
+ + +
diff --git a/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.scss b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.scss new file mode 100644 index 0000000..3b017e0 --- /dev/null +++ b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.scss @@ -0,0 +1,9 @@ +.card{ + max-height: 120px; + @apply shadow bg-white rounded-md p-6 ; +} + +.cardChoose{ + max-height: 120px; + @apply shadow bg-white rounded-md p-6 border-2 border-blue-300; +} diff --git a/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.spec.ts b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.spec.ts new file mode 100644 index 0000000..c6df251 --- /dev/null +++ b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveDialogComponent } from './approve-dialog.component'; + +describe('ApproveDialogComponent', () => { + let component: ApproveDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.ts b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.ts new file mode 100644 index 0000000..2ac167c --- /dev/null +++ b/src/app/feature/approve-examination/feature/dialog/approve-dialog/approve-dialog.component.ts @@ -0,0 +1,78 @@ +import {catchError, tap, filter, concatMap} from 'rxjs/operators'; +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import { throwError } from 'rxjs'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-approve-dialog', + templateUrl: './approve-dialog.component.html', + styleUrls: ['./approve-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveDialogComponent implements OnInit { + RoomChoose = ''; + today = new Date(); + dateSelect = null; + Roomdata = []; + Roomsend = { + testing_information_uid: null, + period_id: null, + date: null + }; + constructor( + private testingInforSV: TestingInformationService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { } + + ngOnInit(): void { + this.Roomdata = this.data.data.testing_periods + } + + chooseRoom(testing_center_uid , branchNameTH){ + if (this.RoomChoose !== testing_center_uid){ + this.RoomChoose = testing_center_uid; + }else{ + this.RoomChoose = ''; + } + } + + choosePeriod(testing_center_uid , period_id){ + if (this.RoomChoose !== period_id){ + this.RoomChoose = period_id; + }else{ + this.RoomChoose = ''; + } + } + + confirm(){ + if (this.Roomsend.date === null){ + return this.swSV.error('กรุณากรอกวันที่ต้องการปล่อยสอบ'); + } + const Roomsend = this.Roomdata.filter((x) => { + return x.period_id === this.RoomChoose; + }); + this.Roomsend.period_id = Roomsend[0].period_id; + this.Roomsend.testing_information_uid = Roomsend[0].testing_information_uid; + this.Roomsend.date = formatDate(this.Roomsend.date, 'yyyy-MM-dd', 'en-US'); + this.testingInforSV.approveExam(this.Roomsend.testing_information_uid, this.Roomsend.period_id, this.Roomsend.date).pipe( + tap(x => { + this.testingInforSV.approveExamAPIstore(this.Roomsend.testing_information_uid, this.Roomsend.period_id, this.Roomsend.date).subscribe(); + }), + tap(x => this.swSV.success('อนุมัติข้อสอบสำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + } + + cancel(){ + this.dialogRef.close(); + } +} diff --git a/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.html b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.html new file mode 100644 index 0000000..eb38dfc --- /dev/null +++ b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.html @@ -0,0 +1,69 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.scss b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.spec.ts b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.spec.ts new file mode 100644 index 0000000..e1b37da --- /dev/null +++ b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExaminationListComponent } from './approve-examination-list.component'; + +describe('ApproveExaminationListComponent', () => { + let component: ApproveExaminationListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExaminationListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExaminationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.ts b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.ts new file mode 100644 index 0000000..793cd86 --- /dev/null +++ b/src/app/feature/approve-examination/feature/list/approve-examination-list/approve-examination-list.component.ts @@ -0,0 +1,48 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../core/service/security/app-token.service'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {tap} from 'rxjs/operators'; +import {MatDialog} from '@angular/material/dialog'; +import {ApproveDialogComponent} from '../../dialog/approve-dialog/approve-dialog.component'; + +@Component({ + selector: 'app-approve-examination-list', + templateUrl: './approve-examination-list.component.html', + styleUrls: ['./approve-examination-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExaminationListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + column = ['1', '2', '3', '4', '5', '6', '7']; + constructor( + private testingInformationSV: TestingInformationService, + public dialog: MatDialog, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + approveDialog(TestInforuid){ + this.testingInformationSV.get(TestInforuid).pipe( + tap(x => this.openDialog(TestInforuid, x)), + ).subscribe(); + } + + openDialog(TestInforuid, data){ + const dialog = this.dialog.open(ApproveDialogComponent, { + width: '50%', + data: { + TestInforuid, + data : data, + } + }); + } + +} diff --git a/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.html b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.html new file mode 100644 index 0000000..fd3fbf8 --- /dev/null +++ b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
diff --git a/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.scss b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.spec.ts b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.spec.ts new file mode 100644 index 0000000..cdfc29e --- /dev/null +++ b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExaminationSearchComponent } from './approve-examination-search.component'; + +describe('ApproveExaminationSearchComponent', () => { + let component: ApproveExaminationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExaminationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExaminationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.ts b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.ts new file mode 100644 index 0000000..cdaa52d --- /dev/null +++ b/src/app/feature/approve-examination/feature/search/approve-examination-search/approve-examination-search.component.ts @@ -0,0 +1,43 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; + +@Component({ + selector: 'app-approve-examination-search', + templateUrl: './approve-examination-search.component.html', + styleUrls: ['./approve-examination-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExaminationSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + academicYearList = []; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + query = { + academic_year_code: null, + testing_information_name: null, + academic_semester_code: null + }; + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/approve-examination/router/approve-examination-router.ts b/src/app/feature/approve-examination/router/approve-examination-router.ts new file mode 100644 index 0000000..8b3f6f4 --- /dev/null +++ b/src/app/feature/approve-examination/router/approve-examination-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-approve-examination-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExaminationRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/auth-callback/auth-callback.module.ts b/src/app/feature/auth-callback/auth-callback.module.ts new file mode 100644 index 0000000..08639d1 --- /dev/null +++ b/src/app/feature/auth-callback/auth-callback.module.ts @@ -0,0 +1,33 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { AuthCallbackRouter } from './router/router'; +import { AuthCallbackComponent } from './presenter/auth-callback/auth-callback.component'; + +const routes: Routes = [ + { + path: '', + component: AuthCallbackRouter, + children: [ + { + path: '', + component: AuthCallbackComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + AuthCallbackRouter, + AuthCallbackComponent, + + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class AuthCallbackModule { } diff --git a/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.html b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.html new file mode 100644 index 0000000..8ea2772 --- /dev/null +++ b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.html @@ -0,0 +1 @@ +

กำลังพาคุณกลับเข้าสู่เว็บไซต์

diff --git a/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.scss b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.spec.ts b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.spec.ts new file mode 100644 index 0000000..2765f63 --- /dev/null +++ b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AuthCallbackComponent } from './auth-callback.component'; + +describe('AuthCallbackComponent', () => { + let component: AuthCallbackComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AuthCallbackComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AuthCallbackComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.ts b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.ts new file mode 100644 index 0000000..50f1dd6 --- /dev/null +++ b/src/app/feature/auth-callback/presenter/auth-callback/auth-callback.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { OidcAuthService } from 'src/app/core/service/oidc/oidc.service'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; + +@Component({ + selector: 'app-auth-callback', + templateUrl: './auth-callback.component.html', + styleUrls: ['./auth-callback.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AuthCallbackComponent implements OnInit { + constructor( + private oidc: OidcAuthService, + private apptokenSV: AppTokenService, + private router: Router + ) { } + + ngOnInit(): void { + this.oidc.manager.signinRedirectCallback().then(res => { + this.oidc.user = res + this.apptokenSV.exchangeToken().pipe( + tap(x => this.router.navigate(['/home'])), + catchError(err => { + this.router.navigate(['/']) + return throwError(err) + }) + ).subscribe() + }).catch(err => { + // this.router.navigate(['/']) + // this.router.navigate(['/setting-exam']) + }) + } +} diff --git a/src/app/feature/auth-callback/router/router.ts b/src/app/feature/auth-callback/router/router.ts new file mode 100644 index 0000000..e705c9e --- /dev/null +++ b/src/app/feature/auth-callback/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-candidate-list-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AuthCallbackRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/candidate-list.module.ts b/src/app/feature/candidate-list/candidate-list/candidate-list.module.ts new file mode 100644 index 0000000..34161fa --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/candidate-list.module.ts @@ -0,0 +1,54 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CandidateListRouter } from './router/candidate-list-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CandidateListContainer } from './container/candidate-list/candidate-list.container'; +import { CandidateListSearchComponent } from './presenter/search/candidate-list-search/candidate-list-search.component'; +import { CandidateListListComponent } from './presenter/list/candidate-list-list/candidate-list-list.component'; +import { DialogChangeSeatComponent } from './presenter/dialog/dialog-change-seat/dialog-change-seat.component'; +import {ScrollingModule} from '@angular/cdk/scrolling'; +import { DialogChangeRoomComponent } from './presenter/dialog/dialog-change-room/dialog-change-room.component'; +import { DialogSyncComponent } from './presenter/dialog/dialog-sync/dialog-sync.component'; +import { CandidateListTestInformationContainer } from './container/candidate-list-test-information/candidate-list-test-information.container'; +import { CandidateListTestInformationComponent } from './presenter/list/candidate-list-test-information/candidate-list-test-information.component'; +import { CandidateListTestInformationSearchComponent } from './presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component'; + +const routes: Routes = [ + { + path: '', + component: CandidateListRouter, + children: [ + { + path: '', + component: CandidateListTestInformationContainer + }, + { + path: 'view/:id', + component: CandidateListContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + CandidateListRouter, + CandidateListContainer, + CandidateListSearchComponent, + CandidateListListComponent, + DialogChangeSeatComponent, + DialogChangeRoomComponent, + DialogSyncComponent, + CandidateListTestInformationContainer, + CandidateListTestInformationComponent, + CandidateListTestInformationSearchComponent, + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ScrollingModule, + ] +}) +export class CandidateListModule { } diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.html b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.html new file mode 100644 index 0000000..196a9b6 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.scss b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.spec.ts b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.spec.ts new file mode 100644 index 0000000..fec3421 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListTestInformationContainer } from './candidate-list-test-information.container'; + +describe('CandidateListTestInformationContainer', () => { + let component: CandidateListTestInformationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListTestInformationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListTestInformationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.ts b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.ts new file mode 100644 index 0000000..1d771c0 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list-test-information/candidate-list-test-information.container.ts @@ -0,0 +1,35 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Router} from "@angular/router"; +import {TestingInformationService} from "../../../../../core/service/testing-information/testing-information.service"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {Observable} from "rxjs"; + +@Component({ + selector: 'app-candidate-list-test-information', + templateUrl: './candidate-list-test-information.container.html', + styleUrls: ['./candidate-list-test-information.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListTestInformationContainer implements OnInit { + subjectList$ = new Observable(); + constructor( + private router: Router, + private testinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.testinforSV.search(`?is_open=true`); + } + + view(id){ + this.router.navigate(['candidate-list/view', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.testinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.testinforSV.search(`?is_open=true`); + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.html b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.html new file mode 100644 index 0000000..045c296 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.html @@ -0,0 +1,17 @@ + + + + + diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.scss b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.spec.ts b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.spec.ts new file mode 100644 index 0000000..f5787ef --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListContainer } from './candidate-list.container'; + +describe('CandidateListContainer', () => { + let component: CandidateListContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.ts b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.ts new file mode 100644 index 0000000..4ce8b93 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/container/candidate-list/candidate-list.container.ts @@ -0,0 +1,111 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {SubjectsService} from '../../../../../core/service/settings/subjects.service'; +import {Observable, throwError} from 'rxjs'; +import {TestingRegisterService} from '../../../../../core/service/testing-register/testing-register.service'; +import {VEligibleCandidatesService} from '../../../../../core/service/testing-register/v-eligible-candidates.service'; +import {MatDialog} from '@angular/material/dialog'; +import {DialogSyncComponent} from '../../presenter/dialog/dialog-sync/dialog-sync.component'; +import {catchError, concatMap, tap} from 'rxjs/operators'; +import {BranchService} from '../../../../../core/service/settings/branch.service'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {TestingInformationService} from 'src/app/core/service/testing-information/testing-information.service'; +import { + EligibleCandidateService +} from '../../../../../core/service/report/eligible_candidate/eligible-candidate.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-candidate-list', + templateUrl: './candidate-list.container.html', + styleUrls: ['./candidate-list.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListContainer implements OnInit { + testinginformationuid; + subjectList2 = []; + subjectList = []; + subjectList1$ = new Observable(); + subjectList3 = []; + subjectList4 = []; + testingInfoData; + + constructor( + private router: Router, + public activeRouter: ActivatedRoute, + private VECandidateSV: VEligibleCandidatesService, + private ReportEligibleCandidate: EligibleCandidateService, + private subjectSV: SubjectsService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private testcenterSV: TestingCenterService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingInfoSV: TestingInformationService + ) { + } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => this.testinginformationuid = x.id), + tap(x => { + this.subjectList1$ = this.VECandidateSV.getAllByTestinUid(x.id); + }), + concatMap(x => this.testingInfoSV.get(this.testinginformationuid)), + tap(x => this.testingInfoData = x) + ).subscribe(); + this.subjectSV.getAll().subscribe( + result => this.subjectList4 = result + ); + this.branchSV.getAll().subscribe( + result => this.subjectList = result + ); + this.testingFieldSV.getAll().subscribe( + result => { + this.subjectList2 = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => this.subjectList3 = result + ); + } + + search(query) { + query += `&testing_information_uid=${this.testinginformationuid}`; + if (query) return this.subjectList1$ = this.VECandidateSV.search(`?${query}`); + if (!query) return this.subjectList1$ = this.VECandidateSV.getAllByTestinUid(this.testinginformationuid); + } + + export(testInforUid) { + this.ReportEligibleCandidate.getReportWithTestInforUid(testInforUid) + .subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + } + + // syncData(data){ + // console.log(data) + // } + + syncData(data) { + // console.log(id); + const dialogRef = this.dialog.open(DialogSyncComponent, { + width: '500px', + height: '340px', + }); + dialogRef.afterClosed().pipe( + tap(x => { + this.VECandidateSV.getAll().pipe( + tap(y => this.subjectList1$ = this.VECandidateSV.getAll()), + tap(y => this.cdr.detectChanges()) + ).subscribe(); + }), + ).subscribe(); + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.html b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.html new file mode 100644 index 0000000..a79473c --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.html @@ -0,0 +1,59 @@ +

+
+
+ + + + + --กรุณาเลือก-- + + + {{subject.branch_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject2.testing_field_name_th}} + + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject3.testing_room_name_th}} + + +
+ +
+ + +
+
+
+ + + + diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.spec.ts new file mode 100644 index 0000000..82c5e5a --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogChangeRoomComponent } from './dialog-change-room.component'; + +describe('DialogChangeRoomComponent', () => { + let component: DialogChangeRoomComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogChangeRoomComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogChangeRoomComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.ts new file mode 100644 index 0000000..84f983c --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component.ts @@ -0,0 +1,135 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Inject} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {CheckAvailableSeatService} from '../../../../../../core/service/testing-register/check-available-seat.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {CheckAvailableRoomService} from '../../../../../../core/service/testing-register/check-available-room.service'; + +@Component({ + selector: 'app-dialog-change-room', + templateUrl: './dialog-change-room.component.html', + styleUrls: ['./dialog-change-room.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogChangeRoomComponent implements OnInit { + subjectList = []; + subjectList2 = []; + subjectList3 = []; + roomData: any; + form; + setupdata = { + testing_center_uid: null, + testing_center_name_th: null, + branch_uid: null, + branch_name_th: null, + testing_field_uid: null, + testing_field_name_th: null, + testing_room_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + }; + constructor( + private fb: FormBuilder, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private dialogRef: MatDialogRef, + private checkavailableseatSV: CheckAvailableSeatService, + private checkavailableroomSV: CheckAvailableRoomService, + private swSV: SweetalertService, + private cdf: ChangeDetectorRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + testing_subject_selected_uid: null, + branch_uid: null, + branch_name_th: null, + testing_field_uid: null, + testing_field_name_th: null, + testing_center_uid: null, + testing_room_name_th: null, + }); + } + + ngOnInit(): void { + this.form.get('testing_subject_selected_uid').setValue(this.data.testing_subject_selected_uid); + this.branchSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList = x), + ).subscribe(); + this.testingFieldSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe(); + this.testcenterSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList3 = x), + ).subscribe(); + } + + setFormtestcentername(testcenterData, choose){ + console.log(testcenterData); + console.log(choose); + if (choose === 'branch_name_th'){ + this.setupdata.branch_name_th = testcenterData.branch_name_th; + this.setupdata.branch_uid = testcenterData.branch_uid; + this.form.get('branch_uid').setValue(testcenterData.branch_uid); + this.testingFieldSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe( + result => { + this.subjectList2 = this.subjectList2.filter((x) => { + return x.branch_uid === testcenterData.branch_uid; + }); + } + ); + } + if (choose === 'testing_field_name_th'){ + this.setupdata.testing_field_name_th = testcenterData.testing_field_name_th; + this.setupdata.testing_field_uid = testcenterData.testing_field_uid; + this.form.get('testing_field_uid').setValue(testcenterData.testing_field_uid); + this.testcenterSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList3 = x), + ).subscribe( + result => { + this.subjectList3 = this.subjectList3.filter((x) => { + return x.testing_field_uid === testcenterData.testing_field_uid; + }); + } + ); + } + if (choose === 'testing_room_name_th'){ + this.setupdata.testing_room_name_th = testcenterData.testing_room_name_th; + this.setupdata.testing_room_uid = testcenterData.testing_center_uid; + this.form.get('testing_center_uid').setValue(testcenterData.testing_center_uid); + this.setupdata.testing_center_uid = testcenterData.testing_center_uid; + } + } + + save(){ + const form = this.form.getRawValue(); + console.log(this.form.getRawValue()); + // this.checkavailableroomSV.update2(form).pipe( + // tap(x => this.swSV.updateSuccess()), + // tap(x => this.dialogRef.close()), + // catchError(err => { + // this.swSV.err(); + // this.dialogRef.close('err'); + // return throwError(err); + // }) + // ).subscribe(); + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.html b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.html new file mode 100644 index 0000000..e31bbd7 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.html @@ -0,0 +1,46 @@ +
+
+
+ + +
+ +
+ + + +
+ +
+ + + +
+ +
+
+
+ + +
+
+ + +
+
+
+ +
+ + +
+
+
+ + + + diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.scss new file mode 100644 index 0000000..55eb0cd --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.scss @@ -0,0 +1,9 @@ +.example-viewport { + height: 200px; + width: 200px; + border: 1px solid black; +} + +.example-item { + height: 50px; +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.spec.ts new file mode 100644 index 0000000..3388965 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogChangeSeatComponent } from './dialog-change-seat.component'; + +describe('DialogChangeSeatComponent', () => { + let component: DialogChangeSeatComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogChangeSeatComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogChangeSeatComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.ts new file mode 100644 index 0000000..b610d97 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component.ts @@ -0,0 +1,74 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {CheckAvailableSeatService} from '../../../../../../core/service/testing-register/check-available-seat.service'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {FormBuilder} from '@angular/forms'; +import {UpdateTestingSeatService} from "../../../../../../core/service/testing-register/update-testing-seat.service"; + +@Component({ + selector: 'app-dialog-change-seat', + templateUrl: './dialog-change-seat.component.html', + styleUrls: ['./dialog-change-seat.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogChangeSeatComponent implements OnInit { + seatData: any; + form; + constructor( + private fb: FormBuilder, + private dialogRef: MatDialogRef, + private checkavailableseatSV: CheckAvailableSeatService, + private updatetestingseatSV: UpdateTestingSeatService, + private swSV: SweetalertService, + private cdf: ChangeDetectorRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + testing_subject_selected_uid: null, + testing_seat: null + }); + } + + ngOnInit(): void { + console.log(this.data); + this.checkseat(this.data); + } + + checkseat(data){ + this.checkavailableseatSV.add(data).pipe( + // tap(x => this.swSV.success('มีห้องว่าง')), + // tap(x => console.log(x)), + tap(x => { + this.seatData = x; + this.form.patchValue(this.data); + this.cdf.detectChanges(); + }), + catchError(err => { + this.swSV.errText('ไม่มีห้องว่าง'); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } + + save(){ + const form = this.form.getRawValue(); + console.log(this.form.getRawValue()); + this.updatetestingseatSV.updateSeat(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close('err'); + return throwError(err); + }) + ).subscribe(); + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.html b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.html new file mode 100644 index 0000000..0cd5e5f --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.html @@ -0,0 +1,66 @@ +
+
+
+
+ + สร้างข้อสอบใหม่ทั้งหมด + สร้างข้อสอบเฉพาะคนที่ไม่มีข้อสอบ + +
+
+
+ + + + + + + + + + + + + + +
+ + +
+
+ + +
+ + +
+ +
+ หมายเหตุ :

{{isCanDetail}}

+
+ +
+
+ + + diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.spec.ts new file mode 100644 index 0000000..792cde5 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogSyncComponent } from './dialog-sync.component'; + +describe('DialogSyncComponent', () => { + let component: DialogSyncComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogSyncComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogSyncComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.ts new file mode 100644 index 0000000..f04989b --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-sync/dialog-sync.component.ts @@ -0,0 +1,116 @@ +import { TOUCH_BUFFER_MS } from '@angular/cdk/a11y'; +import { formatDate } from '@angular/common'; +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {catchError, combineAll, tap} from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { SyncService } from 'src/app/core/service/sync/sync.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; +import Swal from 'sweetalert2'; +import {FormBuilder, FormGroup} from '@angular/forms'; +import {data} from 'autoprefixer'; +import { throwError } from 'rxjs'; + +@Component({ + selector: 'app-dialog-sync', + templateUrl: './dialog-sync.component.html', + styleUrls: ['./dialog-sync.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogSyncComponent implements OnInit { + form: FormGroup; + isCanSync = false; + isCanDetail; + query = { + from_date: null, + testing_information_uid: null, + to_date: null, + is_delete: null + }; + maxDate; + testingInfomation; + constructor( + public dialogRef: MatDialogRef, + private syncSV: SyncService, + private cdr: ChangeDetectorRef, + private formBuilder: FormBuilder, + private swSV: SweetalertService, + private testingInformationSV: TestingInformationService, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.formBuilder.group({ + testing_information_uid: null, + is_delete: true, + }); + } + + ngOnInit(): void { + this.maxDate = new Date(); + this.testingInformationSV.getMaintrueAndTestInforUid(this.data.testing_information_uid).pipe( + tap(x => this.testingInfomation = x), + tap(x => this.form.get('testing_information_uid').patchValue(this.data.testing_information_uid)), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + this.testingInformationSV.checkBeforeSync(this.data.testing_information_uid).pipe( + tap(y => this.isCanSync = true), + tap(y => this.cdr.detectChanges()), + catchError(err => { + this.isCanDetail = err.error; + this.cdr.detectChanges() + return throwError(err); + }) + ).subscribe() + } + + save(){ + this.query.from_date = formatDate(this.query.from_date, 'yyyy-MM-dd', 'en-US'); + this.query.to_date = formatDate(this.query.to_date, 'yyyy-MM-dd', 'en-US'); + this.query.is_delete = this.form.get('is_delete').value; + const query = createQueryStringFromObject(this.query); + Swal.fire({ + title: 'กำลังสร้างข้อสอบ...', + // text: `ใช้เวลาประมาณ ${this.data.mins} / นาที`, + html: `ใช้เวลาประมาณ ${this.data.mins} นาที`, + allowEscapeKey: false, + allowOutsideClick: false, + didOpen: () => { + Swal.showLoading(Swal.getDenyButton()) + } + }); + this.syncSV.sync_all(`?${query}`).pipe( + tap(x => Swal.hideLoading()), + tap(x => Swal.close()), + tap((x:any) => this.swSV.saveSuccessCustom('เสร็จสิ้น',x)), + tap(x => this.dialogRef.close()), + catchError(err => { + Swal.hideLoading() + Swal.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe(); + } + + cancel(){ + this.dialogRef.close() + } + + setDate(x){ + const selectData = this.testingInfomation.filter((member) => { + return member.testing_information_uid === x; + }); + if (selectData !== undefined){ + this.query.from_date = selectData[0].testing_start_datetime; + this.query.to_date = selectData[0].testing_end_datetime; + this.query.testing_information_uid = selectData[0].testing_information_uid; + }else { + this.swSV.error('ไม่พบข้อมูล'); + } + } + + display(uid){ + if (uid && this.testingInfomation) return this.testingInfomation.find(x => x.testing_information_uid === uid)?.testing_information_name + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.html b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.html new file mode 100644 index 0000000..3624d07 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.html @@ -0,0 +1,75 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสผู้สอบ {{x.student_code}} ชื่อ-นามสกุล {{x.examinee_full_name}} ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} ที่นั่งสอบ {{x.testing_seat}} รหัสวิชาที่สอบ {{x.subject_code}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} ({{x.start_time}}) ยืนยันข้อมูล + {{x.testing_register_approved? 'ยืนยันแล้ว' : 'ยังไม่ยืนยัน'}} +
+ +
+
+
diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.spec.ts new file mode 100644 index 0000000..ee21ae6 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListListComponent } from './candidate-list-list.component'; + +describe('CandidateListListComponent', () => { + let component: CandidateListListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.ts new file mode 100644 index 0000000..4d8e396 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-list/candidate-list-list.component.ts @@ -0,0 +1,86 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {MatDialog} from '@angular/material/dialog'; +import {DialogChangeSeatComponent} from '../../dialog/dialog-change-seat/dialog-change-seat.component'; +import {VEligibleCandidatesService} from '../../../../../../core/service/testing-register/v-eligible-candidates.service'; +import {tap} from 'rxjs/operators'; +import {DialogChangeRoomComponent} from '../../dialog/dialog-change-room/dialog-change-room.component'; +import {ActivatedRoute, Router} from '@angular/router'; + +@Component({ + selector: 'app-candidate-list-list', + templateUrl: './candidate-list-list.component.html', + styleUrls: ['./candidate-list-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + column = [ + 'student_code', + 'examinee_full_name', + 'branch_name_th', + 'testing_field_name_th', + 'testing_room_name_th', + 'testing_seat', + 'subject_code', + 'testing_datetime', + 'period_id', + 'testing_register_approved' + ]; + constructor( + private router: Router, + public activeRouter: ActivatedRoute, + private dialog: MatDialog, + private cdf: ChangeDetectorRef, + private VECandidateSV: VEligibleCandidatesService + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + openDialog(id){ + console.log(id); + const dialogRef = this.dialog.open(DialogChangeSeatComponent, { + width: '500px', + height: '460px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => { + this.activeRouter.params.pipe( + tap(y => console.log(x.id)), + tap(y => { + this.subjectList = this.VECandidateSV.getAllByTestinUid(x.id); + }), + tap(y => this.cdf.detectChanges()) + + ).subscribe(); + }) + ).subscribe(); + } + + openDialogChangeRoom(id){ + console.log(id); + const dialogRef = this.dialog.open(DialogChangeRoomComponent, { + width: '500px', + height: '400px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => { + this.VECandidateSV.getAll().pipe( + tap(y => console.log(y)), + tap(y => this.subjectList = y), + tap(y => this.cdf.detectChanges()) + ).subscribe(); + }), + ).subscribe(); + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.html b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.html new file mode 100644 index 0000000..313b043 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.html @@ -0,0 +1,85 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.spec.ts new file mode 100644 index 0000000..6ea5483 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListTestInformationComponent } from './candidate-list-test-information.component'; + +describe('CandidateListTestInformationComponent', () => { + let component: CandidateListTestInformationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListTestInformationComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListTestInformationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.ts new file mode 100644 index 0000000..cca98fa --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/list/candidate-list-test-information/candidate-list-test-information.component.ts @@ -0,0 +1,52 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; + +@Component({ + selector: 'app-candidate-list-test-information-list', + templateUrl: './candidate-list-test-information.component.html', + styleUrls: ['./candidate-list-test-information.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListTestInformationComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() view = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'is_open', + 'created_by', + 'created_datetime', + '7']; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onView(id){ + this.view.emit(id); + } +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.html b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.html new file mode 100644 index 0000000..3cbfc49 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.html @@ -0,0 +1,113 @@ +

ค้นหาข้อมูลผู้สอบในรอบสอบ {{testingInformationData?.testing_information_name}}

+
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_field_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.testing_room_name_th}} + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + Section {{x.period_id}} {{x.start_time}} + + +
+
+ +
+
+ + +
+ +
+
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+
+
+ + + diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.spec.ts new file mode 100644 index 0000000..69cfc79 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListSearchComponent } from './candidate-list-search.component'; + +describe('CandidateListSearchComponent', () => { + let component: CandidateListSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.ts new file mode 100644 index 0000000..fb6e4ef --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-search/candidate-list-search.component.ts @@ -0,0 +1,150 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {tap} from 'rxjs/operators'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {formatDate} from "@angular/common"; +import { ThisReceiver } from '@angular/compiler'; +import {ActivatedRoute} from '@angular/router'; + +@Component({ + selector: 'app-candidate-list-search', + templateUrl: './candidate-list-search.component.html', + styleUrls: ['./candidate-list-search.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListSearchComponent implements OnInit,OnChanges { + @Input() subjectList2: any = []; + @Input() subjectList: any = []; + @Input() subjectList1: any = []; + @Input() subjectList3: any = []; + @Input() subjectList4: any = []; + @Input() testingInformationData: any + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + @Output() export = new EventEmitter(); + branchList: any = []; + testInforId; + testingFieldList: any = []; + filteredTestingFieldList: any = []; + filteredRoomList: any = []; + roomList: any = []; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + constructor( + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + public activeRouter: ActivatedRoute, + ) { } + query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null, + }; + ngOnInit(): void { + } + + ngOnChanges(): void { + this.branchList = this.testingInformationData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.branch_name_th === value.branch_name_th) === index) + this.roomList = this.testingInformationData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_room_name_th === value.testing_room_name_th) === index) + this.testingFieldList = this.testingInformationData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_field_name_th === value.testing_field_name_th) === index) + } + + onAdd(){ + this.add.emit(); + } + + filterTestingField(data){ + this.filteredTestingFieldList = this.branchList.filter(x => data.branch_uid == x.branch_uid) + } + + setRoom(data){ + this.filteredRoomList = this.roomList.filter(x => (x.branch_uid == data.branch_uid)&&(x.testing_field_uid == data.testing_field_uid)) + } + + onExport(){ + this.activeRouter.params.pipe( + tap(x => this.export.emit(x.id)), + ).subscribe(); + } + + onSearch(){ + const periodid = []; + let textfree = ''; + if (this.query.testing_datetime != null){ + this.query.testing_datetime = formatDate(this.query.testing_datetime, 'yyyy-MM-dd', 'en-US'); + } + if (this.query.period_id != null){ + periodid.push(this.query.period_id); + for (let i = 0; i < periodid[0].length; i++) { + console.log(periodid[0][i]); + textfree += `&period_id=${periodid[0][i]}`; + } + // this.query.period_id = null; + } + const query = createQueryStringFromObject(this.query); + this.search.emit(`${query}${textfree}`); + } + + displayTestInfor(uid){ + if (uid && this.subjectList4) return this.subjectList4.find(x => x.subject_uid === uid)?.subject_code + } + + displayBrand(uid){ + if (uid && this.subjectList) return this.subjectList.find(x => x.branch_uid === uid)?.branch_name_th + } + + displayField(uid){ + if (uid && this.subjectList2) return this.subjectList2.find(x => x.testing_field_uid === uid)?.testing_field_name_th + } + + displayCenter(uid){ + if (uid && this.subjectList3) return this.subjectList3.find(x => x.testing_center_uid === uid)?.testing_room_name_th + } + + clear(){ + this.query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null, + }; + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.html b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.scss b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.spec.ts b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.spec.ts new file mode 100644 index 0000000..086379d --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidateListTestInformationSearchComponent } from './candidate-list-test-information-search.component'; + +describe('CandidateListTestInformationSearchComponent', () => { + let component: CandidateListTestInformationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidateListTestInformationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidateListTestInformationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.ts b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.ts new file mode 100644 index 0000000..d8c98aa --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/presenter/search/candidate-list-test-information-search/candidate-list-test-information-search.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-candidate-list-test-information-search', + templateUrl: './candidate-list-test-information-search.component.html', + styleUrls: ['./candidate-list-test-information-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListTestInformationSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + } + +} diff --git a/src/app/feature/candidate-list/candidate-list/router/candidate-list-router.ts b/src/app/feature/candidate-list/candidate-list/router/candidate-list-router.ts new file mode 100644 index 0000000..9ef2d22 --- /dev/null +++ b/src/app/feature/candidate-list/candidate-list/router/candidate-list-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-candidate-list-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidateListRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/check-candidate-list.module.ts b/src/app/feature/candidate-list/check-candidate-list/check-candidate-list.module.ts new file mode 100644 index 0000000..fc5e05a --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/check-candidate-list.module.ts @@ -0,0 +1,55 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CheckCandidateListRouter } from './router/check-candidate-list-router'; +import { CheckCandidateListContainer } from './container/check-candidate-list/check-candidate-list.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CheckCandidateListSearchComponent } from './presenter/check-candidate-list-search/check-candidate-list-search.component'; +import { CheckCandidateListTableComponent } from './presenter/check-candidate-list-table/check-candidate-list-table.component'; +import { CheckCandidateTestingListComponent } from './presenter/check-candidate-testing-list/check-candidate-testing-list.component'; +import { + ChangeExamInformationFormComponent +} from '../../exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component'; +import { CheckCandidateTestingListSearchComponent } from './presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component'; +import { CheckCandidateTestingContainer } from './container/check-candidate-testing/check-candidate-testing.container'; + + +const routes: Routes = [ + { + path: '', + component: CheckCandidateListRouter, + children: [ + { + path: 'view/:id', + component: CheckCandidateListContainer + }, + { + path: '', + component: CheckCandidateTestingContainer + }, + // { + // path: 'view/:id', + // component: CheckCandidateTestingListComponent + // }, + ] + } +]; + + +@NgModule({ + declarations: [ + CheckCandidateListRouter, + CheckCandidateListContainer, + CheckCandidateListSearchComponent, + CheckCandidateListTableComponent, + CheckCandidateTestingListComponent, + CheckCandidateTestingListSearchComponent, + CheckCandidateTestingContainer + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class CheckCandidateListModule { } diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.html b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.html new file mode 100644 index 0000000..14270b1 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.html @@ -0,0 +1,12 @@ + + diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.scss b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.spec.ts b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.spec.ts new file mode 100644 index 0000000..8348300 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateListContainer } from './check-candidate-list.container'; + +describe('CheckCandidateListContainer', () => { + let component: CheckCandidateListContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateListContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateListContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.ts b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.ts new file mode 100644 index 0000000..d2f8ccc --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-list/check-candidate-list.container.ts @@ -0,0 +1,130 @@ +import {MatDialog} from '@angular/material/dialog'; +import {TestingCenterService} from './../../../../../core/service/TestingCenter/testing-center.service'; +import {VEligibleCandidatesService} from './../../../../../core/service/testing-register/v-eligible-candidates.service'; +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, OnChanges, SimpleChanges} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {ActivatedRoute, Router} from '@angular/router'; +import {SubjectsService} from 'src/app/core/service/settings/subjects.service'; +import {BranchService} from 'src/app/core/service/settings/branch.service'; +import {TestingFieldService} from 'src/app/core/service/settings/testing-field.service'; +import {DialogSyncComponent} from '../../../candidate-list/presenter/dialog/dialog-sync/dialog-sync.component'; +import {catchError, concatMap, filter, map, switchMap, tap} from 'rxjs/operators'; +import {SyncService} from "../../../../../core/service/sync/sync.service"; +import Swal from "sweetalert2"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {TestingInformationService} from 'src/app/core/service/testing-information/testing-information.service'; +import {CustomeEventPage} from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-check-candidate-list', + templateUrl: './check-candidate-list.container.html', + styleUrls: ['./check-candidate-list.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateListContainer implements OnInit { + testingInformationUID; + eligibleCandidate$ = new Observable(); + subject$ = new Observable() + testingField$ = new Observable() + testingCenter$ = new Observable() + branch$ = new Observable() + haveExam: false; + testingInfoData; + paginator; + currentQueryPaging = ''; + currentQueryString = ''; + + constructor( + public activeRouter: ActivatedRoute, + private VECandidateSV: VEligibleCandidatesService, + private subjectSV: SubjectsService, + private syncSV: SyncService, + private swSV: SweetalertService, + private dialog: MatDialog, + private testingInfoSV: TestingInformationService + ) { + } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => this.testingInformationUID = x.id), + tap(x => this.currentQueryString = `testing_information_uid=${x.id}`), + concatMap(x => this.testingInfoSV.get(this.testingInformationUID)), + tap(x => this.testingInfoData = x) + ).subscribe() + this.subject$ = this.subjectSV.getAll() + } + + pageChange(event: CustomeEventPage) { + this.paginator = event.paginator + this.currentQueryPaging = event.queryStringPage + if (this.currentQueryString) { + return this.eligibleCandidate$ = this.VECandidateSV.getPage(`${event.queryStringPage}?${this.currentQueryString}`) + } else { + return this.eligibleCandidate$ = this.VECandidateSV.getPage(`${event.queryStringPage}`) + } + } + + search(queryString) { + console.log(queryString); + this.currentQueryString = queryString; + if (queryString) { + this.paginator.firstPage(); + this.eligibleCandidate$ = this.VECandidateSV.getPage(`${this.currentQueryPaging}?${this.currentQueryString}`); + // if (haveExan !== false) { + // this.paginator.firstPage(); + // this.eligibleCandidate$ = this.VECandidateSV.getPage(`${this.currentQueryPaging}?${this.currentQueryString}`) + // .pipe(map((x: any) => { + // const res = x.results.filter(y => y.have_exan === haveExan); + // return {...x, results: [...res], row_count: x.row_count}; + // })); + // return this.eligibleCandidate$; + // } else { + // return this.eligibleCandidate$ = this.VECandidateSV.getPage(`${this.currentQueryPaging}`) + // } + } + if (!queryString) { + return this.eligibleCandidate$ = this.VECandidateSV.getPage(`${this.currentQueryPaging}`) + } + } + + syncData(data) { + const dataObject = { + testing_information_uid: this.testingInformationUID, + mins: (this.paginator.length * 3) / 60 + } + const dialogRef = this.dialog.open(DialogSyncComponent, { + width: '500px', + height: '340px', + data: dataObject, + }); + } + + clearData(data) { + this.swSV.confirmText('ต้องการล้างการสร้างข้อสอบหรือไม่').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + Swal.fire({ + title: 'กำลังซิงค์ข้อมูล...', + html: 'กรุณารอ...', + allowEscapeKey: false, + allowOutsideClick: false, + didOpen: () => { + Swal.showLoading(); + } + }); + return this.syncSV.deleteTestInforUid(this.testingInformationUID).pipe( + tap(x => Swal.hideLoading()), + tap(x => Swal.close()), + tap(x => this.swSV.success('เสร็จสิ้น')), + catchError(err => { + this.swSV.errOpenExamDetailText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.html b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.html new file mode 100644 index 0000000..06af224 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.html @@ -0,0 +1,9 @@ + + + diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.scss b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.spec.ts b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.spec.ts new file mode 100644 index 0000000..73b1979 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateTestingContainer } from './check-candidate-testing.container'; + +describe('CheckCandidateTestingContainer', () => { + let component: CheckCandidateTestingContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateTestingContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateTestingContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.ts b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.ts new file mode 100644 index 0000000..1f9c11a --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/container/check-candidate-testing/check-candidate-testing.container.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {Observable} from 'rxjs'; +import {Router} from '@angular/router'; +import {CustomeEventPage} from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-check-candidate-testing', + templateUrl: './check-candidate-testing.container.html', + styleUrls: ['./check-candidate-testing.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateTestingContainer implements OnInit { + testingInformation$ = new Observable(); + paginator; + currentQueryPaging = ''; + currentQueryString = ''; + + constructor( + private testinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private router: Router, + ) { + } + + ngOnInit(): void { + this.search(`is_open=true`) + } + + pageChange(event: CustomeEventPage) { + this.paginator = event.paginator + this.currentQueryPaging = event.queryStringPage + if (this.currentQueryString) { + return this.testingInformation$ = this.testinforSV.getPage(`${event.queryStringPage}?${this.currentQueryString}`) + } else { + return this.testingInformation$ = this.testinforSV.getPage(`${event.queryStringPage}`) + } + } + + search(queryString) { + // if(query) return this.testingInformation$ = this.testinforSV.getSearchForCountSeat(`?${query}`); + // if(!query) return this.testingInformation$ = this.testinforSV.getSearchForCountSeat(`?is_open=true`); + this.currentQueryString = queryString + if (queryString) { + this.paginator.firstPage() + return this.testingInformation$ = this.testinforSV.getPage(`${this.currentQueryPaging}?${this.currentQueryString}`) + } + if (!queryString) { + return this.testingInformation$ = this.testinforSV.getPage(`${this.currentQueryPaging}?is_open=true`) + } + } + + view(id) { + this.router.navigate(['check-candidate-list/view', id]); + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.html b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.html new file mode 100644 index 0000000..5f49b19 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.html @@ -0,0 +1,100 @@ +

ค้นหานักศึกษาเพื่อสร้างข้อสอบในรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+
+ + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+
+ +
+
+
+
+
+ + + + + + +
+
+ + + + + + +
+
+
+ +
+ + + + + Section {{x.period_id}} {{x.start_time}} + + +
+
+
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.scss b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.spec.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.spec.ts new file mode 100644 index 0000000..706854d --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateListSearchComponent } from './check-candidate-list-search.component'; + +describe('CheckCandidateListSearchComponent', () => { + let component: CheckCandidateListSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateListSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateListSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.ts new file mode 100644 index 0000000..58ba030 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-search/check-candidate-list-search.component.ts @@ -0,0 +1,124 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter} from '@angular/core'; +import {tap} from 'rxjs/operators'; +import {TestingFieldService} from 'src/app/core/service/settings/testing-field.service'; +import {TestingCenterService} from 'src/app/core/service/TestingCenter/testing-center.service'; +import {createQueryStringFromObject} from 'src/app/shared/util/func'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-check-candidate-list-search', + templateUrl: './check-candidate-list-search.component.html', + styleUrls: ['./check-candidate-list-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateListSearchComponent implements OnInit { + @Input() testingInfoData: any; + @Input() subjectList: any = []; + @Output() add = new EventEmitter(); + @Output() cleardata = new EventEmitter(); + @Output() search = new EventEmitter(); + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + query = { + subject_uid: null, + student_code: null, + has_exam: null, + start_testing_date: null, + end_testing_date: null, + period_id: null, + testing_information_uid: null + }; + + constructor() { + } + + ngOnInit(): void { + + } + + onClear() { + this.cleardata.emit(); + } + + onAdd() { + this.add.emit(); + } + + onSearch() { + this.query.testing_information_uid = this.testingInfoData.testing_information_uid + const periodid = []; + let textfree = ''; + if (this.query.start_testing_date != null) { + this.query.start_testing_date = formatDate(this.query.start_testing_date, 'yyyy-MM-dd', 'en-US'); + } + if (this.query.end_testing_date != null) { + this.query.end_testing_date = formatDate(this.query.end_testing_date, 'yyyy-MM-dd', 'en-US'); + } + if (this.query.period_id != null) { + periodid.push(this.query.period_id); + for (let i = 0; i < periodid[0].length; i++) { + console.log(periodid[0][i]); + textfree += `&period_id=${periodid[0][i]}`; + } + this.query.period_id = null; + } + const query = createQueryStringFromObject(this.query); + // this.search.emit({value: `${query}${textfree}`, have_exan: this.query.have_exan === 'true' ? true : null}); + // this.search(emit) + this.search.emit(`${query}${textfree}`); + } + + displaySubject(uid) { + if (uid && this.subjectList) return this.subjectList.find(x => x.subject_uid === uid)?.subject_code + } + + clear() { + this.query = { + subject_uid: null, + student_code: null, + has_exam: null, + start_testing_date: null, + end_testing_date: null, + period_id: null, + testing_information_uid: this.testingInfoData.testing_information_uid + }; + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + checkDatesearch() { + if (this.query.start_testing_date != null && this.query.end_testing_date === null) { + this.query.end_testing_date = this.query.start_testing_date; + } + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.html b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.html new file mode 100644 index 0000000..8bde6a3 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.html @@ -0,0 +1,57 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล {{x.examinee_full_name}} ศูนย์สอบ {{x.branch_name_th}} รหัสวิชาที่สอบ {{x.subject_code}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} ({{x.start_time}}) สถานะข้อสอบ +
มีข้อสอบ
+ +
รหัสผ่าน

{{x.pwd}}

วันที่สร้างข้อสอบ {{x.create_date | thaidate}}
+ +
+
+
diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.scss b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.spec.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.spec.ts new file mode 100644 index 0000000..3a39d8a --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateListTableComponent } from './check-candidate-list-table.component'; + +describe('CheckCandidateListTableComponent', () => { + let component: CheckCandidateListTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateListTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateListTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.ts new file mode 100644 index 0000000..efc54a7 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-list-table/check-candidate-list-table.component.ts @@ -0,0 +1,42 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Input, + OnChanges, + SimpleChanges, + ChangeDetectorRef +} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {tap} from 'rxjs/operators'; +import {BaseList} from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-check-candidate-list-table', + templateUrl: './check-candidate-list-table.component.html', + styleUrls: ['./check-candidate-list-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateListTableComponent extends BaseList implements OnInit, OnChanges { + @Input() eligibleCandidateList: any = []; + @Input() haveExam: any; + column = ['1', '2', '3', '4', '7', '8', '9', '10', '11', '0']; + + constructor( + private dialog: MatDialog, + private cdf: ChangeDetectorRef, + ) { + super(); + } + + ngOnInit(): void { + this.getEventPage().pipe( + tap(x => this.onPaginatorPageChange.emit(x)) + ).subscribe() + } + + ngOnChanges(changes: SimpleChanges): void { + this.eligibleCandidateList = this.updatePagingMatabe(this.eligibleCandidateList ? this.eligibleCandidateList : []); + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.html b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.scss b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.spec.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.spec.ts new file mode 100644 index 0000000..d68a681 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateTestingListSearchComponent } from './check-candidate-testing-list-search.component'; + +describe('CheckCandidateTestingListSearchComponent', () => { + let component: CheckCandidateTestingListSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateTestingListSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateTestingListSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.ts new file mode 100644 index 0000000..21898e9 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list-search/check-candidate-testing-list-search.component.ts @@ -0,0 +1,51 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; + +@Component({ + selector: 'app-check-candidate-testing-list-search', + templateUrl: './check-candidate-testing-list-search.component.html', + styleUrls: ['./check-candidate-testing-list-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateTestingListSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + + constructor( + private AcademicYearSV: AcademicYearService, + ) { + } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch() { + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear() { + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.html b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.html new file mode 100644 index 0000000..97e379c --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.html @@ -0,0 +1,76 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} จำนวนผู้เข้าสอบ {{x.total_register}} จำนวนคนที่มีข้อสอบ/ทั้งหมด {{x.total_have_exam_total_register}} จำนวนผู้เข้าสอบ/เก้าอี้ทั้งหมด {{x.seat_create_total_seat}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.scss b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.spec.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.spec.ts new file mode 100644 index 0000000..bf94dea --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckCandidateTestingListComponent } from './check-candidate-testing-list.component'; + +describe('CheckCandidateTestingListComponent', () => { + let component: CheckCandidateTestingListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CheckCandidateTestingListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckCandidateTestingListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.ts b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.ts new file mode 100644 index 0000000..099efe7 --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/presenter/check-candidate-testing-list/check-candidate-testing-list.component.ts @@ -0,0 +1,54 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {tap} from 'rxjs/operators'; +import {BaseList} from '../../../../../core/base/base-list'; + +@Component({ + selector: 'app-check-candidate-testing-list', + templateUrl: './check-candidate-testing-list.component.html', + styleUrls: ['./check-candidate-testing-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateTestingListComponent extends BaseList implements OnInit, OnChanges { + + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'total_register', + 'total_have_exam_total_register', + 'seat_create_total_seat', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + 'created_datetime', + '7' + ]; + @Output() view = new EventEmitter(); + @Input() testingInformationList: any = []; + reload: boolean; + + constructor() { + super(); + } + + ngOnInit(): void { + this.getEventPage().pipe( + tap(x => this.onPaginatorPageChange.emit(x)), + tap(x => { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + }), + ).subscribe() + } + + ngOnChanges() { + this.testingInformationList = this.updatePagingMatabe(this.testingInformationList ? this.testingInformationList : []); + } + + onView(id) { + this.view.emit(id); + } + +} diff --git a/src/app/feature/candidate-list/check-candidate-list/router/check-candidate-list-router.ts b/src/app/feature/candidate-list/check-candidate-list/router/check-candidate-list-router.ts new file mode 100644 index 0000000..5dd7c5c --- /dev/null +++ b/src/app/feature/candidate-list/check-candidate-list/router/check-candidate-list-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CheckCandidateListRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.html b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.html new file mode 100644 index 0000000..5c10eb9 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.scss b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.spec.ts b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.spec.ts new file mode 100644 index 0000000..ef0a839 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeTestInformationContainer } from './seat-change-test-information.container'; + +describe('SeatChangeTestInformationContainer', () => { + let component: SeatChangeTestInformationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeTestInformationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeTestInformationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.ts b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.ts new file mode 100644 index 0000000..f11d216 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change-test-information/seat-change-test-information.container.ts @@ -0,0 +1,33 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from "rxjs"; +import {TestingInformationService} from "../../../../../core/service/testing-information/testing-information.service"; +import {Router} from "@angular/router"; + +@Component({ + selector: 'app-seat-change-test-information', + templateUrl: './seat-change-test-information.container.html', + styleUrls: ['./seat-change-test-information.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeTestInformationContainer implements OnInit { + subjectList$ = new Observable(); + constructor( + private testinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private router: Router, + ) { } + + ngOnInit(): void { + this.subjectList$ = this.testinforSV.search(`?is_open=true`); + } + + search(query){ + if(query) return this.subjectList$ = this.testinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.testinforSV.search(`?is_open=true`); + } + + view(id){ + this.router.navigate(['seat-change/view', id]); + } + +} diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.html b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.html new file mode 100644 index 0000000..86e8dff --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.html @@ -0,0 +1,14 @@ + + diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.scss b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.spec.ts b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.spec.ts new file mode 100644 index 0000000..d2453e0 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeContainer } from './seat-change.container'; + +describe('SeatChangeContainer', () => { + let component: SeatChangeContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.ts b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.ts new file mode 100644 index 0000000..39f73c0 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/container/seat-change/seat-change.container.ts @@ -0,0 +1,89 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {concatMap, tap} from "rxjs/operators"; +import {ActivatedRoute, Router} from "@angular/router"; +import {VEligibleCandidatesService} from "../../../../../core/service/testing-register/v-eligible-candidates.service"; +import {SubjectsService} from "../../../../../core/service/settings/subjects.service"; +import {BranchService} from "../../../../../core/service/settings/branch.service"; +import {TestingFieldService} from "../../../../../core/service/settings/testing-field.service"; +import {TestingCenterService} from "../../../../../core/service/TestingCenter/testing-center.service"; +import {MatDialog} from "@angular/material/dialog"; +import {Observable} from "rxjs"; +import {DialogSyncComponent} from "../../../candidate-list/presenter/dialog/dialog-sync/dialog-sync.component"; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-seat-change', + templateUrl: './seat-change.container.html', + styleUrls: ['./seat-change.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeContainer implements OnInit { + testinginformationuid; + subjectList2 = []; + subjectList = []; + subjectList1$ = new Observable(); + subjectList3 = []; + subjectList4 = []; + testingInfoData; + constructor( + private router: Router, + public activeRouter: ActivatedRoute, + private VECandidateSV: VEligibleCandidatesService, + private subjectSV: SubjectsService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private testcenterSV: TestingCenterService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private testingInfoSV: TestingInformationService + ) { } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => this.testinginformationuid = x.id), + tap(x => { + this.subjectList1$ = this.VECandidateSV.getAllByTestinUid(x.id); + }), + concatMap(x => this.testingInfoSV.get(this.testinginformationuid)), + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + this.subjectSV.getAll().subscribe( + result => this.subjectList4 = result + ); + this.branchSV.getAll().subscribe( + result => this.subjectList = result + ); + this.testingFieldSV.getAll().subscribe( + result => { + this.subjectList2 = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => this.subjectList3 = result + ); + } + + search(query){ + query += `&testing_information_uid=${this.testinginformationuid}`; + if(query) return this.subjectList1$ = this.VECandidateSV.search(`?${query}`); + if(!query) return this.subjectList1$ = this.VECandidateSV.getAllByTestinUid(this.testinginformationuid); + } + + syncData(data){ + // console.log(id); + const dialogRef = this.dialog.open(DialogSyncComponent, { + width: '500px', + height: '340px', + }); + dialogRef.afterClosed().pipe( + tap(x => { + this.VECandidateSV.getAll().pipe( + tap(y => this.subjectList1$ = this.VECandidateSV.getAll()), + tap(y => this.cdr.detectChanges()) + ).subscribe(); + }), + ).subscribe(); + } + +} diff --git a/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.html b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.html new file mode 100644 index 0000000..60e3a4c --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.html @@ -0,0 +1,81 @@ +
+

ค้นหาห้องว่าง

+
+
+
+ + + + + + +
+
+ + + + + + + + + +
+
+ + +
+ +
+ +
+
+
+
+

แสดงผลรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} เวลา {{x.start_time}} คาบ {{x.period_id}} + +
+ +
diff --git a/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.scss b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.spec.ts b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.spec.ts new file mode 100644 index 0000000..bc2f96d --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamDayDialogComponent } from './change-exam-day-dialog.component'; + +describe('ChangeExamDayDialogComponent', () => { + let component: ChangeExamDayDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamDayDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamDayDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.ts b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.ts new file mode 100644 index 0000000..c6f3f8a --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/change-exam-day-dialog/change-exam-day-dialog.component.ts @@ -0,0 +1,110 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatGridTileHeaderCssMatStyler } from '@angular/material/grid-list'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { ChangeTestingRoomAndDateService } from 'src/app/core/service/testing-register/change-testing-room-and-date.service'; +import { CheckAvailableRoomAndPeriodService } from 'src/app/core/service/testing-register/check-available-room-and-period.service'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +@Component({ + selector: 'app-change-exam-day-dialog', + templateUrl: './change-exam-day-dialog.component.html', + styleUrls: ['./change-exam-day-dialog.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamDayDialogComponent extends BaseList implements OnInit { + seatLists: any = []; + testingDate; + query = { + testing_room_code: '', + period_id: '', + }; + PeriodLists: any = []; + RoomLists: any = []; + testingInfoData; + currentDate = new Date() + constructor( + public dialogRef: MatDialogRef, + private fb: FormBuilder, + private testInforSV: TestingInformationService, + private swSV: SweetalertService, + private checkAvlRoomAndPeriodSV: CheckAvailableRoomAndPeriodService, + @Inject(MAT_DIALOG_DATA) public data, + private cdr: ChangeDetectorRef, + private changeTestingRoomAndDateSV: ChangeTestingRoomAndDateService + ) { + super() + } + + ngOnInit(): void { + // console.log(this.data.data.testing_information_uid) + this.testInforSV.get(this.data.data.testing_information_uid).pipe( + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + + search(){ + if (this.testingDate != null){ + // const date = formatDate(this.query.testing_date, 'yyyy-MM-dd', 'en-US'); + this.testingDate = formatDate(this.testingDate, 'yyyy-MM-dd', 'en-US'); + if (this.query.period_id != null || this.query.testing_room_code != null){ + const query = createQueryStringFromObject(this.query); + this.checkAvlRoomAndPeriodSV.checkAvalroomWithQuery(this.data.data,query,this.testingDate).pipe( + tap((x:any) => { + if(x.length == 0){ + this.swSV.errText('ไม่มีห้องในวันที่ค้นหา') + }else{ + this.seatLists = []; + this.seatLists = this.updateMatTable(x); + this.cdr.detectChanges(); + } + }) + ).subscribe(); + }else { + this.checkAvlRoomAndPeriodSV.checkAvalroom(this.data.data).pipe( + tap((x:any) => { + if(x.length == 0){ + this.swSV.errText('ไม่มีห้องในวันที่ค้นหา') + }else{ + this.seatLists = []; + this.seatLists = this.updateMatTable(x); + this.cdr.detectChanges(); + } + }) + ).subscribe(); + } + }else { + return this.swSV.errText('กรุณาใส่วันที่') + } + + } + + select(data){ + const date = formatDate(this.testingDate, 'yyyy-MM-dd', 'en-US'); + const obj = { + testing_information_uid : this.data.data.testing_information_uid, + testing_register_uid: this.data.data.testing_register_uid, + testing_subject_selected_uid: this.data.data.testing_subject_selected_uid, + new_branch_uid: data.branch_uid, + new_testing_field_uid: data.testing_field_uid, + new_testing_center_uid: data.testing_center_uid, + new_testing_date: date, + new_period_id: data.period_id + } + this.changeTestingRoomAndDateSV.changeRoomAndDate(obj).pipe( + tap(x => this.swSV.saveSuccess('ย้ายวันที่สอบสำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.html b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.html new file mode 100644 index 0000000..23a1478 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.html @@ -0,0 +1,96 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.scss b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.spec.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.spec.ts new file mode 100644 index 0000000..2612aaf --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeTestInformationListComponent } from './seat-change-test-information-list.component'; + +describe('SeatChangeTestInformationListComponent', () => { + let component: SeatChangeTestInformationListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeTestInformationListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeTestInformationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.ts new file mode 100644 index 0000000..541d45f --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component.ts @@ -0,0 +1,29 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-seat-change-test-information-list', + templateUrl: './seat-change-test-information-list.component.html', + styleUrls: ['./seat-change-test-information-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeTestInformationListComponent extends BaseList implements OnInit, OnChanges { + column = ['1', '0', '2', '3', '4', '8', '9', '10', '5', '6', '7']; + @Output() view = new EventEmitter(); + @Input() subjectList: any = []; + constructor(){ + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onView(id){ + this.view.emit(id); + } + +} diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.html b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.scss b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.spec.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.spec.ts new file mode 100644 index 0000000..a4689d8 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeTestInformationSearchComponent } from './seat-change-test-information-search.component'; + +describe('SeatChangeTestInformationSearchComponent', () => { + let component: SeatChangeTestInformationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeTestInformationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeTestInformationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.ts new file mode 100644 index 0000000..d47d72f --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component.ts @@ -0,0 +1,50 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../../shared/util/func'; + +@Component({ + selector: 'app-seat-change-test-information-search', + templateUrl: './seat-change-test-information-search.component.html', + styleUrls: ['./seat-change-test-information-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeTestInformationSearchComponent implements OnInit { + + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + } + +} diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.html b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.html new file mode 100644 index 0000000..9ca84b7 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.html @@ -0,0 +1,65 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เลขที่นั่งสอบ + {{x.testing_seat}} + + รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล {{x.examinee_full_name}} ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} รหัสวิชาที่สอบ {{x.subject_code}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} ({{x.start_time}}) สถานะ {{x.test_status_name}} ย้ายวันสอบ + +
+ +
+
+
diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.scss b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.spec.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.spec.ts new file mode 100644 index 0000000..8eb28b0 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeListComponent } from './seat-change-list.component'; + +describe('SeatChangeListComponent', () => { + let component: SeatChangeListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.ts new file mode 100644 index 0000000..965817d --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/list/seat-change-list/seat-change-list.component.ts @@ -0,0 +1,106 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, ChangeDetectorRef} from '@angular/core'; +import {BaseList} from "../../../../../../../core/base/base-list"; +import {ActivatedRoute, Router} from "@angular/router"; +import {MatDialog} from "@angular/material/dialog"; +import { + VEligibleCandidatesService +} from "../../../../../../../core/service/testing-register/v-eligible-candidates.service"; +import { + DialogChangeSeatComponent +} from "../../../../../candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component"; +import {switchMap, tap} from "rxjs/operators"; +import { + DialogChangeRoomComponent +} from "../../../../../candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component"; +import { ChangeExamDayDialogComponent } from '../../../change-exam-day-dialog/change-exam-day-dialog.component'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; + +@Component({ + selector: 'app-seat-change-list', + templateUrl: './seat-change-list.component.html', + styleUrls: ['./seat-change-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeListComponent extends BaseList implements OnInit, OnChanges { + @Input() testingInfoData:any ; + @Input() subjectList: any = []; + column = ['1', '2', '3', '4', '5', '6', '7', '8', '9','10', '11']; + constructor( + private router: Router, + public activeRouter: ActivatedRoute, + private dialog: MatDialog, + private cdf: ChangeDetectorRef, + private VECandidateSV: VEligibleCandidatesService + ) { + super(); + } + + ngOnInit(): void { + + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + isAvailable(data){ + const noShowStatusArray = ['03','04','06','10','13'] + if(!data.test_status_code) return true + if(noShowStatusArray.some(x => x == data.test_status_code)) return false + return true + } + + openDialog(id){ + const dialogRef = this.dialog.open(DialogChangeSeatComponent, { + width: '500px', + height: '460px', + data: id + }); + dialogRef.afterClosed().pipe( + switchMap(x => { + return this.VECandidateSV.getAllByTestinUid(this.testingInfoData.testing_information_uid).pipe( + tap(x => this.subjectList.data = x), + tap(x => this.cdf.detectChanges()) + ) + }) + ).subscribe(); + } + + openDialogChangeRoom(id){ + const dialogRef = this.dialog.open(DialogChangeRoomComponent, { + width: '500px', + height: '400px', + data: id + }); + dialogRef.afterClosed().pipe( + switchMap(x => { + return this.VECandidateSV.getAllByTestinUid(this.testingInfoData.testing_information_uid).pipe( + tap(x => this.subjectList.data = x), + tap(x => this.cdf.detectChanges()) + ) + }) + ).subscribe(); + } + + changeExamDay(data){ + console.log(data) + const obj = { + data: data, + information: this.testingInfoData + } + const dialogRef = this.dialog.open(ChangeExamDayDialogComponent, { + width: '800px', + height: '600px', + data: obj + }); + dialogRef.afterClosed().pipe( + switchMap(x => { + return this.VECandidateSV.getAllByTestinUid(this.testingInfoData.testing_information_uid).pipe( + tap(x => this.subjectList.data = x), + tap(x => this.cdf.detectChanges()) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.html b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.html new file mode 100644 index 0000000..aeb9b7c --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.html @@ -0,0 +1,105 @@ +

ค้นหารายชื่อนักศึกษาสำหรับย้ายที่นั่งสอบในรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + + +
+ +
+ + + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_field_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.testing_room_name_th}} + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+
+ + + diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.scss b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.spec.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.spec.ts new file mode 100644 index 0000000..35efd0a --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SeatChangeSearchComponent } from './seat-change-search.component'; + +describe('SeatChangeSearchComponent', () => { + let component: SeatChangeSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SeatChangeSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SeatChangeSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.ts b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.ts new file mode 100644 index 0000000..c2c452f --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/presenter/seat-change/search/seat-change-search/seat-change-search.component.ts @@ -0,0 +1,134 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges, SimpleChanges} from '@angular/core'; +import {TestingCenterService} from "../../../../../../../core/service/TestingCenter/testing-center.service"; +import {TestingFieldService} from "../../../../../../../core/service/settings/testing-field.service"; +import {createQueryStringFromObject} from "../../../../../../../shared/util/func"; +import {tap} from "rxjs/operators"; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-seat-change-search', + templateUrl: './seat-change-search.component.html', + styleUrls: ['./seat-change-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeSearchComponent implements OnInit,OnChanges { + + @Input() subjectList2: any = []; + @Input() subjectList: any = []; + @Input() subjectList1: any = []; + @Input() subjectList3: any = []; + @Input() subjectList4: any = []; + @Input() testingInfoData: any; + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + branchList: any = []; + testingFieldList: any = []; + filteredTestingFieldList: any = []; + filteredRoomList: any = []; + roomList: any = []; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + constructor( + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + ) { } + query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null + }; + ngOnInit(): void { + + } + + ngOnChanges(): void { + this.branchList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.branch_name_th === value.branch_name_th) === index) + this.roomList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_room_name_th === value.testing_room_name_th) === index) + this.testingFieldList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_field_name_th === value.testing_field_name_th) === index) + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + if (this.query.testing_datetime != null){ + this.query.testing_datetime = formatDate(this.query.testing_datetime, 'yyyy-MM-dd', 'en-US'); + } + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + displayTestInfor(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_subjects.find(x => x.subject_uid === uid)?.subject_code + } + + displayBrand(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.branch_uid === uid)?.branch_name_th + } + + displayField(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.testing_field_uid === uid)?.testing_field_name_th + } + + displayCenter(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.testing_center_uid === uid)?.testing_room_name_th + } + + filterTestingField(data){ + this.filteredTestingFieldList = [] + this.filteredTestingFieldList = this.branchList.filter(x => data.branch_uid == x.branch_uid) + } + + setRoom(data){ + this.filteredRoomList = this.roomList.filter(x => (x.branch_uid == data.branch_uid)&&(x.testing_field_uid == data.testing_field_uid)) + } + + clear(){ + this.query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null + }; + this.onSearch() + } + + +} diff --git a/src/app/feature/candidate-list/seat-change/router/seat-change-router.ts b/src/app/feature/candidate-list/seat-change/router/seat-change-router.ts new file mode 100644 index 0000000..ffa19e5 --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/router/seat-change-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SeatChangeRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/candidate-list/seat-change/seat-change.module.ts b/src/app/feature/candidate-list/seat-change/seat-change.module.ts new file mode 100644 index 0000000..dea06fe --- /dev/null +++ b/src/app/feature/candidate-list/seat-change/seat-change.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SeatChangeRouter } from './router/seat-change-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SeatChangeContainer } from './container/seat-change/seat-change.container'; +import { SeatChangeTestInformationContainer } from './container/seat-change-test-information/seat-change-test-information.container'; +import { SeatChangeListComponent } from './presenter/seat-change/list/seat-change-list/seat-change-list.component'; +import { SeatChangeSearchComponent } from './presenter/seat-change/search/seat-change-search/seat-change-search.component'; +import { SeatChangeTestInformationListComponent } from './presenter/seat-change-test-information/list/seat-change-test-information-list/seat-change-test-information-list.component'; +import { SeatChangeTestInformationSearchComponent } from './presenter/seat-change-test-information/search/seat-change-test-information-search/seat-change-test-information-search.component'; +import { ChangeExamDayDialogComponent } from './presenter/change-exam-day-dialog/change-exam-day-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: SeatChangeRouter, + children: [ + { + path: 'view/:id', + component: SeatChangeContainer + }, + { + path: '', + component: SeatChangeTestInformationContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + SeatChangeRouter, + SeatChangeContainer, + SeatChangeTestInformationContainer, + SeatChangeListComponent, + SeatChangeSearchComponent, + SeatChangeTestInformationListComponent, + SeatChangeTestInformationSearchComponent, + ChangeExamDayDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class SeatChangeModule { } diff --git a/src/app/feature/candidate-payment-status/candidate-payment-status.module.ts b/src/app/feature/candidate-payment-status/candidate-payment-status.module.ts new file mode 100644 index 0000000..fe4677e --- /dev/null +++ b/src/app/feature/candidate-payment-status/candidate-payment-status.module.ts @@ -0,0 +1,47 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CandidatePaymentStatusRouter } from './router/router'; +import { CandidatePaymentStatusContainer } from './container/candidate-payment-status/candidate-payment-status.container'; +import { ListComponent } from './presenter/list/list.component'; +import { SearchComponent } from './presenter/search/search.component'; +import { TestingInfoListComponent } from './presenter/testing-info-list/testing-info-list.component'; +import { TestingInfoSearchComponent } from './presenter/testing-info-search/testing-info-search.component'; +import { TestingInfoContainer } from './container/testing-info/testing-info.container'; + + +const routes: Routes = [ + { + path: '', + component: CandidatePaymentStatusRouter, + children: [ + { + path: '', + component: TestingInfoContainer + }, + { + path: 'view/:id', + component: CandidatePaymentStatusContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + CandidatePaymentStatusContainer, + CandidatePaymentStatusRouter, + ListComponent, + SearchComponent, + TestingInfoListComponent, + TestingInfoSearchComponent, + TestingInfoContainer +], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CandidatePaymentStatusModule {} diff --git a/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.html b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.html new file mode 100644 index 0000000..5bc6e49 --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.html @@ -0,0 +1,5 @@ + + + diff --git a/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.scss b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.spec.ts b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.spec.ts new file mode 100644 index 0000000..3f58d2a --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CandidatePaymentStatusContainer } from './candidate-payment-status.container'; + +describe('CandidatePaymentStatusContainer', () => { + let component: CandidatePaymentStatusContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CandidatePaymentStatusContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CandidatePaymentStatusContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.ts b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.ts new file mode 100644 index 0000000..ff3ad74 --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/candidate-payment-status/candidate-payment-status.container.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; +import { concatMap, tap } from 'rxjs/operators'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { CandidatePaymentStatusService } from 'src/app/core/service/testing-register/candidate-payment-status.service'; + +@Component({ + selector: 'app-candidate-payment-status', + templateUrl: './candidate-payment-status.container.html', + styleUrls: ['./candidate-payment-status.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidatePaymentStatusContainer implements OnInit { + uid; + testingInfoData; + candidateList$ = new Observable() + constructor( + private activatedRoute: ActivatedRoute, + private candidatePaymentStatus: CandidatePaymentStatusService, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.activatedRoute.params.pipe( + tap(x => this.uid = x.id), + tap(x => { + this.candidateList$ = this.candidatePaymentStatus.search(`?testing_information_uid=${x.id}`); + }), + concatMap(x => this.testingInformationSV.get(this.uid)), + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + search(query){ + if(query) return this.candidateList$ = this.candidatePaymentStatus.search(`?${query}`); + if(!query) return this.candidateList$ = this.candidatePaymentStatus.search(`?testing_information_uid=${this.uid}`); + } + +} diff --git a/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.html b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.html new file mode 100644 index 0000000..b378440 --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.html @@ -0,0 +1,8 @@ + + + + diff --git a/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.scss b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.spec.ts b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.spec.ts new file mode 100644 index 0000000..b60933a --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoContainer } from './testing-info.container'; + +describe('TestingInfoContainer', () => { + let component: TestingInfoContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.ts b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.ts new file mode 100644 index 0000000..30e93ee --- /dev/null +++ b/src/app/feature/candidate-payment-status/container/testing-info/testing-info.container.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-testing-info', + templateUrl: './testing-info.container.html', + styleUrls: ['./testing-info.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoContainer implements OnInit { + academicYear$ = new Observable() + testingInfo$ = new Observable() + constructor( + private testingInfoSV: TestingInformationService, + private academicYearSV: AcademicYearService, + private router: Router + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfoSV.search(`?is_open=true`); + this.academicYear$ = this.academicYearSV.getAll() + } + + view(id){ + this.router.navigate(['candidate-payment-status/view', id]); + } + + search(query){ + if(query) return this.testingInfo$ = this.testingInfoSV.search(`?${query}`); + if(!query) return this.testingInfo$ = this.testingInfoSV.search(`?is_open=true`); + } + +} diff --git a/src/app/feature/candidate-payment-status/presenter/list/list.component.html b/src/app/feature/candidate-payment-status/presenter/list/list.component.html new file mode 100644 index 0000000..da2b9a6 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/list/list.component.html @@ -0,0 +1,58 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสผู้สอบ {{x.student_code}} ชื่อ-นามสกุล {{x.examinee_full_name}} ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} ที่นั่งสอบ {{x.testing_seat}} รหัสวิชาที่สอบ {{x.subject_code}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} ({{x.start_time}}) สถานะการชำระเงิน + {{x.payment_status}} +
+ +
+
+
diff --git a/src/app/feature/candidate-payment-status/presenter/list/list.component.scss b/src/app/feature/candidate-payment-status/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/presenter/list/list.component.spec.ts b/src/app/feature/candidate-payment-status/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/presenter/list/list.component.ts b/src/app/feature/candidate-payment-status/presenter/list/list.component.ts new file mode 100644 index 0000000..8c456d8 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/list/list.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Router, ActivatedRoute } from '@angular/router'; +import { tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { VEligibleCandidatesService } from 'src/app/core/service/testing-register/v-eligible-candidates.service'; +import { DialogChangeRoomComponent } from 'src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component'; +import { DialogChangeSeatComponent } from 'src/app/feature/candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit, OnChanges { + @Input() candidateList: any = []; + constructor( + private router: Router, + public activeRouter: ActivatedRoute, + private dialog: MatDialog, + private cdf: ChangeDetectorRef, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.candidateList = this.updateMatTable(this.candidateList ? this.candidateList : []); + } + +} diff --git a/src/app/feature/candidate-payment-status/presenter/search/search.component.html b/src/app/feature/candidate-payment-status/presenter/search/search.component.html new file mode 100644 index 0000000..3e3f84c --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/search/search.component.html @@ -0,0 +1,105 @@ +

ค้นหารายชื่อนักศึกษาสำหรับตรวจสอบสถานะการชำระค่าสมัคร {{testingInfoData?.testing_information_name}}

+
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + + +
+ +
+ + + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_field_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.testing_room_name_th}} + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+
+ + + diff --git a/src/app/feature/candidate-payment-status/presenter/search/search.component.scss b/src/app/feature/candidate-payment-status/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/presenter/search/search.component.spec.ts b/src/app/feature/candidate-payment-status/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/presenter/search/search.component.ts b/src/app/feature/candidate-payment-status/presenter/search/search.component.ts new file mode 100644 index 0000000..2750e0f --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/search/search.component.ts @@ -0,0 +1,98 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { TestingFieldService } from 'src/app/core/service/settings/testing-field.service'; +import { TestingCenterService } from 'src/app/core/service/TestingCenter/testing-center.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit,OnChanges { + + @Input() testingInfoData: any; + @Output() search = new EventEmitter(); + branchList: any = []; + testingFieldList: any = []; + filteredTestingFieldList: any = []; + filteredRoomList: any = []; + roomList: any = []; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null, + testing_information_uid: null + }; + constructor( + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + ) { } + + ngOnInit(): void { + + } + + ngOnChanges(): void { + this.query.testing_information_uid = this.testingInfoData.testing_information_uid + this.branchList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.branch_name_th === value.branch_name_th) === index) + this.roomList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_room_name_th === value.testing_room_name_th) === index) + this.testingFieldList = this.testingInfoData?.testing_rooms.filter((value,index,self) => self.findIndex(selfValue => selfValue.testing_field_name_th === value.testing_field_name_th) === index) + } + + + onSearch(){ + if (this.query.testing_datetime != null){ + this.query.testing_datetime = formatDate(this.query.testing_datetime, 'yyyy-MM-dd', 'en-US'); + } + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + displayTestInfor(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_subjects.find(x => x.subject_uid === uid)?.subject_code + } + + displayBrand(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.branch_uid === uid)?.branch_name_th + } + + displayField(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.testing_field_uid === uid)?.testing_field_name_th + } + + displayCenter(uid){ + if (uid && this.testingInfoData) return this.testingInfoData.testing_rooms.find(x => x.testing_center_uid === uid)?.testing_room_name_th + } + + filterTestingField(data){ + this.filteredTestingFieldList = [] + this.filteredTestingFieldList = this.branchList.filter(x => data.branch_uid == x.branch_uid) + } + + setRoom(data){ + this.filteredRoomList = this.roomList.filter(x => (x.branch_uid == data.branch_uid)&&(x.testing_field_uid == data.testing_field_uid)) + } + + clear(){ + this.query = { + subject_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + student_code: null, + testing_information_uid: this.testingInfoData.testing_information_uid + }; + this.onSearch() + } + + +} diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.html b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.html new file mode 100644 index 0000000..36c0a28 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.html @@ -0,0 +1,96 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.scss b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.spec.ts b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.spec.ts new file mode 100644 index 0000000..96cc780 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoListComponent } from './testing-info-list.component'; + +describe('TestingInfoListComponent', () => { + let component: TestingInfoListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.ts b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.ts new file mode 100644 index 0000000..9df7548 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-list/testing-info-list.component.ts @@ -0,0 +1,30 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; +import { OBJECT } from 'src/app/core/enum/role'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; + +@Component({ + selector: 'app-testing-info-list', + templateUrl: './testing-info-list.component.html', + styleUrls: ['./testing-info-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoListComponent extends BaseList implements OnInit, OnChanges { + @Input() testingInfoList: any = []; + role = []; + roleConfig = OBJECT; + @Output() view = new EventEmitter(); + column = ['1', '0', '2', '3', '4', '8', '9', '10', '5', '6', '7']; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + } + ngOnChanges(){ + this.testingInfoList = this.updateMatTable(this.testingInfoList ? this.testingInfoList : []); + } +} diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.html b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.scss b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.spec.ts b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.spec.ts new file mode 100644 index 0000000..76f66b8 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoSearchComponent } from './testing-info-search.component'; + +describe('TestingInfoSearchComponent', () => { + let component: TestingInfoSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.ts b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.ts new file mode 100644 index 0000000..df7e382 --- /dev/null +++ b/src/app/feature/candidate-payment-status/presenter/testing-info-search/testing-info-search.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, Input } from '@angular/core'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-testing-info-search', + templateUrl: './testing-info-search.component.html', + styleUrls: ['./testing-info-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + @Input() academicYearList: any = []; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + constructor() { } + + ngOnInit(): void { + + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + } + +} diff --git a/src/app/feature/candidate-payment-status/router/router.ts b/src/app/feature/candidate-payment-status/router/router.ts new file mode 100644 index 0000000..2592deb --- /dev/null +++ b/src/app/feature/candidate-payment-status/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CandidatePaymentStatusRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/change-exam-day/change-exam-day.module.ts b/src/app/feature/change-exam-day/change-exam-day.module.ts new file mode 100644 index 0000000..b3a4fc4 --- /dev/null +++ b/src/app/feature/change-exam-day/change-exam-day.module.ts @@ -0,0 +1,44 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ChangeExamDayRouter } from './router/router'; +import { ChangeExamDayContainer } from './container/change-exam-day/change-exam-day.container'; +import { ListComponent } from './presenter/list/list/list.component'; +import { AlrdyListComponent } from './presenter/alrdy-list/alrdy-list/alrdy-list.component'; +import { EmptyListComponent } from './presenter/empty-list/empty-list/empty-list.component'; +import { WaitListComponent } from './presenter/wait-list/wait-list/wait-list.component'; +import { ReasonDialogComponent } from './presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component'; +import { ChangeDialogComponent } from './presenter/dialog/change-dialog/change-dialog/change-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: ChangeExamDayRouter, + children: [ + { + path: '', + component: ChangeExamDayContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ChangeExamDayContainer, + ChangeExamDayRouter, + ListComponent, + AlrdyListComponent, + EmptyListComponent, + WaitListComponent, + ReasonDialogComponent, + ChangeDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ChangeExamDayModule {} diff --git a/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.html b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.html new file mode 100644 index 0000000..abf43e6 --- /dev/null +++ b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.scss b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.spec.ts b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.spec.ts new file mode 100644 index 0000000..bd2b89d --- /dev/null +++ b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamDayContainer } from './change-exam-day.container'; + +describe('ChangeExamDayContainer', () => { + let component: ChangeExamDayContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamDayContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamDayContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.ts b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.ts new file mode 100644 index 0000000..a6e934d --- /dev/null +++ b/src/app/feature/change-exam-day/container/change-exam-day/change-exam-day.container.ts @@ -0,0 +1,39 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ChangeTestingDateService } from 'src/app/core/service/testing-register/change-testing-date.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-change-exam-day', + templateUrl: './change-exam-day.container.html', + styleUrls: ['./change-exam-day.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamDayContainer implements OnInit { + emptyList$ = new Observable() + waitList$ = new Observable() + alrdyList$ = new Observable() + curindex = 0; + constructor( + private changeSV: ChangeTestingDateService + ) { } + + ngOnInit(): void { + this.waitList$ = this.changeSV.search(`?seat_status_id=4`) + this.alrdyList$ = this.changeSV.search(`?seat_status_id=2`) + this.emptyList$ = this.changeSV.search(`?seat_status_id=3`) + } + + index(index){ + this.curindex = index + // console.log(this.curindex) + } + + search(query){ + const data = createQueryStringFromObject(query) + if(this.curindex == 0) return this.waitList$ = this.changeSV.search(`?${data}&seat_status_id=4`) + if(this.curindex == 1) return this.alrdyList$ = this.changeSV.search(`?${data}&seat_status_id=2`) + if(this.curindex == 2) return this.emptyList$ = this.changeSV.search(`?${data}&seat_status_id=3`) + } + +} diff --git a/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.html b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.html new file mode 100644 index 0000000..2288bf0 --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.html @@ -0,0 +1,62 @@ +
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล {{x.full_name}} ศูนย์สอบ {{x.branch_name_th}} รหัสวิชาสอบ {{x.subject_code}} วันสอบเดิม {{x.testing_datetime | thaidate}} Section เดิม {{x.period_id}} ({{x.start_time}}) + วันที่ขอสอบใหม่ + {{x.new_testing_datetime}} + Section + {{x.new_period_id}} ({{x.new_start_time}}) + ที่นั่งสอบ + + {{x.seat_no}} + สาเหตุ +
+ find_in_page +
+
+ +
+
diff --git a/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.scss b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.spec.ts b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.spec.ts new file mode 100644 index 0000000..e1a413b --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AlrdyListComponent } from './alrdy-list.component'; + +describe('AlrdyListComponent', () => { + let component: AlrdyListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AlrdyListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AlrdyListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.ts b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.ts new file mode 100644 index 0000000..c86d5a9 --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/alrdy-list/alrdy-list/alrdy-list.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, OnChanges, Input } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { BaseList } from 'src/app/core/base/base-list'; +import { ReasonDialogComponent } from '../../dialog/reason-dialog/reason-dialog/reason-dialog.component'; + +@Component({ + selector: 'alrdy-list', + templateUrl: './alrdy-list.component.html', + styleUrls: ['./alrdy-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AlrdyListComponent extends BaseList implements OnInit,OnChanges { + list; + @Input() aldyList : any = []; + column = ['1','2','3','4','5','6','7','8','9','10'] + constructor( + private dialog: MatDialog + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.aldyList = this.updateMatTable(this.aldyList? this.aldyList:[]) + } + + reason(x){ + const dialogRef = this.dialog.open(ReasonDialogComponent, { + width: '90vh', + data: x, + }); + } + +} diff --git a/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.html b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.html new file mode 100644 index 0000000..3e1770e --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.html @@ -0,0 +1,42 @@ +
+
+
+

ห้องสอบที่สามารถเปลี่ยนได้

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ diff --git a/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.scss b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.spec.ts b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.spec.ts new file mode 100644 index 0000000..28f1bed --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeDialogComponent } from './change-dialog.component'; + +describe('ChangeDialogComponent', () => { + let component: ChangeDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.ts b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.ts new file mode 100644 index 0000000..929dd5b --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/change-dialog/change-dialog/change-dialog.component.ts @@ -0,0 +1,79 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { ChangeTestingDateService } from 'src/app/core/service/testing-register/change-testing-date.service'; +import { CheckAvailableRoomService } from 'src/app/core/service/testing-register/check-available-room.service'; +import { CheckAvailableSeatService } from 'src/app/core/service/testing-register/check-available-seat.service'; +import {CheckAvailableRoomNoConditionService} from "../../../../../../core/service/testing-register/check-available-room-no-condition.service"; + +@Component({ + selector: 'app-change-dialog', + templateUrl: './change-dialog.component.html', + styleUrls: ['./change-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeDialogComponent implements OnInit { + room; + seat; + form; + constructor( + private changeTestingDateSV: ChangeTestingDateService, + private fb: FormBuilder, + private cdr: ChangeDetectorRef, + private checkAvalSV: CheckAvailableSeatService, + private checkAvaRoomNoConditionSV: CheckAvailableRoomNoConditionService, + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private swSV: SweetalertService + ) { + this.form = this.fb.group({ + manage_testing_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: [null,Validators.required], + testing_seat: [null,Validators.required] + }) + } + + ngOnInit(): void { + this.checkAvalSV.checkAval(this.data).pipe( + tap(x => this.seat = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.checkAvaRoomNoConditionSV.checkAvalroom(this.data).pipe( + tap(x => this.room = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.form.get('testing_field_uid').setValue(this.data.testing_field_uid) + this.form.get('branch_uid').setValue(this.data.branch_uid) + this.form.get('manage_testing_uid').setValue(this.data.manage_testing_uid) + } + + confirm(){ + const form = this.form.getRawValue() + this.changeTestingDateSV.approve(form).pipe( + tap(x => this.swSV.success('อนุมัติสำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText('อนุมัติไม่สำเร็จ') + return throwError(err) + }) + ).subscribe() + } + + cancel(){ + this.changeTestingDateSV.reject(this.data.manage_testing_uid).pipe( + tap(x => this.swSV.success('ไม่อนุมัติสำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText('มีข้อผิดพลาดในการไม่อนุมัติ') + return throwError(err) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.html b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.html new file mode 100644 index 0000000..13f39ed --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.html @@ -0,0 +1,12 @@ +

เหตุผลในการเปลี่ยนวันสอบ

+
+ +
+

เอกสารแนบ

+
+ +
+ search +
+
+ diff --git a/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.scss b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.spec.ts b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.spec.ts new file mode 100644 index 0000000..11c247d --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReasonDialogComponent } from './reason-dialog.component'; + +describe('ReasonDialogComponent', () => { + let component: ReasonDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReasonDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReasonDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.ts b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.ts new file mode 100644 index 0000000..85752d5 --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/dialog/reason-dialog/reason-dialog/reason-dialog.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { BaseTiny } from 'src/app/core/base/tinymce'; + +@Component({ + selector: 'app-reason-dialog', + templateUrl: './reason-dialog.component.html', + styleUrls: ['./reason-dialog.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReasonDialogComponent extends BaseTiny implements OnInit { + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + super() + } + + ngOnInit(): void { + // console.log(this.data) + } + + file(){ + window.open(this.data.manage_testing_file) + } + +} diff --git a/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.html b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.html new file mode 100644 index 0000000..5b0945f --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.html @@ -0,0 +1,55 @@ + +
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล {{x.full_name}} ศูนย์สอบ {{x.branch_name_th}} รหัสวิชาสอบ {{x.subject_code}} วันสอบเดิม {{x.testing_datetime | thaidate}} Section เดิม {{x.period_id}} ({{x.start_time}}) + วันที่ขอสอบใหม่ + {{x.new_testing_datetime | thaidate}} + Section + {{x.new_period_id}} ({{x.new_start_time}}) สาเหตุ +
+ find_in_page +
+
+ +
+
diff --git a/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.scss b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.spec.ts b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.spec.ts new file mode 100644 index 0000000..9b54bce --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EmptyListComponent } from './empty-list.component'; + +describe('EmptyListComponent', () => { + let component: EmptyListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EmptyListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EmptyListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.ts b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.ts new file mode 100644 index 0000000..feb56db --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/empty-list/empty-list/empty-list.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ReasonDialogComponent } from '../../dialog/reason-dialog/reason-dialog/reason-dialog.component'; + +@Component({ + selector: 'empty-list', + templateUrl: './empty-list.component.html', + styleUrls: ['./empty-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EmptyListComponent implements OnInit { + list; + @Input() emptyList : any = []; + column = ['1','2','3','4','5','6','7','8','9'] + constructor( + private dialog: MatDialog + ) { } + + ngOnInit(): void { + } + + reason(x){ + const dialogRef = this.dialog.open(ReasonDialogComponent, { + width: '90vh', + data: x, + }); + } + +} diff --git a/src/app/feature/change-exam-day/presenter/list/list/list.component.html b/src/app/feature/change-exam-day/presenter/list/list/list.component.html new file mode 100644 index 0000000..82c03ae --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/list/list/list.component.html @@ -0,0 +1,41 @@ +

รายการนักศึกษาขอเปลี่ยนวันสอบ

+
+
+
+ +
+
+ +   + +
+
+
+
+ + + +
+ รออนุมัติ +
+
+ +
+ + +
+ อนุมัติแล้ว +
+
+ +
+ + +
+ ไม่มีห้องว่าง +
+
+ +
+
+
diff --git a/src/app/feature/change-exam-day/presenter/list/list/list.component.scss b/src/app/feature/change-exam-day/presenter/list/list/list.component.scss new file mode 100644 index 0000000..09d98ab --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/list/list/list.component.scss @@ -0,0 +1,41 @@ +:host ::ng-deep .mat-ink-bar { + display: none !important; +} + +.tab{ + background: #C4C4C4; + border-radius: 6px 6px 0px 0px; + width: 150px; + height: 40px; + margin-top: 10px; + margin-left: -5px; + display: flex; + pointer-events: all; + color: #2D9CDB; +} + + +:host ::ng-deep .mat-tab-label { + height: 48px; + padding: 0 5px !important ; + opacity: 1; + min-width: 150px; + pointer-events: none !important; +} + +:host ::ng-deep .mat-tab-label-active .tab { + color: white; + background: #2D9CDB; +} + +.edit{ + @apply z-10 pr-1 text-center flex items-center justify-center; +} + +.inputname{ + @apply bg-transparent border-none focus:ring-opacity-0 cursor-pointer text-white; +} + +:host ::ng-deep .mat-tab-label:focus { + background-color: transparent !important; +} diff --git a/src/app/feature/change-exam-day/presenter/list/list/list.component.spec.ts b/src/app/feature/change-exam-day/presenter/list/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/list/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/list/list/list.component.ts b/src/app/feature/change-exam-day/presenter/list/list/list.component.ts new file mode 100644 index 0000000..27f62f2 --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/list/list/list.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent implements OnInit { + @Input() waitList: any = []; + @Input() emptyList: any = []; + @Input() aldyList: any = []; + @Output() index = new EventEmitter() + @Output() search = new EventEmitter() + query = { + student_code:null + } + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + this.search.emit(this.query) + } + + clear(){ + this.query = { + student_code: null + } + this.search.emit(this.query) + } + + onTabChanged(index){ + // console.log(index) + this.index.emit(index.index) + } + +} diff --git a/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.html b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.html new file mode 100644 index 0000000..8e76c6f --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.html @@ -0,0 +1,62 @@ +
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล {{x.full_name}} ศูนย์สอบ {{x.branch_name_th}} รหัสวิชาสอบ {{x.subject_code}} วันสอบเดิม {{x.testing_datetime | thaidate}} Section เดิม {{x.period_id}} ({{x.start_time}}) + วันที่ขอสอบใหม่ + {{x.new_testing_datetime | thaidate}} + Section + {{x.new_period_id}} ({{x.new_start_time}}) สาเหตุ +
+ find_in_page +
+
+
+ +
+
+ +
+
diff --git a/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.scss b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.spec.ts b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.spec.ts new file mode 100644 index 0000000..7b0ecd3 --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { WaitListComponent } from './wait-list.component'; + +describe('WaitListComponent', () => { + let component: WaitListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ WaitListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WaitListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.ts b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.ts new file mode 100644 index 0000000..e1cc70e --- /dev/null +++ b/src/app/feature/change-exam-day/presenter/wait-list/wait-list/wait-list.component.ts @@ -0,0 +1,51 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { CheckAvailableSeatService } from 'src/app/core/service/testing-register/check-available-seat.service'; +import { ChangeDialogComponent } from '../../dialog/change-dialog/change-dialog/change-dialog.component'; +import { ReasonDialogComponent } from '../../dialog/reason-dialog/reason-dialog/reason-dialog.component'; + +@Component({ + selector: 'wait-list', + templateUrl: './wait-list.component.html', + styleUrls: ['./wait-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class WaitListComponent extends BaseList implements OnInit,OnChanges { + @Input() waitList: any = []; + list = [1,2,3] + column = ['1','2','3','4','5','6','7','8','9','10'] + constructor( + private dialog: MatDialog, + private checkAvalSeatSV: CheckAvailableSeatService + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.waitList = this.updateMatTable(this.waitList? this.waitList:[]) + } + + checkAvailable(x){ + console.log(x) + // this.checkAvalSeatSV.add(x).pipe( + // tap(x => console.log(x)) + // ).subscribe() + const dialogRef = this.dialog.open(ChangeDialogComponent, { + width: '500px', + data: x, + }); + } + + reason(x){ + const dialogRef = this.dialog.open(ReasonDialogComponent, { + width: '90vh', + data: x, + }); + } + +} diff --git a/src/app/feature/change-exam-day/router/router.ts b/src/app/feature/change-exam-day/router/router.ts new file mode 100644 index 0000000..24faa4b --- /dev/null +++ b/src/app/feature/change-exam-day/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamDayRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/change-exam-room/change-exam-room.module.ts b/src/app/feature/change-exam-room/change-exam-room.module.ts new file mode 100644 index 0000000..e611d2d --- /dev/null +++ b/src/app/feature/change-exam-room/change-exam-room.module.ts @@ -0,0 +1,51 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ChangeExamRoomRouter } from './router/router'; +import { ChangeExamRoomContainer } from './container/change-exam-room/change-exam-room.container'; +import { SearchComponent } from './presenter/search/search.component'; +import { ListComponent } from './presenter/list/list.component'; +import { ViewComponent } from './presenter/view/view.component'; +import { DialogComponent } from './presenter/dialog/dialog.component'; +import { ChangeExamRoomViewContainer } from './container/change-exam-room-view/change-exam-room-view.container'; +import { RoomViewListComponent } from './presenter/room-view/room-view-list/room-view-list.component'; +import { RoomViewSearchComponent } from './presenter/room-view/room-view-search/room-view-search.component'; + + +const routes: Routes = [ + { + path: '', + component: ChangeExamRoomRouter, + children: [ + { + path: '', + component: ChangeExamRoomContainer + }, + { + path: 'view/:id', + component: ChangeExamRoomViewContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ChangeExamRoomRouter, + ChangeExamRoomContainer, + SearchComponent, + ListComponent, + ViewComponent, + DialogComponent, + ChangeExamRoomViewContainer, + RoomViewListComponent, + RoomViewSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ChangeExamRoomModule {} diff --git a/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.html b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.html new file mode 100644 index 0000000..1fab288 --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.html @@ -0,0 +1,12 @@ + + + + diff --git a/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.scss b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.spec.ts b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.spec.ts new file mode 100644 index 0000000..add0a62 --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamRoomViewContainer } from './change-exam-room-view.container'; + +describe('ChangeExamRoomViewContainer', () => { + let component: ChangeExamRoomViewContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamRoomViewContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamRoomViewContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.ts b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.ts new file mode 100644 index 0000000..b5fd650 --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room-view/change-exam-room-view.container.ts @@ -0,0 +1,94 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, ChangeDetectorRef} from '@angular/core'; +import {BaseList, CustomeEventPage} from '../../../../core/base/base-list'; +import {map, switchMap, tap} from 'rxjs/operators'; +import {Observable} from 'rxjs'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate} from '@angular/common'; +import {DialogComponent} from '../../presenter/dialog/dialog.component'; +import {TestingControlsService} from '../../../../core/service/testing-information/testing-controls.service'; +import {MatDialog} from '@angular/material/dialog'; + +@Component({ + selector: 'app-change-exam-room-view', + templateUrl: './change-exam-room-view.container.html', + styleUrls: ['./change-exam-room-view.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamRoomViewContainer extends BaseList implements OnInit{ + @Input() testingInformationList: any = []; + testingInformation$ = new Observable(); + paginator; + Id; + testingInfoData; + currentQueryPaging = ''; + currentQueryString = ''; + reload: boolean; + constructor( + private testinforSV: TestingInformationService, + private testingControlSV: TestingControlsService, + private cdr: ChangeDetectorRef, + private router: Router, + private dialog: MatDialog, + public activeRouter: ActivatedRoute, + ){ + super(); + } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => x.id ? this.Id = x.id : this.Id = null), + tap(x => { + this.testinforSV.get(this.Id).pipe( + tap(y => this.testingInfoData = y), + ).subscribe(); + }), + ).subscribe(); + } + + pageChange(event: CustomeEventPage){ + this.paginator = event.paginator; + this.currentQueryPaging = event.queryStringPage; + if (this.currentQueryString) { + return this.testingInformation$ = this.testingControlSV.getNoRoomPage(`${event.queryStringPage}?${this.currentQueryString}`,this.Id) + }else{ + return this.testingInformation$ = this.testingControlSV.getNoRoomPage(`${event.queryStringPage}`,this.Id) + } + } + + search(queryString){ + // if(query) return this.testingInformation$ = this.testingControlSV.getSearchForCountSeat(`?${query}`); + // if(!query) return this.testingInformation$ = this.testingControlSV.getSearchForCountSeat(`?is_open=true`); + + this.currentQueryString = queryString + if (queryString) { + this.paginator.firstPage() + return this.testingInformation$ = this.testingControlSV.query(`${this.currentQueryPaging}?${this.currentQueryString}`) + } + if (!queryString) { + return this.testingInformation$ = this.testingControlSV.query(`${this.currentQueryPaging}`) + } + } + + changeRoom(x){ + console.log(x) + const obj = { + data : x.data, + testing_information: x.TestInformation + } + // this.query.start_date = formatDate(this.query.start_date, 'yyyy-MM-dd', 'en-US'); + // this.query.end_date = formatDate(this.query.end_date, 'yyyy-MM-dd', 'en-US'); + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj + }); + // + dialogRef.afterClosed().pipe( + switchMap(x => { + return this.testingControlSV.getNoRoomPage(`1?5`,this.Id).pipe( + tap(x => this.cdr.detectChanges())) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.html b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.html new file mode 100644 index 0000000..1a04c37 --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.html @@ -0,0 +1,2 @@ + + diff --git a/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.scss b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.spec.ts b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.spec.ts new file mode 100644 index 0000000..61d092e --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamRoomContainer } from './change-exam-room.container'; + +describe('ChangeExamRoomContainer', () => { + let component: ChangeExamRoomContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamRoomContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamRoomContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.ts b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.ts new file mode 100644 index 0000000..28651e7 --- /dev/null +++ b/src/app/feature/change-exam-room/container/change-exam-room/change-exam-room.container.ts @@ -0,0 +1,27 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-change-exam-room', + templateUrl: './change-exam-room.container.html', + styleUrls: ['./change-exam-room.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamRoomContainer implements OnInit { + testingInfo$ = new Observable() + constructor( + private testingInfomationSV: TestingInformationService, + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfomationSV.search(`?is_open=true`) + } + + search(query){ + if(query) return this.testingInfo$ = this.testingInfomationSV.search(`?${query}`); + if(!query) return this.testingInfo$ = this.testingInfomationSV.search(`?is_open=true`); + } + + +} diff --git a/src/app/feature/change-exam-room/presenter/dialog/dialog.component.html b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.html new file mode 100644 index 0000000..ea9adbf --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.html @@ -0,0 +1,87 @@ +
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + + + + + +
+
+ +
+
+ + +
+
+ +
+ +
+ + +
+
+ +
+ *เก้าอี้จะมีการสุ่มใหม่ +
+ +
+
+ + +
+ +
diff --git a/src/app/feature/change-exam-room/presenter/dialog/dialog.component.scss b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/dialog/dialog.component.spec.ts b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.spec.ts new file mode 100644 index 0000000..a32e0ea --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogComponent } from './dialog.component'; + +describe('DialogComponent', () => { + let component: DialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/dialog/dialog.component.ts b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.ts new file mode 100644 index 0000000..8e115dc --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/dialog/dialog.component.ts @@ -0,0 +1,102 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { TestingFieldService } from 'src/app/core/service/settings/testing-field.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { ChangeTestingRoomService } from 'src/app/core/service/testing-register/change-testing-room.service'; +import { TestingCenterService } from 'src/app/core/service/TestingCenter/testing-center.service'; + +@Component({ + selector: 'app-dialog', + templateUrl: './dialog.component.html', + styleUrls: ['./dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogComponent extends BaseForm implements OnInit { + testingCenterList: any = []; + branchList: any = []; + testingFieldList: any = []; + filteredTestingFieldList: any = []; + filteredTestingCenterList : any = []; + constructor( + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + public router: Router, + public dialogRef: MatDialogRef, + private testingCenterSV: TestingCenterService, + @Inject(MAT_DIALOG_DATA) public data: any, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private changeTestingRoomSV: ChangeTestingRoomService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.form.patchValue(this.data.data) + this.testingCenterSV.getAll().pipe( + tap(x => this.testingCenterList = x) + ).subscribe() + this.branchSV.getAll().pipe( + tap(x => this.branchList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.testingFieldSV.getAll().pipe( + tap(x => this.testingFieldList = x) + ).subscribe() + } + + createForm(): FormGroup { + return this.fb.group({ + testing_information_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_datetime: null, + period_id: null, + new_period_id: null, + new_branch_uid: [null,Validators.required], + new_testing_field_uid: [null,Validators.required], + new_testing_center_uid: [null,Validators.required], + new_testing_datetime: [null,Validators.required], + room_remark: [null,Validators.required] + }) + } + + filterTestingField(uid){ + this.form.get('new_testing_field_uid').setValue(null) + this.filteredTestingFieldList = this.testingFieldList.filter(x => x.branch_uid == uid) + } + + findTestingCenter(){ + const form = this.form.getRawValue() + const find = this.testingCenterList.filter(x => (x.branch_uid == form.new_branch_uid) && (x.testing_field_uid == form.new_testing_field_uid)) + this.filteredTestingCenterList = find + } + + confirm(){ + const form = this.form.getRawValue() + this.changeTestingRoomSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess('ย้ายห้องสำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + cancel(){ + this.dialogRef.close() + } + +} diff --git a/src/app/feature/change-exam-room/presenter/list/list.component.html b/src/app/feature/change-exam-room/presenter/list/list.component.html new file mode 100644 index 0000000..648010e --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/list/list.component.html @@ -0,0 +1,79 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ประเภทผู้สมัคร {{x.type_of_examinee}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/change-exam-room/presenter/list/list.component.scss b/src/app/feature/change-exam-room/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/list/list.component.spec.ts b/src/app/feature/change-exam-room/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/list/list.component.ts b/src/app/feature/change-exam-room/presenter/list/list.component.ts new file mode 100644 index 0000000..bb6736a --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/list/list.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() testingInfomationList : any = []; + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(changes: SimpleChanges): void { + this.testingInfomationList = this.updateMatTable(this.testingInfomationList? this.testingInfomationList:[]) + } + + onView(uid){ + this.router.navigate(['change-exam-room/view',uid]) + } +} diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.html b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.html new file mode 100644 index 0000000..959eaa8 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.html @@ -0,0 +1,43 @@ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} จำนวนผู้สมัคร {{x.total_register}} + +
+ +
+
+
+ + diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.scss b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.spec.ts b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.spec.ts new file mode 100644 index 0000000..0dd8f88 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RoomViewListComponent } from './room-view-list.component'; + +describe('RoomViewListComponent', () => { + let component: RoomViewListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RoomViewListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RoomViewListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.ts b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.ts new file mode 100644 index 0000000..6c87489 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-list/room-view-list.component.ts @@ -0,0 +1,52 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {map, switchMap, tap} from 'rxjs/operators'; +import {formatDate} from '@angular/common'; +import {DialogComponent} from '../../dialog/dialog.component'; +import {ActivatedRoute} from '@angular/router'; +import {TestingControlsService} from '../../../../../core/service/testing-information/testing-controls.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-room-view-list', + templateUrl: './room-view-list.component.html', + styleUrls: ['./room-view-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RoomViewListComponent extends BaseList implements OnInit, OnChanges{ + testingControlList: any = []; + @Input() testingInformationList: any = []; + @Input() testingInfoData:any; + @Input() query:any; + @Output() changeroom = new EventEmitter(); + + reload: boolean; + constructor( + public activeRoute: ActivatedRoute, + private testingControlSV: TestingControlsService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService, + private testingInfoSV: TestingInformationService + ){ + super(); + } + + ngOnInit(): void { + this.getEventPage().pipe( + tap(x => this.onPaginatorPageChange.emit(x)) + ).subscribe(); + } + + ngOnChanges(){ + this.testingInformationList = this.updatePagingMatabe(this.testingInformationList ? this.testingInformationList : []); + } + + changeRoom(data){ + this.changeroom.emit({data, TestInformation: this.testingInfoData}); + + } + +} diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.html b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.html new file mode 100644 index 0000000..5b47bfb --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.html @@ -0,0 +1,55 @@ +
+

แสดงรายการค้นหาของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
+
+
+ + +
+
+
+
diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.scss b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.spec.ts b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.spec.ts new file mode 100644 index 0000000..3ef069a --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RoomViewSearchComponent } from './room-view-search.component'; + +describe('RoomViewSearchComponent', () => { + let component: RoomViewSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RoomViewSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RoomViewSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.ts b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.ts new file mode 100644 index 0000000..3650ee3 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/room-view/room-view-search/room-view-search.component.ts @@ -0,0 +1,71 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, ChangeDetectorRef, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {formatDate} from '@angular/common'; +import {map, tap} from 'rxjs/operators'; +import {ActivatedRoute} from '@angular/router'; +import {TestingControlsService} from '../../../../../core/service/testing-information/testing-controls.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-room-view-search', + templateUrl: './room-view-search.component.html', + styleUrls: ['./room-view-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RoomViewSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + @Input() testingInfoData:any; + query = { + start_date: null, + end_date: null, + period_id: null, + testing_information_uid: null, + testing_room_name_th: null, + }; + id; + constructor( + public activeRoute: ActivatedRoute, + private testingControlSV: TestingControlsService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService, + private testingInfoSV: TestingInformationService + ) { } + + ngOnInit(): void { + this.activeRoute.params.pipe( + tap(x => x.id ? this.id = x.id : this.id = null) + ).subscribe(); + this.testingInfoSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + onSearch(){ + this.query.testing_information_uid = this.testingInfoData.testing_information_uid; + if (this.query.start_date !== null && this.query.end_date !== null){ + if(this.query.start_date) this.query.start_date = formatDate(this.query.start_date, 'yyyy-MM-dd', 'en-US'); + if(this.query.end_date) this.query.end_date = formatDate(this.query.end_date, 'yyyy-MM-dd', 'en-US'); + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + }else { + this.swSV.errText('กรุณาใส่วันที่เริ่มต้นและสิ้นสุด') + + } + + } + + clear(){ + this.query = { + start_date: null, + end_date: null, + period_id: null, + testing_room_name_th: null, + testing_information_uid: this.query.testing_information_uid + }; + } + +} diff --git a/src/app/feature/change-exam-room/presenter/search/search.component.html b/src/app/feature/change-exam-room/presenter/search/search.component.html new file mode 100644 index 0000000..5a81e9a --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/search/search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/change-exam-room/presenter/search/search.component.scss b/src/app/feature/change-exam-room/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/search/search.component.spec.ts b/src/app/feature/change-exam-room/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/search/search.component.ts b/src/app/feature/change-exam-room/presenter/search/search.component.ts new file mode 100644 index 0000000..99b1bf0 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/search/search.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + registration_type: 1, + is_open: true + }; + constructor( + private acdmYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.acdmYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + registration_type: 1, + is_open: true + }; + } +} diff --git a/src/app/feature/change-exam-room/presenter/view/view.component.html b/src/app/feature/change-exam-room/presenter/view/view.component.html new file mode 100644 index 0000000..147f954 --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/view/view.component.html @@ -0,0 +1,95 @@ +
+

แสดงรายการค้นหาของรอบสอบ {{testingInfoData?.testing_information_name}}

+ +
+
+ + +
+
+ + + + + + +
+
+ + + + + + +
+
+ + +
+
+
+
+ + +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} วันที่สอบ {{x.testing_datetime | thaidate}} Section {{x.period_id}} จำนวนผู้สมัคร {{x.total_register}} + +
+ +
+
diff --git a/src/app/feature/change-exam-room/presenter/view/view.component.scss b/src/app/feature/change-exam-room/presenter/view/view.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-exam-room/presenter/view/view.component.spec.ts b/src/app/feature/change-exam-room/presenter/view/view.component.spec.ts new file mode 100644 index 0000000..f644b0a --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/view/view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewComponent } from './view.component'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-exam-room/presenter/view/view.component.ts b/src/app/feature/change-exam-room/presenter/view/view.component.ts new file mode 100644 index 0000000..9b023ea --- /dev/null +++ b/src/app/feature/change-exam-room/presenter/view/view.component.ts @@ -0,0 +1,117 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute } from '@angular/router'; +import { filter, map, switchMap, tap } from 'rxjs/operators'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; +import { TestingControlsService } from 'src/app/core/service/testing-information/testing-controls.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { DialogComponent } from '../dialog/dialog.component'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {formatDate} from '@angular/common'; +import {createQueryStringFromObject} from '../../../../shared/util/func'; +import {query} from '@angular/animations'; +import {compareSegments} from '@angular/compiler-cli/src/ngtsc/sourcemaps/src/segment_marker'; + +@Component({ + selector: 'app-view', + templateUrl: './view.component.html', + styleUrls: ['./view.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ViewComponent extends BaseSubList implements OnInit { + testingControlList: any = []; + query = { + start_date: null, + end_date: null, + period_id: null, + testing_room_name_th: null, + }; + testingInfoData; + constructor( + public activeRoute: ActivatedRoute, + private testingControlSV: TestingControlsService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService, + private testingInfoSV: TestingInformationService + ) { + super(activeRoute) + } + + ngOnInit(): void { + this.swSV.loadingStart() + this.testingControlSV.getNoRoomStatus(`?testing_information_uid=${this.id}`).pipe( + map((x:any) => x.filter(data => data.room_status != true)), + tap(x => this.testingControlList = this.updateMatTable(x)), + tap(x => this.swSV.close()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.testingInfoSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + changeRoom(x){ + const obj = { + data : x, + testing_information: this.testingInfoData + } + this.query.start_date = formatDate(this.query.start_date, 'yyyy-MM-dd', 'en-US'); + this.query.end_date = formatDate(this.query.end_date, 'yyyy-MM-dd', 'en-US'); + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj + }); + + dialogRef.afterClosed().pipe( + switchMap(x => { + return this.testingControlSV.getNoRoomStatus(`?testing_information_uid=${this.id}&start_date=${this.query.start_date}&end_date=${this.query.end_date}`).pipe( + map((x:any) => x.filter(data => data.room_status != true)), + tap(x => this.testingControlList.data = x), + tap(x => this.cdr.detectChanges())) + }) + ).subscribe() + } + + search(){ + if (this.query.start_date !== null && this.query.end_date !== null){ + this.swSV.loadingStart() + if(this.query.start_date) this.query.start_date = formatDate(this.query.start_date, 'yyyy-MM-dd', 'en-US'); + if(this.query.end_date) this.query.end_date = formatDate(this.query.end_date, 'yyyy-MM-dd', 'en-US'); + console.log(this.createQueryStringFromObject(this.query)) + this.testingControlSV.getNoRoomStatus(`?${this.createQueryStringFromObject(this.query)}`).pipe( + map((x:any) => x.filter(data => data.room_status != true)), + tap(x => this.testingControlList = this.updateMatTable(x)), + tap(x => this.swSV.close()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + }else { + this.swSV.errText('กรุณาใส่วันที่เริ่มต้นและสิ้นสุด') + } + } + + createQueryStringFromObject(query){ + let queryStr: string = '' + + for (const key in query) { + console.log(query[key]); + if (query[key] != null) { + queryStr += `${key}=${query[key]}&` + } + } + let lastIndex = queryStr.lastIndexOf('&') + queryStr = queryStr.slice(0,lastIndex) + return queryStr + } + + clear(){ + this.query = { + start_date: null, + end_date: null, + period_id: null, + testing_room_name_th: null + }; + } + +} diff --git a/src/app/feature/change-exam-room/router/router.ts b/src/app/feature/change-exam-room/router/router.ts new file mode 100644 index 0000000..76335f4 --- /dev/null +++ b/src/app/feature/change-exam-room/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamRoomRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/change-password/change-password.module.ts b/src/app/feature/change-password/change-password.module.ts new file mode 100644 index 0000000..dbd0e5e --- /dev/null +++ b/src/app/feature/change-password/change-password.module.ts @@ -0,0 +1,32 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {RouterModule, Routes} from '@angular/router'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { ChangePasswordRouter } from './router/router'; +import { FormComponent } from './form/form.component'; + +const routes: Routes = [ + { + path: '', + component: ChangePasswordRouter, + children: [ + { + path: '', + component: FormComponent + } + ] + } +]; + +@NgModule({ + declarations: [ + ChangePasswordRouter, + FormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ChangePasswodModule { } diff --git a/src/app/feature/change-password/form/form.component.html b/src/app/feature/change-password/form/form.component.html new file mode 100644 index 0000000..fb289f7 --- /dev/null +++ b/src/app/feature/change-password/form/form.component.html @@ -0,0 +1,38 @@ +
+

เปลี่ยนรหัสผ่าน

+
+
+
+
+ + +
+ +
+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
+ +
+ รหัสผ่านควรมี พิมพ์เล็ก พิมพ์ใหญ่ ตัวเลขและต้องมีมากกว่า 8 ตัวอักษร +
+
+ + +
+ +
diff --git a/src/app/feature/change-password/form/form.component.scss b/src/app/feature/change-password/form/form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/change-password/form/form.component.spec.ts b/src/app/feature/change-password/form/form.component.spec.ts new file mode 100644 index 0000000..31024eb --- /dev/null +++ b/src/app/feature/change-password/form/form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormComponent } from './form.component'; + +describe('FormComponent', () => { + let component: FormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/change-password/form/form.component.ts b/src/app/feature/change-password/form/form.component.ts new file mode 100644 index 0000000..184252e --- /dev/null +++ b/src/app/feature/change-password/form/form.component.ts @@ -0,0 +1,94 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { OidcAuthService } from 'src/app/core/service/oidc/oidc.service'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormComponent extends BaseFormUid implements OnInit { + confirm; + canEdit: boolean + constructor( + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + public fb: FormBuilder, + private userOpenidSV: UserOpenidService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private appTokenSV: AppTokenService, + private oidc: OidcAuthService, + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.canEdit = true + const data = this.appTokenSV.user + this.userOpenidSV.get(data.user_uid).pipe( + tap(x => this.setupForm(x)), + tap(x => this.cdr.detectChanges()), + ).subscribe() + + } + + setupForm(x){ + this.form.patchValue(x) + this.form.get('password').setValue(null) + } + + createForm(){ + return this.fb.group({ + user_uid: null, + login_name: [null,Validators.required], + display_name: [null,Validators.required], + password: [null,[ + Validators.required, + Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,30})') + ]], + confirm: [null,[ + Validators.required, + Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,30})') + ]], + agency_uid: "00000000-0000-0000-0000-000000000000", + image_url: "", + is_active: true, + group_name: "", + agency_name: "" + }) + } + + save(){ + const form = this.form.getRawValue() + const uid = form.user_uid + if(form.password == form.confirm){ + this.userOpenidSV.changePassword(uid,form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + tap(x => this.oidc.logout()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + }else{ + this.swSV.errText('รหัสผ่านไม่ตรงกัน') + } + } + + cancel(){ + this.location.back() + } + +} diff --git a/src/app/feature/change-password/router/router.ts b/src/app/feature/change-password/router/router.ts new file mode 100644 index 0000000..4620247 --- /dev/null +++ b/src/app/feature/change-password/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-create-user-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangePasswordRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.html b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.html new file mode 100644 index 0000000..9865ac8 --- /dev/null +++ b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.html @@ -0,0 +1,2 @@ + + diff --git a/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.scss b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.spec.ts b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.spec.ts new file mode 100644 index 0000000..b60933a --- /dev/null +++ b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoContainer } from './testing-info.container'; + +describe('TestingInfoContainer', () => { + let component: TestingInfoContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.ts b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.ts new file mode 100644 index 0000000..93f82e0 --- /dev/null +++ b/src/app/feature/create-exam-seat/container/testing-info/testing-info.container.ts @@ -0,0 +1,37 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-testing-info', + templateUrl: './testing-info.container.html', + styleUrls: ['./testing-info.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoContainer implements OnInit { + testingInfo$ = new Observable() + query = { + is_open: true, + is_register: false, + registration_type: 2, + type_of_examinee: 'นักศึกษาโครงการพิเศษ/บุคคลทั่วไปแบบโครงการ' + } + querySting; + constructor( + private testingInfomationSV: TestingInformationService, + ) { + this.querySting = createQueryStringFromObject(this.query) + } + + ngOnInit(): void { + console.log(this.querySting) + this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?${this.querySting}`) + } + + search(query){ + if(query) return this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?${this.querySting}&${query}`); + if(!query) return this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?${this.querySting}&${query}`); + } + +} diff --git a/src/app/feature/create-exam-seat/create-exam-seat.module.ts b/src/app/feature/create-exam-seat/create-exam-seat.module.ts new file mode 100644 index 0000000..48fa075 --- /dev/null +++ b/src/app/feature/create-exam-seat/create-exam-seat.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamSeatRouter } from './router/router'; +import { TestingInfoContainer } from './container/testing-info/testing-info.container'; +import { TestingInfoListComponent } from './presenter/testing-info-list/testing-info-list.component'; +import { TestingInfoSearchComponent } from './presenter/testing-info-search/testing-info-search.component'; +import { ViewComponent } from './presenter/view/view.component'; +import { CreateSeatComponent } from './presenter/create-seat/create-seat.component'; +import { StudentDialogComponent } from './presenter/student-dialog/student-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamSeatRouter, + children: [ + { + path: '', + component: TestingInfoContainer + }, + { + path: 'view/:id', + component: ViewComponent + }, + { + path: 'seat/:testing_information_uid/:branch_uid/:testing_field_uid/:testing_center_uid/:testing_date/:section/:total_seat_generate/:total_student', + component: CreateSeatComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamSeatRouter, + TestingInfoContainer, + TestingInfoListComponent, + TestingInfoSearchComponent, + ViewComponent, + CreateSeatComponent, + StudentDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreatExamSeatModule { } diff --git a/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.html b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.html new file mode 100644 index 0000000..b61ee82 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.html @@ -0,0 +1,93 @@ +
+
+
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+
+ + +
+ +
+ + +
+
+
+ +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ +
+
+
+
+

รายชื่อนักศึกษา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสผู้เข้าสอบ {{x.student_code? x.student_code : '-'}} ชื่อ-นามสกุล {{x.student_name_th}} รหัสวิชา {{x.register_subject_code}} วิชาสอบ {{x.subject_name_th}} ที่นั่ง {{x.testing_seat}}
+ +
+
+
diff --git a/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.scss b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.spec.ts b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.spec.ts new file mode 100644 index 0000000..513cb7a --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateSeatComponent } from './create-seat.component'; + +describe('CreateSeatComponent', () => { + let component: CreateSeatComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateSeatComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateSeatComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.ts b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.ts new file mode 100644 index 0000000..d5e07b2 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/create-seat/create-seat.component.ts @@ -0,0 +1,96 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { ActivatedRoute } from '@angular/router'; +import { throwError } from 'rxjs'; +import { catchError, filter, switchMap, tap } from 'rxjs/operators'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; +import { GenerateGroupSeatDetailService } from 'src/app/core/service/student/generate-group-seat-detail.service'; +import { StudentGenerateSeatService } from 'src/app/core/service/student/student-generate-seat.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import Swal from 'sweetalert2'; +import { StudentDialogComponent } from '../student-dialog/student-dialog.component'; + +@Component({ + selector: 'app-create-seat', + templateUrl: './create-seat.component.html', + styleUrls: ['./create-seat.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateSeatComponent extends BaseSubList implements OnInit { + studentList: any = []; + data; + testingInfomationData; + totalSeatGenerate; + totalStudent; + paramsData; + constructor( + public activeRoute: ActivatedRoute, + private generateGroupSeatDetailSV: GenerateGroupSeatDetailService, + private testingInfomationSV: TestingInformationService, + private studentGenerateSeatSV: StudentGenerateSeatService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog + ) { + super(activeRoute) + } + + ngOnInit(): void { + this.activeRoute.params.pipe( + tap(x => this.paramsData = x), + tap(x => this.totalSeatGenerate = x.total_seat_generate), + tap(x => this.totalStudent = x.total_student), + switchMap(x => this.generateGroupSeatDetailSV.getDetail(x)), + tap(x => this.studentList = this.updateMatTable(x)), + tap(x => this.data = x[0]), + switchMap(x => this.testingInfomationSV.searchForSeat(`?registration_type=1&testing_information_uid=${x[0].testing_information_uid}`)), + tap(x => this.testingInfomationData = x[0]), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + add(){ + Swal.fire({ + title: 'กำลังสร้างที่นั่งสอบ...', + html: 'กรุณารอ...', + allowEscapeKey: false, + allowOutsideClick: false, + didOpen: () => { + Swal.showLoading() + } + }); + + this.studentGenerateSeatSV.createSeat(this.paramsData).pipe( + tap(x => Swal.hideLoading()), + tap(x => Swal.close()), + tap(x => this.swSV.success('สร้างที่นั่งสอบสำเร็จ')), + tap(x => window.history.back()), + catchError(err => { + Swal.hideLoading() + Swal.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + addStudent(){ + const obj = { + params_data: this.paramsData, + student_list: this.studentList.data + } + const dialogRef = this.dialog.open(StudentDialogComponent, { + width: '500px', + data: obj, + }); + + dialogRef.afterClosed().pipe( + switchMap(x => this.generateGroupSeatDetailSV.getDetail(this.paramsData)), + tap(x => this.studentList = this.updateMatTable(x)), + tap(x => this.data = x[0]), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + +} diff --git a/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.html b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.html new file mode 100644 index 0000000..71f0fab --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.html @@ -0,0 +1,32 @@ +
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+ + +
+ +
diff --git a/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.scss b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.spec.ts b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.spec.ts new file mode 100644 index 0000000..f9eee5e --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StudentDialogComponent } from './student-dialog.component'; + +describe('StudentDialogComponent', () => { + let component: StudentDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StudentDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(StudentDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.ts b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.ts new file mode 100644 index 0000000..82f233a --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/student-dialog/student-dialog.component.ts @@ -0,0 +1,83 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { StudentService } from 'src/app/core/service/student/student.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-student-dialog', + templateUrl: './student-dialog.component.html', + styleUrls: ['./student-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class StudentDialogComponent extends BaseForm implements OnInit { + subject; + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + public router: Router, + private testingInformationSV: TestingInformationService, + private studentSV: StudentService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.testingInformationSV.get(this.data.params_data.testing_information_uid).pipe( + tap(x => this.subject = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + createForm(): FormGroup { + return this.fb.group({ + testing_information_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + testing_date: null, + section: null, + student_code: [null,Validators.required], + student_name_th: [null,Validators.required], + student_name_en: null, + register_subject_code: [null,Validators.required] + }) + } + + confirm(){ + // this.dialogRef.close() + this.form.patchValue(this.data.params_data) + const form = this.form.getRawValue() + form.section = +form.section + const isDuplicate = this.data.student_list.find(x => x.student_code == form.student_code) + if(isDuplicate){ + this.swSV.errText('รหัสนักศึกษาซ้ำกัน') + }else{ + this.studentSV.addStudent(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + + } + + cancel(){ + this.dialogRef.close() + } +} diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.html b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.html new file mode 100644 index 0000000..c848055 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.html @@ -0,0 +1,73 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ประเภทผู้สมัคร {{x.type_of_examinee}} เก้าอี้ทั้งหมด {{x.total_seat}} จำนวนที่นำเข้าแล้ว {{x.no_imported}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.scss b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.spec.ts b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.spec.ts new file mode 100644 index 0000000..96cc780 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoListComponent } from './testing-info-list.component'; + +describe('TestingInfoListComponent', () => { + let component: TestingInfoListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.ts b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.ts new file mode 100644 index 0000000..a033400 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-list/testing-info-list.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-testing-info-list', + templateUrl: './testing-info-list.component.html', + styleUrls: ['./testing-info-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoListComponent extends BaseList implements OnInit,OnChanges { + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'type_of_examinee', + 'total_seat', + 'no_imported', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + 'created_datetime', + '11' + ]; + reload: boolean; + @Input() testingInfomationList : any = []; + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(): void { + this.testingInfomationList = this.updateMatTable(this.testingInfomationList? this.testingInfomationList:[]) + } + + onView(uid){ + this.router.navigate(['create-exam-seat/view',uid]) + } + +} diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.html b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.html new file mode 100644 index 0000000..5111de9 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.html @@ -0,0 +1,29 @@ + +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
+ diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.scss b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.spec.ts b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.spec.ts new file mode 100644 index 0000000..76f66b8 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoSearchComponent } from './testing-info-search.component'; + +describe('TestingInfoSearchComponent', () => { + let component: TestingInfoSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.ts b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.ts new file mode 100644 index 0000000..d7060f1 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/testing-info-search/testing-info-search.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-testing-info-search', + templateUrl: './testing-info-search.component.html', + styleUrls: ['./testing-info-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private acdmYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.acdmYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } +} diff --git a/src/app/feature/create-exam-seat/presenter/view/view.component.html b/src/app/feature/create-exam-seat/presenter/view/view.component.html new file mode 100644 index 0000000..2846542 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/view/view.component.html @@ -0,0 +1,91 @@ +

ค้นหา

+
+
+
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + +
+ +
+ +   + +
+
+
+
+
+
+
+

แสดงผลรายการที่นำเข้าของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ศูนย์สอบ {{x.branch_name_th}} สนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} วันที่ {{x.testing_date | thaidate}} คาบสอบ {{x.section}} สร้างเลขที่นั่งสอบ + {{x.is_generate_seat? 'check_circle' : ''}} + เครื่องมือ +
+ + + +
+
+ +
+
+
diff --git a/src/app/feature/create-exam-seat/presenter/view/view.component.scss b/src/app/feature/create-exam-seat/presenter/view/view.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam-seat/presenter/view/view.component.spec.ts b/src/app/feature/create-exam-seat/presenter/view/view.component.spec.ts new file mode 100644 index 0000000..f644b0a --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/view/view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewComponent } from './view.component'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam-seat/presenter/view/view.component.ts b/src/app/feature/create-exam-seat/presenter/view/view.component.ts new file mode 100644 index 0000000..2a68852 --- /dev/null +++ b/src/app/feature/create-exam-seat/presenter/view/view.component.ts @@ -0,0 +1,92 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { catchError, concatMap, filter, switchMap, tap } from 'rxjs/operators'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; +import { GenerateGroupService } from 'src/app/core/service/student/generate-group.service'; +import { ResetSeatService } from 'src/app/core/service/student/reset-seat.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-view', + templateUrl: './view.component.html', + styleUrls: ['./view.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ViewComponent extends BaseSubList implements OnInit { + testingCenterList: any = []; + testingInfoData; + query = { + section: null, + start_testing_date: null, + end_testing_date: null, + testing_information_uid: null + } + constructor( + public activeRoute: ActivatedRoute, + private studentGenerateGroupSV: GenerateGroupService, + private router: Router, + private cdr: ChangeDetectorRef, + private testingInformationSV: TestingInformationService, + private swSV: SweetalertService, + private resetSeatSV: ResetSeatService + ) { + super(activeRoute) + } + + ngOnInit(): void { + this.studentGenerateGroupSV.search(`?testing_information_uid=${this.id}`).pipe( + tap(x => this.testingCenterList = this.updateMatTable(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.testingInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + edit(x){ + this.router.navigate(['create-exam-seat/seat',x.testing_information_uid,x.branch_uid,x.testing_field_uid,x.testing_center_uid,x.testing_date,x.section,x.total_seat_generate,x.total_student]) + } + + search(){ + this.query.testing_information_uid = this.id + if(this.query.start_testing_date) this.query.start_testing_date = formatDate(this.query.start_testing_date, 'yyyy-MM-dd', 'en-US'); + if(this.query.end_testing_date) this.query.end_testing_date = formatDate(this.query.end_testing_date, 'yyyy-MM-dd', 'en-US'); + console.log(this.query) + const query = createQueryStringFromObject(this.query) + this.studentGenerateGroupSV.search(`?${query}`).pipe( + tap(x => this.testingCenterList.data = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + clear(){ + this.studentGenerateGroupSV.search(`?testing_information_uid=${this.id}`).pipe( + tap(x => this.testingCenterList.data = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + clearData(data){ + this.swSV.confirm('ต้องการจะล้างข้อมูลนี้ไหม').pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.resetSeatSV.reset(data).pipe( + concatMap(x => this.studentGenerateGroupSV.search(`?testing_information_uid=${this.id}`)), + tap(x => this.testingCenterList.data = x), + tap(x => this.swSV.saveSuccess('ล้างข้อมูลสำเร็จ')), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/create-exam-seat/router/router.ts b/src/app/feature/create-exam-seat/router/router.ts new file mode 100644 index 0000000..f60a0c8 --- /dev/null +++ b/src/app/feature/create-exam-seat/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-exam-seat-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSeatRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/approve-exam/approve-exam.module.ts b/src/app/feature/create-exam/approve-exam/approve-exam.module.ts new file mode 100644 index 0000000..486aab2 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/approve-exam.module.ts @@ -0,0 +1,42 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ApproveExamRouter } from './router/approve-exam-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ApproveExamContainer } from './container/approve-exam/approve-exam.container'; +import { ApproveExamSearchComponent } from './presenter/search/approve-exam-search/approve-exam-search.component'; +import { ApproveExamListComponent } from './presenter/list/approve-exam-list/approve-exam-list.component'; +import { ConfirmApproveExamDialogComponent } from './presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: ApproveExamRouter, + children: [ + { + path: '', + component: ApproveExamContainer + }, + // { + // path: 'view/:id', + // component: CheckCandidateTestingListComponent + // }, + ] + } +]; + +@NgModule({ + declarations: [ + ApproveExamRouter, + ApproveExamContainer, + ApproveExamSearchComponent, + ApproveExamListComponent, + ConfirmApproveExamDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ApproveExamModule { } diff --git a/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.html b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.html new file mode 100644 index 0000000..8a1dd5c --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.scss b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.spec.ts b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.spec.ts new file mode 100644 index 0000000..b777a98 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExamContainer } from './approve-exam.container'; + +describe('ApproveExamContainer', () => { + let component: ApproveExamContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExamContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExamContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.ts b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.ts new file mode 100644 index 0000000..1e6e2b6 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/container/approve-exam/approve-exam.container.ts @@ -0,0 +1,107 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from "rxjs/operators"; +import { + ConfirmRejectExamDialogComponent +} from '../../../reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component'; +import {ConfirmApproveExamDialogComponent} from '../../presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component'; +import {MatDialog} from '@angular/material/dialog'; +import {ExamNotificationService} from '../../../../../core/service/testing-information/exam-notification.service'; +import Swal from 'sweetalert2'; + +@Component({ + selector: 'app-approve-exam', + templateUrl: './approve-exam.container.html', + styleUrls: ['./approve-exam.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExamContainer implements OnInit { + subjectList$ = new Observable(); + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private ExamNotiSV: ExamNotificationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private dialog: MatDialog, + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getisOpenNullandMaintrue(); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.searchisOpenNullFalseandMaintrue(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getisOpenNullandMaintrue(); + } + + notification(){ + // Swal.fire({ + // title: 'ส่งอัพเดทการแจ้งเตือน?', + // showDenyButton: true, + // showCancelButton: true, + // confirmButtonText: 'รูปแบบPOST', + // denyButtonText: `รูปแบบGET`, + // }).then((result) => { + // if (result.isConfirmed) { + // console.log(1) + // this.ExamNotiSV.sendNotfiPost().pipe( + // tap(x => this.swSV.success('อัพเดทการแจ้งเตือนเสร็จสิ้น')), + // catchError(err => { + // this.swSV.errOpenExamDetailText(err.error); + // return throwError(err); + // }) + // ).subscribe(); + // } else if (result.isDenied) { + // console.log(2) + // // this.ExamNotiSV.sendNotiTest().pipe( + // // tap(x => this.swSV.success('อัพเดทการแจ้งเตือนเสร็จสิ้น')), + // // catchError(err => { + // // this.swSV.errOpenExamDetailText(err.error); + // // return throwError(err); + // // }) + // // ).subscribe(); + // } + // }); + this.ExamNotiSV.sendNotiTest(); + + } + + edit(id){ + this.router.navigate(['create-exam-information/edit', id]); + } + + open(id){ + this.swSV.confirmOpenExam().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.checkandopentest(id).pipe( + tap(x => this.swSV.success('รอบสอบเปิดแล้ว')), + tap(x => this.ExamNotiSV.sendNotiTest()), + tap(x => this.subjectList$ = this.TestinforSV.getisOpenNullandMaintrue()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errOpenExamDetailText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + + open2(id){ + const dialogRef = this.dialog.open(ConfirmApproveExamDialogComponent, { + width: '550px', + height: '250px', + data: id, + panelClass: 'custom-modalbox' + }); + dialogRef.afterClosed().subscribe(result => { + this.subjectList$ = this.TestinforSV.getisOpenNullandMaintrue(); + }); + } + +} diff --git a/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.html b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.html new file mode 100644 index 0000000..f344279 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.html @@ -0,0 +1,46 @@ +
+
+
+
กรอก Username อีกครั้งเพื่อยืนยันการเปิด
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+

Username

+
+
+ +
+
+
+
+
+
+ + +
+
+ + + + + diff --git a/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.scss b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.scss new file mode 100644 index 0000000..a22b7ee --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.scss @@ -0,0 +1,11 @@ +.bgPopup{ // สีพื้นหลังหน้า list ลอง + background-color: #576071; +} + +.lock_open{ + @apply focus:outline-none text-green-700 text-sm py-1 px-2 rounded-md hover:bg-green-100 hover:bg-opacity-50 +} + +.lock_outline{ + @apply focus:outline-none text-gray-400 text-sm py-1 px-2 rounded-md hover:bg-gray-100 bg-opacity-50 +} diff --git a/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.spec.ts b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.spec.ts new file mode 100644 index 0000000..7503ac9 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfirmApproveExamDialogComponent } from './confirm-approve-exam-dialog.component'; + +describe('ConfirmApproveExamDialogComponent', () => { + let component: ConfirmApproveExamDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfirmApproveExamDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfirmApproveExamDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.ts b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.ts new file mode 100644 index 0000000..741c406 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/dialog/confirm-approve-exam-dialog/confirm-approve-exam-dialog.component.ts @@ -0,0 +1,70 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {FormBuilder} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {Location} from '@angular/common'; +import {ExamNotificationService} from '../../../../../../core/service/testing-information/exam-notification.service'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; + +@Component({ + selector: 'app-confirm-approve-exam-dialog', + templateUrl: './confirm-approve-exam-dialog.component.html', + styleUrls: ['./confirm-approve-exam-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ConfirmApproveExamDialogComponent extends BaseForm implements OnInit{ + userData; + userName; + constructor( + private TestinforSV: TestingInformationService, + private appTokenSV: AppTokenService, + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + private swSV: SweetalertService, + public location: Location, + private examResultSV: ExamNotificationService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + ) { + super( + router, + activeRoute, + fb, + location + ); + this.form = this.fb.group({ + Username: null, + }); + } + + ngOnInit(): void { + this.userData = this.appTokenSV.user; + this.userName = this.userData.login + } + + save(){ + console.log(this.data) + const form = this.form.getRawValue(); + this.TestinforSV.checkandopentest(this.data).pipe( + tap(x => this.swSV.success('รอบสอบเปิดแล้ว')), + tap(x => this.dialogRef.close()), + // tap(x => this.subjectList$ = this.TestinforSV.getAll()), + // tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errOpenExamDetailText(err.error); + return throwError(err); + }) + ).subscribe(); + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.html b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.html new file mode 100644 index 0000000..b96cd0e --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.html @@ -0,0 +1,77 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะ + เปิดรอบแล้ว + ปิดรอบสอบแล้ว + กำลังสร้าง + เครื่องมือ +
+ +
+
ผู้เปิดรอบ {{x.updated_by}} วันที่ {{x.updated_datetime | thaidate}}
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.scss b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.spec.ts b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.spec.ts new file mode 100644 index 0000000..9ec4fc2 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExamListComponent } from './approve-exam-list.component'; + +describe('ApproveExamListComponent', () => { + let component: ApproveExamListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExamListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExamListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.ts b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.ts new file mode 100644 index 0000000..f011bed --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/list/approve-exam-list/approve-exam-list.component.ts @@ -0,0 +1,75 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Input, + Output, + EventEmitter, + OnChanges, + ChangeDetectorRef +} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import { + TestingInformationService +} from "../../../../../../core/service/testing-information/testing-information.service"; +import {catchError, concatMap, filter, tap} from "rxjs/operators"; +import {throwError} from "rxjs"; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; + +@Component({ + selector: 'app-approve-exam-list', + templateUrl: './approve-exam-list.component.html', + styleUrls: ['./approve-exam-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExamListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + @Output() edit = new EventEmitter(); + @Output() open = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '10', + 'count_subject', + 'is_open', + '7', + 'updated_by', + 'updated_datetime' + ]; + private reload: boolean; + constructor( + private TestInformationSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onOpen(id){ + this.open.emit(id); + } + +} diff --git a/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.html b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.html new file mode 100644 index 0000000..218b831 --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.html @@ -0,0 +1,34 @@ +

ค้นหา

+
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + + +
+
diff --git a/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.scss b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.spec.ts b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.spec.ts new file mode 100644 index 0000000..641598b --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApproveExamSearchComponent } from './approve-exam-search.component'; + +describe('ApproveExamSearchComponent', () => { + let component: ApproveExamSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApproveExamSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApproveExamSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.ts b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.ts new file mode 100644 index 0000000..5e38bfd --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/presenter/search/approve-exam-search/approve-exam-search.component.ts @@ -0,0 +1,58 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-approve-exam-search', + templateUrl: './approve-exam-search.component.html', + styleUrls: ['./approve-exam-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExamSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + @Output() notification = new EventEmitter(); + academicYearList: any = []; + academicSemList: any = []; + query = { + testing_information_name: null, + academic_semester_code: null, + academic_year_code: null + }; + + constructor( + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + ) { + } + + ngOnInit(): void { + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch() { + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear() { + this.query = { + testing_information_name: null, + academic_semester_code: null, + academic_year_code: null + }; + } + + noti() { + this.notification.emit(); + } +} diff --git a/src/app/feature/create-exam/approve-exam/router/approve-exam-router.ts b/src/app/feature/create-exam/approve-exam/router/approve-exam-router.ts new file mode 100644 index 0000000..6b2b85c --- /dev/null +++ b/src/app/feature/create-exam/approve-exam/router/approve-exam-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ApproveExamRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.html b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.html new file mode 100644 index 0000000..ae6e7b6 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.html @@ -0,0 +1,10 @@ + + diff --git a/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.scss b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.spec.ts b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.spec.ts new file mode 100644 index 0000000..15f6407 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamCalenderContainer } from './create-exam-calender.container'; + +describe('CreateExamCalenderContainer', () => { + let component: CreateExamCalenderContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamCalenderContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamCalenderContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.ts b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.ts new file mode 100644 index 0000000..3e10e99 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/container/create-exam-calender/create-exam-calender.container.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-create-exam-calender', + templateUrl: './create-exam-calender.container.html', + styleUrls: ['./create-exam-calender.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamCalenderContainer implements OnInit { + + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + add(){ + this.router.navigate(['create-exam-calendar/add']); + } + + edit(id){ + this.router.navigate(['create-exam-calendar/edit', id]); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + expand(id){ + this.router.navigate(['create-exam-calendar/expand', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-calendar/create-exam-calendar.module.ts b/src/app/feature/create-exam/create-exam-calendar/create-exam-calendar.module.ts new file mode 100644 index 0000000..b429c95 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/create-exam-calendar.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamCalendarRouter } from './router/create-exam-calendar-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamCalenderContainer } from './container/create-exam-calender/create-exam-calender.container'; +import { CreateExamCalendarFormComponent } from './presenter/form/create-exam-calendar-form/create-exam-calendar-form.component'; +import { CreateExamCalendarListComponent } from './presenter/list/create-exam-calendar-list/create-exam-calendar-list.component'; +import { CreateExamCalenderSearchComponent } from './presenter/search/create-exam-calender-search/create-exam-calender-search.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamCalendarRouter, + children: [ + { + path: '', + component: CreateExamCalenderContainer + }, + { + path: 'add', + component: CreateExamCalendarFormComponent + }, + { + path: 'edit/:id', + component: CreateExamCalendarFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamCalendarRouter, + CreateExamCalenderContainer, + CreateExamCalendarFormComponent, + CreateExamCalendarListComponent, + CreateExamCalenderSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateExamCalendarModule { } diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.html b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.html new file mode 100644 index 0000000..1b9f42f --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.html @@ -0,0 +1,103 @@ +
+  {{calendarForm.getRawValue() | json}}
+
+
+

กำหนดปฎิทินของรอบสอบ {{testingInfoData?.testing_information_name}}

+ + + ปฏิทินกิจกรรมอื่นๆ + + +
+
+
+ + +
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ปฏิทินการสอบ {{element.calendar_type_name_th}} วันที่เริ่มต้น {{element.start_datetime | thaidate}} วันที่สิ้นสุด {{element.end_datetime | thaidate}} +
+ +
+
ไม่มีข้อมูล
+
+
+
+ + + +
+
+ +
+  {{setexamform.getRawValue() | json}}
+
diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.scss b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.spec.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.spec.ts new file mode 100644 index 0000000..22b3789 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamCalendarFormComponent } from './create-exam-calendar-form.component'; + +describe('CreateExamCalendarFormComponent', () => { + let component: CreateExamCalendarFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamCalendarFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamCalendarFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.ts new file mode 100644 index 0000000..cc7ceec --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/form/create-exam-calendar-form/create-exam-calendar-form.component.ts @@ -0,0 +1,410 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {MatTableDataSource} from '@angular/material/table'; + +@Component({ + selector: 'app-create-exam-calendar-form', + templateUrl: './create-exam-calendar-form.component.html', + styleUrls: ['./create-exam-calendar-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamCalendarFormComponent extends BaseForm implements OnInit { + Today; + testingInfoData; + setexamform: FormGroup; + calendarForm: FormGroup; + dataSource = new MatTableDataSource(); + displayedColumns: string[] = ['1', '2', '3', '4']; + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + calendarLists; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + constructor( + public fb: FormBuilder, + public formBuilder: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private AcademicSemSV: AcademicSemesterService, + private AcademicYearSV: AcademicYearService, + private CalendarTypeSV: CalendarTypeService, + private TestInformationSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + super( + router, + activeRoute, + fb, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + start_datetime: null, + end_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.calendarForm = this.formBuilder.group({ + calendar_type_uid: [null, Validators.required], + calendar_type_name_th: null, + start_datetime: [null, Validators.required], + end_datetime: [null, Validators.required], + }); + } + + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + console.log(data) + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + ngOnInit(): void { + this.Today = formatDate(new Date(), 'yyyy-MM-dd', 'en-US'); + this.CalendarTypeSV.getAll().subscribe( + result => { + this.calendarLists = result; + } + ); + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + }), + tap(x => this.add3Edit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + break; + } + } + + add3Edit(data){ + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + } + + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + const table = form2.getRawValue(); + this.dataSource.data = table; + } + + addPeriodEdit(x){ + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + addSubject(x){ + const form = this.setexamform.get('testing_subjects') as FormArray; + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + + setcalendarForm(selectCalendar){ + const CalendarChoose = this.calendarLists.filter(x => x.calendar_type_uid === selectCalendar); + this.calendarForm.get('calendar_type_name_th').setValue(CalendarChoose[0].calendar_type_name_th); + } + + setDatecalendarForm(choose, Date){ + const Dateset:any = formatDate(Date, 'yyyy-MM-dd', 'en-US') + switch(choose) { + case 'start': { + this.calendarForm.get('start_datetime').setValue(Dateset); + break; + } + case 'end': { + this.calendarForm.get('end_datetime').setValue(Dateset); + break; + } + } + } + + addCalendar(){ + const form = this.calendarForm.getRawValue(); + const form2 = this.setexamform.get('testing_calendars') as FormArray; + console.log(form); + form2.push(this.testing_calendars(form)); + const table = form2.getRawValue(); + this.dataSource.data = table; + // this.calendarForm.reset(null); + this.calendarForm.get('calendar_type_uid').setValue(null); + this.calendarForm.get('start_datetime').setValue(null); + this.calendarForm.get('end_datetime').setValue(null); + this.calendarForm.get('calendar_type_name_th').setValue(null); + } + + removeArray(i){ + const form = this.setexamform.get('testing_calendars') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource.data = table; + } + + save(){ + switch (this.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back(){ + this.location.back() + } + +} diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.html b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.html new file mode 100644 index 0000000..16d2570 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.html @@ -0,0 +1,89 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ + +
+
+
diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.scss b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.spec.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.spec.ts new file mode 100644 index 0000000..ad5373e --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamCalendarListComponent } from './create-exam-calendar-list.component'; + +describe('CreateExamCalendarListComponent', () => { + let component: CreateExamCalendarListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamCalendarListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamCalendarListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.ts new file mode 100644 index 0000000..a99607c --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/list/create-exam-calendar-list/create-exam-calendar-list.component.ts @@ -0,0 +1,65 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; + +@Component({ + selector: 'app-create-exam-calendar-list', + templateUrl: './create-exam-calendar-list.component.html', + styleUrls: ['./create-exam-calendar-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamCalendarListComponent extends BaseList implements OnInit, OnChanges { + + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + '10', + 'created_datetime', + '7' + ]; + private reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.html b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.html new file mode 100644 index 0000000..578bba0 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.scss b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.spec.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.spec.ts new file mode 100644 index 0000000..454a912 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamCalenderSearchComponent } from './create-exam-calender-search.component'; + +describe('CreateExamCalenderSearchComponent', () => { + let component: CreateExamCalenderSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamCalenderSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamCalenderSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.ts b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.ts new file mode 100644 index 0000000..7fc416b --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/presenter/search/create-exam-calender-search/create-exam-calender-search.component.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {Observable} from 'rxjs'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-create-exam-calender-search', + templateUrl: './create-exam-calender-search.component.html', + styleUrls: ['./create-exam-calender-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamCalenderSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-calendar/router/create-exam-calendar-router.ts b/src/app/feature/create-exam/create-exam-calendar/router/create-exam-calendar-router.ts new file mode 100644 index 0000000..4a9e205 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-calendar/router/create-exam-calendar-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamCalendarRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.html b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.html new file mode 100644 index 0000000..e62fadb --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.html @@ -0,0 +1,10 @@ + + diff --git a/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.scss b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.spec.ts b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.spec.ts new file mode 100644 index 0000000..a283fec --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamConditionContainer } from './create-exam-condition.container'; + +describe('CreateExamConditionContainer', () => { + let component: CreateExamConditionContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamConditionContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamConditionContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.ts b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.ts new file mode 100644 index 0000000..046c7ca --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/container/create-exam-condition/create-exam-condition.container.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-create-exam-condition', + templateUrl: './create-exam-condition.container.html', + styleUrls: ['./create-exam-condition.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamConditionContainer implements OnInit { + + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + add(){ + this.router.navigate(['create-exam-condition/add']); + } + + edit(id){ + this.router.navigate(['create-exam-condition/edit', id]); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + expand(id){ + this.router.navigate(['create-exam-condition/expand', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-condition/create-exam-condition.module.ts b/src/app/feature/create-exam/create-exam-condition/create-exam-condition.module.ts new file mode 100644 index 0000000..edd802c --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/create-exam-condition.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamConditionRouter} from './router/create-exam-condition-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamConditionContainer } from './container/create-exam-condition/create-exam-condition.container'; +import { CreateExamConditionFormComponent } from './presenter/form/create-exam-condition-form/create-exam-condition-form.component'; +import { CreateExamConditionListComponent } from './presenter/list/create-exam-condition-list/create-exam-condition-list.component'; +import { CreateExamConditionSearchComponent } from './presenter/search/create-exam-condition-search/create-exam-condition-search.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamConditionRouter, + children: [ + { + path: '', + component: CreateExamConditionContainer + }, + { + path: 'add', + component: CreateExamConditionFormComponent + }, + { + path: 'edit/:id', + component: CreateExamConditionFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamConditionRouter, + CreateExamConditionContainer, + CreateExamConditionFormComponent, + CreateExamConditionListComponent, + CreateExamConditionSearchComponent, + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateExamConditionModule { } diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.html b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.html new file mode 100644 index 0000000..22022b2 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.html @@ -0,0 +1,31 @@ +
+
+

กำหนดเงื่อนไขของรอบสอบ {{testingInfoData?.testing_information_name}}

+

ประเภทการนำเข้าข้อมูล

+
+
+ + นักศึกษา ม.ราม Upload File & API
+ นักศึกษาโครงการ / บุคคลทั่วไป แบบ Upload File
+ บุคคลทั่วไป
+
+
+
+

ระบุเงื่อนไข

+
+
+ อัพโหลดเอกสารยืนยันตัวตน + + ลงทะเบียนสอบผ่านระบบออนไลน์ + ลงทะเบียนสอบผ่านเค้าเตอร์รับสมัคร +
+
+
+
+
+ + +
+
+ +
{{setexamform.getRawValue() | json}}
diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.scss b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.spec.ts b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.spec.ts new file mode 100644 index 0000000..4e6eab9 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamConditionFormComponent } from './create-exam-condition-form.component'; + +describe('CreateExamConditionFormComponent', () => { + let component: CreateExamConditionFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamConditionFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamConditionFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.ts b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.ts new file mode 100644 index 0000000..039de02 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/form/create-exam-condition-form/create-exam-condition-form.component.ts @@ -0,0 +1,366 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; + +@Component({ + selector: 'app-create-exam-condition-form', + templateUrl: './create-exam-condition-form.component.html', + styleUrls: ['./create-exam-condition-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamConditionFormComponent extends BaseForm implements OnInit { + // MainForm + setexamform: FormGroup; + testingInfoData; + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + constructor( + public fb: FormBuilder, + public formBuilder: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private AcademicSemSV: AcademicSemesterService, + private AcademicYearSV: AcademicYearService, + private TestInformationSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + super( + router, + activeRoute, + fb, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + } + + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + console.log(data) + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + tap(x => { + const data: any = x; + console.log(data); + this.setexamform.patchValue(data); + if (data.type_of_examinee === 'บุคคลทั่วไป'){ + this.setexamform.get('registration_type').setValue(3) + }else if(data.type_of_examinee === 'นักศึกษา') { + this.setexamform.get('registration_type').setValue(1) + + }else if(data.type_of_examinee === 'นักศึกษาโครงการพิเศษ/บุคคลทั่วไปแบบโครงการ') { + this.setexamform.get('registration_type').setValue(2) + } + }), + tap(x => this.add3Edit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + break; + } + } + + add3Edit(data){ + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + } + + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x){ + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + addSubject(x){ + const form = this.setexamform.get('testing_subjects') as FormArray; + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + + changeRegisterType(){ + const regisType = this.setexamform.get('registration_type').value; + // this.setexamform.get('is_register_verify').setValue(false); + // this.setexamform.get('is_register').setValue(false); + // this.setexamform.get('is_counter').setValue(false); + // this.setexamform.get('is_upload_document').setValue(false); + } + + save(){ + switch (this.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back(){ + this.location.back() + } + +} diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.html b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.html new file mode 100644 index 0000000..dfbd511 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.html @@ -0,0 +1,89 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ + +
+
+
diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.scss b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.spec.ts b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.spec.ts new file mode 100644 index 0000000..3dd3821 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamConditionListComponent } from './create-exam-condition-list.component'; + +describe('CreateExamConditionListComponent', () => { + let component: CreateExamConditionListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamConditionListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamConditionListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.ts b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.ts new file mode 100644 index 0000000..ce7c2d4 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/list/create-exam-condition-list/create-exam-condition-list.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-create-exam-condition-list', + templateUrl: './create-exam-condition-list.component.html', + styleUrls: ['./create-exam-condition-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamConditionListComponent extends BaseList implements OnInit, OnChanges { + + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + '9', + 'created_by', + '10', + 'created_datetime', + '7' + ]; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onExpand(id){ + this.expand.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.html b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.html new file mode 100644 index 0000000..578bba0 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.scss b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.spec.ts b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.spec.ts new file mode 100644 index 0000000..0c3b323 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamConditionSearchComponent } from './create-exam-condition-search.component'; + +describe('CreateExamConditionSearchComponent', () => { + let component: CreateExamConditionSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamConditionSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamConditionSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.ts b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.ts new file mode 100644 index 0000000..5c1c4d7 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/presenter/search/create-exam-condition-search/create-exam-condition-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-create-exam-condition-search', + templateUrl: './create-exam-condition-search.component.html', + styleUrls: ['./create-exam-condition-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamConditionSearchComponent implements OnInit { + + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-condition/router/create-exam-condition-router.ts b/src/app/feature/create-exam/create-exam-condition/router/create-exam-condition-router.ts new file mode 100644 index 0000000..d43fdda --- /dev/null +++ b/src/app/feature/create-exam/create-exam-condition/router/create-exam-condition-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamConditionRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.html b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.html new file mode 100644 index 0000000..b132900 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.html @@ -0,0 +1,13 @@ + + + + + diff --git a/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.scss b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.spec.ts b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.spec.ts new file mode 100644 index 0000000..b0828f9 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamInformationContainer } from './create-exam-information.container'; + +describe('CreateExamInformationContainer', () => { + let component: CreateExamInformationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamInformationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamInformationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.ts b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.ts new file mode 100644 index 0000000..f7212f0 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/container/create-exam-information/create-exam-information.container.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-create-exam-information', + templateUrl: './create-exam-information.container.html', + styleUrls: ['./create-exam-information.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamInformationContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + add(){ + this.router.navigate(['create-exam-information/add']); + } + + edit(id){ + this.router.navigate(['create-exam-information/edit', id]); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + expand(id){ + this.router.navigate(['create-exam-information/expand', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + console.log(err) + this.swSV.errText(err.error.description); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-information/create-exam-information.module.ts b/src/app/feature/create-exam/create-exam-information/create-exam-information.module.ts new file mode 100644 index 0000000..caaf8f8 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/create-exam-information.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamInformationRouter } from './router/create-exam-information-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamInformationContainer } from './container/create-exam-information/create-exam-information.container'; +import { CreateExamInformationSearchComponent } from './presenter/search/create-exam-information-search/create-exam-information-search.component'; +import { CreateExamInformationListComponent } from './presenter/list/create-exam-information-list/create-exam-information-list.component'; +import { CreateExamInformationFormComponent } from './presenter/form/create-exam-information-form/create-exam-information-form.component'; +import {NgxMaterialTimepickerModule} from 'ngx-material-timepicker'; + +const routes: Routes = [ + { + path: '', + component: CreateExamInformationRouter, + children: [ + { + path: '', + component: CreateExamInformationContainer + }, + { + path: 'add', + component: CreateExamInformationFormComponent + }, + { + path: 'edit/:id', + component: CreateExamInformationFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamInformationRouter, + CreateExamInformationContainer, + CreateExamInformationSearchComponent, + CreateExamInformationListComponent, + CreateExamInformationFormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + NgxMaterialTimepickerModule, + ] +}) +export class CreateExamInformationModule { } diff --git a/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.html b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.html new file mode 100644 index 0000000..66c1494 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.html @@ -0,0 +1,291 @@ +
+ +
+

ข้อมูล ของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ +
+
+
+ +
+
+ + ใช่ + ไม่ใช่ + +
+
+
+
+
+
+ + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

กำหนดวันที่

+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + + +
+ + + + +
+
+
+
+
+ +
+
+ + + + + {{ value | thaidate }} + cancel + + + + + + +
+
+
+ +

กำหนด Section

+
+
+
+ Section {{item.get('period_id').value}} + + + + + + + + + + + +
+
+
+
+ + + +
+
+ +
+
+  {{setexamform.getRawValue() | json}}
+
diff --git a/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.scss b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.scss new file mode 100644 index 0000000..89e840e --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.scss @@ -0,0 +1,10 @@ +.example-margin { + margin: 0 10px; +} + +::ng-deep .mat-calendar-body-cell.selected > .mat-calendar-body-cell-content, +::ng-deep .mat-calendar-body-cell.selected:hover > .mat-calendar-body-cell-content, +::ng-deep .mat-calendar-body-cell.selected > .mat-calendar-body-cell-content:hover { + background-color: #673ab7 !important; + color: #fff !important; +} diff --git a/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.spec.ts b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.spec.ts new file mode 100644 index 0000000..c1ec395 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamInformationFormComponent } from './create-exam-information-form.component'; + +describe('CreateExamInformationFormComponent', () => { + let component: CreateExamInformationFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamInformationFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamInformationFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.ts b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.ts new file mode 100644 index 0000000..222ff13 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/form/create-exam-information-form/create-exam-information-form.component.ts @@ -0,0 +1,542 @@ +import {Component, OnInit, ChangeDetectionStrategy, ViewChild, ChangeDetectorRef} from '@angular/core'; +import {formatDate} from '@angular/common'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {MatDatepicker, MatDatepickerInputEvent} from '@angular/material/datepicker'; +import {MatSort} from '@angular/material/sort'; +import {MatPaginator} from '@angular/material/paginator'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-create-exam-information-form', + templateUrl: './create-exam-information-form.component.html', + styleUrls: ['./create-exam-information-form.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamInformationFormComponent extends BaseForm implements OnInit { + // MainForm + setexamform: FormGroup; + academicSemList: any = []; + academicYearList: any = []; + educationTypeLists: any = []; + testingInfoData; + // ตัวจัดการวันห้ามสอบ + @ViewChild('picker7', {static: true}) _picker: MatDatepicker; + @ViewChild(MatSort, {static: true}) sort: MatSort; + @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator; + public CLOSE_ON_SELECTED = false; + public init = new Date(); + public resetModel = new Date(0); + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + today = new Date(); + daywithout = { + days_without_testing_uid: null, + date_without_testing: null, + }; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + + constructor( + public fb: FormBuilder, + public formBuilder: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private AcademicSemSV: AcademicSemesterService, + private AcademicYearSV: AcademicYearService, + private TestInformationSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + super( + router, + activeRoute, + fb, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + } + + block_days(blockdays?) { + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?) { + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?) { + console.log(data) + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?) { + return this.formBuilder.group({ + status_id: null, + is_open: data?.is_open, + print_start_time: data?.print_start_time, + print_end_time: data?.print_end_time, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: [data?.start_time, Validators.required], + }); + } + + testing_rooms(data?) { + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?) { + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + this.TestInformationSV.getDatatype().pipe( + tap(x => this.educationTypeLists = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => console.log(this.testingInfoData)), + tap(x => { + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + if (data.number_of_times_testing === null) { + this.setexamform.get('is_number_of_times_testing').setValue(false); + } + }), + tap(x => this.add3Edit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + break; + case 'add': + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form4.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + form5.clear(); + break; + } + } + + add3Edit(data) { + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + } + + addCalendaEdit(x) { + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x) { + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = (x.testing_periods[i].start_time).substring(0, 5); + if (this.state === 'edit') { + this.sectionsFakeFalse[foundIndex].print_start_time = x.testing_periods[i].print_start_time; + this.sectionsFakeFalse[foundIndex].print_end_time = x.testing_periods[i].print_end_time; + this.sectionsFakeFalse[foundIndex].testing_period_uid = x.testing_periods[i].testing_period_uid; + this.sectionsFakeFalse[foundIndex].testing_information_uid = x.testing_periods[i].testing_information_uid; + } + } + + // for (let i = 0; i < x.testing_periods.length; i++) { + // x.testing_periods[i].is_check = true + // form.push(this.testing_periods(x.testing_periods[i])); + // } + + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x) { + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + addSubject(x) { + const form = this.setexamform.get('testing_subjects') as FormArray; + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + + public dateClass = (date: Date) => { + if (this._findDate(date) !== -1) { + return ['selected']; + } + return []; + } + + public dateChanged(event: MatDatepickerInputEvent): void { + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + if (event.value) { + const date = event.value; + const index = this._findDate(date); + if (index === -1) { + this.model.push(date); + this.updateBlockdate(date); + } else { + this.model.splice(index, 1); + formblockdays.removeAt(index); + } + + this.resetModel = new Date(0); + if (!this.CLOSE_ON_SELECTED) { + const closeFn = this._picker.close; + this._picker.close = () => { + }; + this._picker['_popupComponentRef'].instance._calendar.monthView._createWeekCells() + setTimeout(() => { + this._picker.close = closeFn; + }); + } + } + } + + public remove(date: Date): void { + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + const index = this._findDate(date); + formblockdays.removeAt(index) + this.model.splice(index, 1); + } + + private _findDate(date: Date): number { + return this.model.map((m) => +m).indexOf(+date); + } + + clearNumberTestFiledandScore() { + if (this.setexamform.get('is_number_of_times_testing').value === false) { + this.setexamform.get('number_of_times_testing').setValue(null); + this.setexamform.get('times_the_score_is_calculated').setValue(1); + } + } + + updateBlockdate(date) { + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + switch (this.state) { + case 'edit': + this.daywithout.date_without_testing = formatDate(date, 'yyyy-MM-dd', 'en-US'); + formblockdays.push(this.block_days(this.daywithout)); + break; + case 'add': + // this.daywithout.id_day = null; + this.daywithout.date_without_testing = formatDate(date, 'yyyy-MM-dd', 'en-US'); + formblockdays.push(this.block_days(this.daywithout)); + break; + } + } + + save() { + switch (this.state) { + case 'edit': + this.swSV.loadingStart('กำลังบันทึกรอบสอบ'); + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + if (form1.first_student_code != null) { + form1.first_student_code = form1.first_student_code.toString(); + } + if (form1.number_of_times_testing != null) { + form1.number_of_times_testing = form1.number_of_times_testing.toString(); + } + if (form1.last_student_code != null) { + form1.last_student_code = form1.last_student_code.toString(); + } + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + + case 'add': + this.swSV.loadingStart('กำลังบันทึกรอบสอบ'); + const form = this.setexamform.getRawValue(); + form.testing_periods = form.testing_periods.filter((member) => { + return member.is_check === true; + }); + if (form.first_student_code != null) { + form.first_student_code = form.first_student_code.toString(); + } + if (form.number_of_times_testing != null) { + form.number_of_times_testing = form.number_of_times_testing.toString(); + } + if (form.last_student_code != null) { + form.last_student_code = form.last_student_code.toString(); + } + // tslint:disable-next-line:max-line-length + if (form.testing_start_datetime == null || form.testing_end_datetime == null || form.registration_start_datetime == null || form.registration_end_datetime == null) { + return this.swSV.errText('กรุณาใส่วันที่'); + } + this.TestInformationSV.add(form).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back() { + this.location.back() + } + + onChangeHour(form, data) { + console.log() + } + +} diff --git a/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.html b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.html new file mode 100644 index 0000000..9fba470 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.html @@ -0,0 +1,90 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ + + +
+
+
diff --git a/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.scss b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.scss new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.spec.ts b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.spec.ts new file mode 100644 index 0000000..7530cf5 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamInformationListComponent } from './create-exam-information-list.component'; + +describe('CreateExamInformationListComponent', () => { + let component: CreateExamInformationListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamInformationListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamInformationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.ts b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.ts new file mode 100644 index 0000000..559e49c --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/list/create-exam-information-list/create-exam-information-list.component.ts @@ -0,0 +1,84 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + OnChanges, + Input, + Output, + EventEmitter, + ViewChild, + ChangeDetectorRef +} from '@angular/core'; +import {BaseList} from "../../../../../../core/base/base-list"; +import {OBJECT} from "../../../../../../core/enum/role"; +import {AppTokenService} from "../../../../../../core/service/security/app-token.service"; +import {MatSort, Sort} from '@angular/material/sort'; +import {LiveAnnouncer} from '@angular/cdk/a11y'; + +@Component({ + selector: 'app-create-exam-information-list', + templateUrl: './create-exam-information-list.component.html', + styleUrls: ['./create-exam-information-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamInformationListComponent extends BaseList implements OnInit, OnChanges { + @ViewChild(MatSort) sort: MatSort; + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + '10', + 'created_datetime', + '7' + ]; + reload: boolean; + + constructor( + private appTokenSV: AppTokenService, + private cdr: ChangeDetectorRef, + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + this.cdr.detectChanges(); + }, 5000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onExpand(id){ + this.expand.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.html b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.html new file mode 100644 index 0000000..c369226 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.scss b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.spec.ts b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.spec.ts new file mode 100644 index 0000000..30da90b --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamInformationSearchComponent } from './create-exam-information-search.component'; + +describe('CreateExamInformationSearchComponent', () => { + let component: CreateExamInformationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamInformationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamInformationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.ts b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.ts new file mode 100644 index 0000000..1d58391 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/presenter/search/create-exam-information-search/create-exam-information-search.component.ts @@ -0,0 +1,52 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-create-exam-information-search', + templateUrl: './create-exam-information-search.component.html', + styleUrls: ['./create-exam-information-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamInformationSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-information/router/create-exam-information-router.ts b/src/app/feature/create-exam/create-exam-information/router/create-exam-information-router.ts new file mode 100644 index 0000000..d58f28d --- /dev/null +++ b/src/app/feature/create-exam/create-exam-information/router/create-exam-information-router.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + // selector: 'app-create-exam-information-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamInformationRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.html b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.html new file mode 100644 index 0000000..9c6586e --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.scss b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.spec.ts b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.spec.ts new file mode 100644 index 0000000..10b71d2 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamRoomContainer } from './create-exam-room.container'; + +describe('CreateExamRoomContainer', () => { + let component: CreateExamRoomContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamRoomContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamRoomContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.ts b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.ts new file mode 100644 index 0000000..96b6118 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/container/create-exam-room/create-exam-room.container.ts @@ -0,0 +1,62 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-create-exam-room', + templateUrl: './create-exam-room.container.html', + styleUrls: ['./create-exam-room.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamRoomContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + add(){ + this.router.navigate(['create-exam-room/add']); + } + + edit(id){ + this.router.navigate(['create-exam-room/edit', id]); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-room/create-exam-room.module.ts b/src/app/feature/create-exam/create-exam-room/create-exam-room.module.ts new file mode 100644 index 0000000..77d48f2 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/create-exam-room.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamRoomRouter } from './router/create-exam-room-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamRoomContainer } from './container/create-exam-room/create-exam-room.container'; +import { CreateExamRoomFormComponent } from './presenter/form/create-exam-room-form/create-exam-room-form.component'; +import { CreateExamRoomListComponent } from './presenter/list/create-exam-room-list/create-exam-room-list.component'; +import { CreateExamRoomSearchComponent } from './presenter/search/create-exam-room-search/create-exam-room-search.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamRoomRouter, + children: [ + { + path: '', + component: CreateExamRoomContainer + }, + { + path: 'add', + component: CreateExamRoomFormComponent + }, + { + path: 'edit/:id', + component: CreateExamRoomFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamRoomRouter, + CreateExamRoomContainer, + CreateExamRoomFormComponent, + CreateExamRoomListComponent, + CreateExamRoomSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateExamRoomModule { } diff --git a/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.html b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.html new file mode 100644 index 0000000..b9f2135 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.html @@ -0,0 +1,131 @@ +
+
+ + + +

กำหนดห้องสอบของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject2.testing_field_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{subject3.testing_room_name_th}} + + +
+ +
+ +
+
+
+ + +
+
+ {{this.setroomcenterForm.invalid}} +
+
+
+
+ +

แสดงรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{element.branch_name_th}} สนามสอบ {{element.testing_field_name_th}} ห้องสอบ {{element.testing_room_name_th}} สุ่มที่นั่งสอบ + + + จัดการที่นั่งสอบ* + + +
+ +
+
ไม่มีข้อมูล
+
+
+
+
+ + +
+
+
+  {{setexamform.getRawValue() | json}}
+
diff --git a/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.scss b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.spec.ts b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.spec.ts new file mode 100644 index 0000000..9e09c44 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamRoomFormComponent } from './create-exam-room-form.component'; + +describe('CreateExamRoomFormComponent', () => { + let component: CreateExamRoomFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamRoomFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamRoomFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.ts b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.ts new file mode 100644 index 0000000..1c36307 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/form/create-exam-room-form/create-exam-room-form.component.ts @@ -0,0 +1,633 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {catchError, tap} from 'rxjs/operators'; +import {MatTableDataSource} from '@angular/material/table'; +import { + SetExamInformationDialogComponent +} from '../../../../../set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import {data} from 'autoprefixer'; +import {Subject, throwError} from 'rxjs'; + +@Component({ + selector: 'app-create-exam-room-form', + templateUrl: './create-exam-room-form.component.html', + styleUrls: ['./create-exam-room-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamRoomFormComponent extends BaseForm implements OnInit { + setroomcenterForm: FormGroup; + subjectList: any = []; + subjectList2: any = []; + subjectList3: any = []; + dataSource3 = new MatTableDataSource(); + displayedColumns3: string[] = ['1', '2', '3', '5', '6', '7']; + testingInfoData; + private curSub: any; + private curSub2: any; + private curSub3: any; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + + constructor( + private academicSemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.setroomcenterForm = this.formBuilder.group({ + branch_name_th: null, + branch_uid: [null, Validators.required], + testing_center_uid: [null, Validators.required], + testing_field_name_th: null, + testing_field_uid: [null, Validators.required], + testing_room_name_th: null, + testing_auth_name: null, + is_random_seat: null, + }); + } + + block_days(blockdays?) { + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?) { + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?) { + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?) { + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + // MainForm + setexamform: FormGroup; + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList = this.clearBranchList(x)), + // ).subscribe(); + // await this.testingFieldSV.getAll().pipe( + // tap(x => this.subjectList2 = x), + // ).subscribe(); + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList3 = x), + // ).subscribe(); + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList3 = x), + // ).subscribe(); + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + const res: any = x; + console.log(res) + this.getBranchList(res) + }), + tap(x => { + form5.clear(); + form3.clear(); + form2.clear(); + form.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + }), + tap(x => this.add3Edit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + } + } + + checkAcaSemandAcaYear(data) { + const returndata = { + academic_year_uid: null, + academic_semester_uid: null + }; + const result = new Subject(); + this.academicSemSV.query(`?academic_semester_code=${data.academic_semester_code}`).subscribe( + res => { + returndata.academic_semester_uid = res[0].academic_semester_uid + this.academicYearSV.query(`?academic_year_code=${data.academic_year_code}`).subscribe( + res2 => { + returndata.academic_year_uid = res2[0].academic_year_uid + result.next(returndata); + } + ); + } + ); + return result.asObservable(); + } + + async getBranchList(data) { + await this.checkAcaSemandAcaYear(data).subscribe( + res => { + if (res.academic_year_uid != null && res.academic_semester_uid != null) { + this.testcenterSV.query(`?academic_year_uid=${res.academic_year_uid}&academic_semester_uid=${res.academic_semester_uid}`).pipe( + // tap(x => this.subjectList = x), + tap(x => this.subjectList = this.clearBranchlist(x)), + ).subscribe(); + } + } + ); + } + + clearBranchlist(arr) { + const resArr = []; + arr.filter(function (item: any): any { + const i = resArr.findIndex(x => (x.branch_name_th === item.branch_name_th)); + if (i <= -1) { + resArr.push(item); + } + return null; + }); + return resArr + } + + add3Edit(data) { + console.log(data) + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + add3EditReserve(data) { + console.log(data) + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + addCalendaEdit(x) { + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x) { + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x) { + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + } + } + + addSubject(x) { + const form = this.setexamform.get('testing_subjects') as FormArray; + if (x.testing_subjects != null) { + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + } + + add3() { + const form = this.setroomcenterForm.getRawValue(); + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const everyResult = form3.getRawValue().some((member) => { + return member.testing_center_uid === form.testing_center_uid + }) + if (everyResult) { + return this.swSV.errText('มีห้องสอบซ้ำ') + } + form3.push(this.testing_rooms(form)); + const table = form3.getRawValue(); + this.dataSource3.data = table; + const index = table.findIndex( + member => member.testing_center_uid === form.testing_center_uid && + member.branch_uid === form.branch_uid && + member.testing_field_uid === form.testing_field_uid + ); + if (index !== -1) { + this.setroomcenterForm.reset(); + this.openDialogexam(form.testing_center_uid, index) + } else { + this.swSV.errText('ไม่พบห้องสอบกรุณาลบสร้างห้องสอบใหม่') + } + + } + + setFieldname(uid) { + const branch = this.subjectList.filter((x) => { + return x.branch_uid === uid; + }); + this.setroomcenterForm.get('branch_name_th').setValue(branch[0].branch_name_th); + this.testingFieldSV.getByBrandID(uid).pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe(); + } + + setRoomname(uid) { + const branch = this.subjectList2.filter((x) => { + return x.testing_field_uid === uid; + }); + this.setroomcenterForm.get('testing_field_name_th').setValue(branch[0].testing_field_name_th); + const academic_year_name_th = this.setexamform.get('academic_year_code').value + const academic_semester_name_th = this.setexamform.get('academic_semester_code').value + this.testcenterSV.query(`?testing_field_uid=${uid}&academic_year_name_th=${academic_year_name_th}&academic_semester_name_th=${academic_semester_name_th}`).pipe( + tap(x => this.subjectList3 = x), + ).subscribe(); + } + + setRoomnameth(uid) { + const branch = this.subjectList3.filter((x) => { + return x.testing_center_uid === uid; + }); + console.log(branch) + this.setroomcenterForm.get('testing_room_name_th').setValue(branch[0].testing_room_name_th); + // this.setroomcenterForm.get('academic_year_uid').setValue(branch[0].academic_year_uid); + // this.setroomcenterForm.get('academic_semester_uid').setValue(branch[0].academic_semester_uid); + } + + displayBranchname(uid) { + if (uid && this.subjectList) return this.subjectList.find(x => x.branch_uid === uid)?.branch_name_th + if (uid && !this.subjectList) return this.curSub?.branch_name_th + } + + displayFieldname(uid) { + if (uid && this.subjectList2) return this.subjectList2.find(x => x.testing_field_uid === uid)?.testing_field_name_th + if (uid && !this.subjectList2) return this.curSub2?.testing_field_name_th + } + + displayRoomname(uid) { + if (uid && this.subjectList3) return this.subjectList3.find(x => x.testing_center_uid === uid)?.testing_room_name_th + if (uid && !this.subjectList3) return this.curSub3?.testing_room_name_th + } + + selectionValue(data, i) { + switch (this.state) { + case 'edit': + let israndom = true; + if (data.is_random_seat === true) { + israndom = false; + } else if (data.is_random_seat === false) { + israndom = true; + } + const form = this.setexamform.get('testing_rooms') as FormArray; + form.at(i).get('is_random_seat').setValue(israndom); + const table = form.getRawValue(); + this.dataSource3.data = table; + break; + } + } + + openDialogexam(id: any, index: any) { + const form = this.setexamform.get('testing_rooms') as FormArray; + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + const centerList = form.getRawValue(); + switch (this.state) { + case 'edit': + console.log(centerList[index]) + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1200px', + height: '700px', + data: { + id, + centerList: centerList[index], + subjectlist: subjectForm.getRawValue(), + state: this.state, + } + }); + dialogRefedit.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const testseat = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(testseat); + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + this.cdRef.detectChanges(); + } + ); + break; + case 'add': + const dialogRefadd = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + subjectlist: subjectForm.getRawValue(), + state: this.state, + } + }); + dialogRefadd.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let i = 0; i < testseat.testing_seat.length; i++) { + formArray.push(testseatdata.get('testing_seat').controls[i]); + } + this.cdRef.detectChanges(); + } + ); + break; + } + } + + removeArray3(i) { + const form = this.setexamform.get('testing_rooms') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + save() { + switch (this.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back() { + this.location.back() + } + +} diff --git a/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.html b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.html new file mode 100644 index 0000000..5026fb2 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.html @@ -0,0 +1,89 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ + +
+
+
diff --git a/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.scss b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.spec.ts b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.spec.ts new file mode 100644 index 0000000..e29adab --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamRoomListComponent } from './create-exam-room-list.component'; + +describe('CreateExamRoomListComponent', () => { + let component: CreateExamRoomListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamRoomListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamRoomListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.ts b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.ts new file mode 100644 index 0000000..f9f70bd --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/list/create-exam-room-list/create-exam-room-list.component.ts @@ -0,0 +1,61 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; + +@Component({ + selector: 'app-create-exam-room-list', + templateUrl: './create-exam-room-list.component.html', + styleUrls: ['./create-exam-room-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamRoomListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + @Input() subjectListFake: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + 'is_open', + 'created_datetime', + '7' + ]; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + this.subjectListFake = this.updateMatTable(this.subjectListFake ? this.subjectListFake : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.html b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.html new file mode 100644 index 0000000..578bba0 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.scss b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.spec.ts b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.spec.ts new file mode 100644 index 0000000..d52a986 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamRoomSearchComponent } from './create-exam-room-search.component'; + +describe('CreateExamRoomSearchComponent', () => { + let component: CreateExamRoomSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamRoomSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamRoomSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.ts b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.ts new file mode 100644 index 0000000..60d209d --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/presenter/search/create-exam-room-search/create-exam-room-search.component.ts @@ -0,0 +1,52 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-create-exam-room-search', + templateUrl: './create-exam-room-search.component.html', + styleUrls: ['./create-exam-room-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamRoomSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-room/router/create-exam-room-router.ts b/src/app/feature/create-exam/create-exam-room/router/create-exam-room-router.ts new file mode 100644 index 0000000..3210534 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-room/router/create-exam-room-router.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + // selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamRoomRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.html new file mode 100644 index 0000000..20601ef --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.spec.ts new file mode 100644 index 0000000..e5f5e52 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSetupPeriodBySubjectContainer } from './create-exam-setup-period-by-subject.container'; + +describe('CreateExamSetupPeriodBySubjectContainer', () => { + let component: CreateExamSetupPeriodBySubjectContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSetupPeriodBySubjectContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSetupPeriodBySubjectContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.ts new file mode 100644 index 0000000..c247d01 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container.ts @@ -0,0 +1,36 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Router} from "@angular/router"; +import {TestingInformationService} from "../../../../../core/service/testing-information/testing-information.service"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {Observable} from "rxjs"; + +@Component({ + selector: 'app-create-exam-setup-period-by-subject', + templateUrl: './create-exam-setup-period-by-subject.container.html', + styleUrls: ['./create-exam-setup-period-by-subject.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSetupPeriodBySubjectContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + edit(id){ + this.router.navigate(['special-period/view', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.module.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.module.ts new file mode 100644 index 0000000..fd75967 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamSetupPeriodBySubjectRouter } from './router/create-exam-setup-period-by-subject-router'; +import { CreateExamSetupPeriodBySubjectContainer } from './container/create-exam-setup-period-by-subject/create-exam-setup-period-by-subject.container'; +import { SetupPeriodBySubjectTestinforListComponent } from './presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component'; +import { SetupPeriodBySubjectTestinforSearchComponent } from './presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SetupPeriodBySubjectListComponent } from './presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component'; +import { SetupPeriodBySubjectInforComponent } from './presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component'; +import { DialogCreatePeriodByDayComponent } from './presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamSetupPeriodBySubjectRouter, + children: [ + { + path: '', + component: CreateExamSetupPeriodBySubjectContainer + }, + { + path: 'view/:testInforId', + component: SetupPeriodBySubjectListComponent + }, + { + path: 'view/:testInforId/:subjectId', + component: SetupPeriodBySubjectInforComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamSetupPeriodBySubjectRouter, + CreateExamSetupPeriodBySubjectContainer, + SetupPeriodBySubjectTestinforListComponent, + SetupPeriodBySubjectTestinforSearchComponent, + SetupPeriodBySubjectListComponent, + SetupPeriodBySubjectInforComponent, + DialogCreatePeriodByDayComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateExamSetupPeriodBySubjectModule { } diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.html new file mode 100644 index 0000000..fc25284 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.html @@ -0,0 +1,38 @@ +
+
+
+ + + + + + +
+ + +
+
+
+
+ คาบสอบ {{item.get('period_id').value}} + +
+
+
+
+ +
+ + +
+
+
+ + + diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.spec.ts new file mode 100644 index 0000000..64e91b5 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogCreatePeriodByDayComponent } from './dialog-create-period-by-day.component'; + +describe('DialogCreatePeriodByDayComponent', () => { + let component: DialogCreatePeriodByDayComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogCreatePeriodByDayComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogCreatePeriodByDayComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.ts new file mode 100644 index 0000000..f5c6dbd --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/dialog/dialog-create-period-by-day/dialog-create-period-by-day.component.ts @@ -0,0 +1,229 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {FormArray, FormBuilder} from "@angular/forms"; +import {CalendarTypeService} from "../../../../../../core/service/settings/calendar-type.service"; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {catchError, tap} from "rxjs/operators"; +import {throwError} from "rxjs"; +import { + TestingInformationService +} from "../../../../../../core/service/testing-information/testing-information.service"; +import { + TestingSubjectAddDateService +} from "../../../../../../core/service/testing-information/testing-subject-add-date.service"; +import {Location} from '@angular/common'; + + +@Component({ + selector: 'app-dialog-create-period-by-day', + templateUrl: './dialog-create-period-by-day.component.html', + styleUrls: ['./dialog-create-period-by-day.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogCreatePeriodByDayComponent implements OnInit { + form; + startDate; + endDate; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + constructor( + private fb: FormBuilder, + private TestInformationSV: TestingInformationService, + private TestSubjectAddDateSV: TestingSubjectAddDateService, + private calendarSV: CalendarTypeService, + private cdr: ChangeDetectorRef, + public location: Location, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + create_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_date: null, + testing_subject_uid: null, + testing_subject_add_date_uid: null, + period: this.fb.array([ + this.testing_periods() + ]) + }); + } + + testing_periods(data?){ + return this.fb.group({ + status_id: 1, + create_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + ngOnInit(): void { + const form = this.form.get('period') as FormArray; + console.log(this.data); + switch (this.data.state) { + case 'edit': + form.clear(); + // this.form.get('testing_subject_uid').setValue(this.data.testsubjectId); + // this.form.get('testing_subject_add_date_uid').setValue(this.data.testingSubjectAddDateId); + this.TestSubjectAddDateSV.get(this.data.testingSubjectAddDateId).pipe( + tap(x => console.log(x)), + tap(x => this.form.patchValue(x)), + tap(x => this.editPeriodEdit(x)), + ).subscribe(); + break; + case 'add': + form.clear(); + this.form.get('testing_subject_uid').setValue(this.data.testsubjectId); + this.TestInformationSV.get(this.data.testInforId).pipe( + tap(x => { + console.log(x); + const data: any = x; + this.startDate = data.testing_start_datetime; + this.endDate = data.testing_end_datetime; + }), + tap(x => this.addPeriodEdit(x)), + ).subscribe(); + break; + } + } + + editPeriodEdit(x){ + const form = this.form.get('period') as FormArray; + const Array = x.period; + console.log(Array); + this.TestInformationSV.get(this.data.testInforId).pipe( + tap(x => { + const data: any = x; + this.startDate = data.testing_start_datetime; + this.endDate = data.testing_end_datetime; + // Filter Array By Array + // const res = Array.findIndex(item1 => + // !!data.testing_periods.find(item2 => item1 === item2.period_id) + // ); + for (let i = 0; i < data.testing_periods.length; i++){ + form.push(this.testing_periods(data.testing_periods[i])); + } + }), + tap(x => { + for (let i = 0; i < Array.length; i++){ + const foundIndex = form.getRawValue().findIndex(v => v.period_id === Array[i]); + if (foundIndex !== null){ + form.at(foundIndex).get('is_check').setValue(true); + } + } + + }), + ).subscribe(); + } + + addPeriodEdit(x){ + const form = this.form.get('period') as FormArray; + const Array = x.testing_periods; + + const SortArray = Array.sort((a, b) => a.period_id - b.period_id); + console.log(SortArray); + + for (let i = 0; i < SortArray.length; i++) { + // const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + // this.sectionsFakeFalse[foundIndex].is_check = true; + // this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + console.log(SortArray[i]); + form.push(this.testing_periods(SortArray[i])); + } + } + + save(){ + const form = this.form.getRawValue() + form.period = form.period.filter((member) => { + return member.is_check === true; + }); + const PeriodList = form.period.filter((member) => { + return member.is_check === true; + }); + const period: any = []; + console.log(PeriodList); + for (let i = 0; i < PeriodList.length; i++) { + period.push(PeriodList[i].period_id) + } + // form.testing_periods.clear() + form.period = period; + // const sendData = form; + switch (this.data.state) { + case 'edit': + console.log(form) + this.TestSubjectAddDateSV.update2(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.cdr.detectChanges()), + tap(x => this.dialogRef.close('success')), + // tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe(); + break; + case 'add': + console.log(form) + this.TestSubjectAddDateSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.cdr.detectChanges()), + tap(x => this.dialogRef.close('success')), + // tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe(); + break; + } + } + + cancel(){ + this.dialogRef.close('success') + } + + + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.html new file mode 100644 index 0000000..3f32254 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.html @@ -0,0 +1,81 @@ +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+

แสดงผลรายการค้นหา

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} วันที่สอบ {{x.testing_date | thaidate}} คาบสอบ {{x.period}} เครื่องมือ +
+ + +
+
+ +
+
+
+ + diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.spec.ts new file mode 100644 index 0000000..56a7bc2 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetupPeriodBySubjectInforComponent } from './setup-period-by-subject-infor.component'; + +describe('SetupPeriodBySubjectInforComponent', () => { + let component: SetupPeriodBySubjectInforComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetupPeriodBySubjectInforComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetupPeriodBySubjectInforComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.ts new file mode 100644 index 0000000..6c5936e --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-infor/setup-period-by-subject-infor.component.ts @@ -0,0 +1,171 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {MatDialog} from '@angular/material/dialog'; +import { + DialogCreatePeriodByDayComponent +} from '../../dialog/dialog-create-period-by-day/dialog-create-period-by-day.component'; +import { + TestingSubjectAddDateService +} from '../../../../../../core/service/testing-information/testing-subject-add-date.service'; +import {throwError} from "rxjs"; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; + +@Component({ + selector: 'app-setup-period-by-subject-infor', + templateUrl: './setup-period-by-subject-infor.component.html', + styleUrls: ['./setup-period-by-subject-infor.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetupPeriodBySubjectInforComponent extends BaseList implements OnInit { + testInforId: any; + testsubjectId: any; + subjectList: any = []; + subjectDetail: any = []; + query = { + testing_subject_uid: null, + testing_information_uid: null, + }; + column = ['0', '1', '2', '3']; + constructor( + private dialog: MatDialog, + private router: Router, + private activeRouter: ActivatedRoute, + private TestinforSV: TestingInformationService, + private TestSubjectAddDateSV: TestingSubjectAddDateService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super(); + } + + ngOnInit(): void { + this.activeRouter.params.pipe( + // tap(x => x.id ? this.state = 'edit' : this.state = 'add'), + tap(x => console.log(x)), + tap(x => x.testInforId ? this.testInforId = x.testInforId : this.testInforId = null), + tap(x => x.testInforId ? this.query.testing_information_uid = x.testInforId : this.query.testing_information_uid = null), + tap(x => x.subjectId ? this.testsubjectId = x.subjectId : this.testsubjectId = null), + tap(x => x.subjectId ? this.query.testing_subject_uid = x.subjectId : this.query.testing_subject_uid = null), + tap(x => + this.TestinforSV.get(x.testInforId).pipe( + tap(y => { + const data: any = y; + this.subjectDetail = data.testing_subjects.filter(x => { + return x.testing_subject_uid === this.testsubjectId; + }); + // this.subjectDetail = this.updateMatTable(data.testing_subjects ? data.testing_subjects : []); + }), + tap(y => console.log(this.subjectDetail)), + tap(y => this.cdr.detectChanges()), + ).subscribe() + ), + tap(x => + this.TestSubjectAddDateSV.search(`?${this.createQueryStringFromObject(this.query)}`).pipe( + tap(y => { + const data: any = y; + console.log(data); + this.subjectDetail = data; + // this.subjectDetail = data.testing_subjects.filter(x => { + // return x.testing_subject_uid === this.testsubjectId; + // }); + this.subjectList = this.updateMatTable(data ? data : []); + }), + tap(y => console.log(this.subjectList)), + tap(y => this.cdr.detectChanges()), + ).subscribe() + ), + ).subscribe(); + } + + onAdd(){ + const dialogRef = this.dialog.open(DialogCreatePeriodByDayComponent, { + width: '700px', + height: '350px', + data: { + testInforId : this.testInforId, + testsubjectId : this.testsubjectId, + state : 'add', + } + }); + dialogRef.afterClosed().pipe( + tap(x => console.log(x)), + tap(x => { + this.TestSubjectAddDateSV.search(`?${this.createQueryStringFromObject(this.query)}`).pipe( + tap(y => { + const data: any = y; + this.subjectList = this.updateMatTable(data ? data : []); + }), + tap(y => this.cdr.detectChanges()), + ).subscribe(); + }), + ).subscribe(); + } + + onEdit(id){ + const dialogRef = this.dialog.open(DialogCreatePeriodByDayComponent, { + width: '700px', + height: '350px', + data: { + testInforId : this.testInforId, + testsubjectId : this.testsubjectId, + testingSubjectAddDateId : id, + state : 'edit', + } + }); + dialogRef.afterClosed().pipe( + tap(x => console.log(x)), + tap(x => { + this.TestSubjectAddDateSV.search(`?${this.createQueryStringFromObject(this.query)}`).pipe( + tap(y => { + const data: any = y; + this.subjectList = this.updateMatTable(data ? data : []); + }), + tap(y => this.cdr.detectChanges()), + ).subscribe(); + }), + ).subscribe(); + } + + onDelete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestSubjectAddDateSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => { + this.TestSubjectAddDateSV.search(`?${this.createQueryStringFromObject(this.query)}`).pipe( + tap(y => { + const data: any = y; + this.subjectList = this.updateMatTable(data ? data : []); + }), + tap(y => this.cdr.detectChanges()), + ).subscribe(); + }), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + + createQueryStringFromObject = (object: any):string => { + let queryStr: string = '' + + for (const key in object) { + if (object[key]) { + queryStr += `${key}=${object[key]}&` + } + } + let lastIndex = queryStr.lastIndexOf('&') + queryStr = queryStr.slice(0,lastIndex) + return queryStr + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.html new file mode 100644 index 0000000..9b73c3c --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.html @@ -0,0 +1,53 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} สถานะ +
+ สร้างแล้ว +
+
+ ยังไม่ได้สร้าง +
+
เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.spec.ts new file mode 100644 index 0000000..a4b03ff --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetupPeriodBySubjectListComponent } from './setup-period-by-subject-list.component'; + +describe('SetupPeriodBySubjectListComponent', () => { + let component: SetupPeriodBySubjectListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetupPeriodBySubjectListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetupPeriodBySubjectListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.ts new file mode 100644 index 0000000..81c7042 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-list/setup-period-by-subject-list.component.ts @@ -0,0 +1,56 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {tap} from 'rxjs/operators'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {BaseList} from "../../../../../../core/base/base-list"; + +@Component({ + selector: 'app-setup-period-by-subject-list', + templateUrl: './setup-period-by-subject-list.component.html', + styleUrls: ['./setup-period-by-subject-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetupPeriodBySubjectListComponent extends BaseList implements OnInit { + testInforId: any; + subjectList: any = []; + column = [ + 'subject_code', + 'subject_name_th', + 'add_date_status', + '4' + ]; + reload: boolean; + constructor( + private router: Router, + private activeRouter: ActivatedRoute, + private TestinforSV: TestingInformationService, + ) { + super(); + } + + ngOnInit(): void { + this.activeRouter.params.pipe( + // tap(x => x.id ? this.state = 'edit' : this.state = 'add'), + tap(x => x.testInforId ? this.testInforId = x.testInforId : this.testInforId = null), + tap(x => + this.TestinforSV.get(x.testInforId).pipe( + tap(y => { + const data: any = y; + this.subjectList = this.updateMatTable(data.testing_subjects ? data.testing_subjects : []); + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + }) + ).subscribe() + ), + ).subscribe(); + } + + onEdit(id){ + this.router.navigate([`special-period/view/${this.testInforId}/`, id]); + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.html new file mode 100644 index 0000000..9f3c7e7 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.html @@ -0,0 +1,83 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+ +
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.spec.ts new file mode 100644 index 0000000..9f4c3b5 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetupPeriodBySubjectTestinforListComponent } from './setup-period-by-subject-testinfor-list.component'; + +describe('SetupPeriodBySubjectTestinforListComponent', () => { + let component: SetupPeriodBySubjectTestinforListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetupPeriodBySubjectTestinforListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetupPeriodBySubjectTestinforListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.ts new file mode 100644 index 0000000..e5ce850 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/list/setup-period-by-subject-testinfor-list/setup-period-by-subject-testinfor-list.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; + +@Component({ + selector: 'app-setup-period-by-subject-testinfor-list', + templateUrl: './setup-period-by-subject-testinfor-list.component.html', + styleUrls: ['./setup-period-by-subject-testinfor-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetupPeriodBySubjectTestinforListComponent extends BaseList implements OnInit, OnChanges{ + @Input() subjectList: any = []; + @Output() edit = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + 'is_open', + 'created_datetime', + '7' + ]; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.html b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.scss b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.spec.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.spec.ts new file mode 100644 index 0000000..5aa7e53 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetupPeriodBySubjectTestinforSearchComponent } from './setup-period-by-subject-testinfor-search.component'; + +describe('SetupPeriodBySubjectTestinforSearchComponent', () => { + let component: SetupPeriodBySubjectTestinforSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetupPeriodBySubjectTestinforSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetupPeriodBySubjectTestinforSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.ts new file mode 100644 index 0000000..21604e6 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/presenter/search/setup-period-by-subject-testinfor-search/setup-period-by-subject-testinfor-search.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; + +@Component({ + selector: 'app-setup-period-by-subject-testinfor-search', + templateUrl: './setup-period-by-subject-testinfor-search.component.html', + styleUrls: ['./setup-period-by-subject-testinfor-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetupPeriodBySubjectTestinforSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-setup-period-by-subject/router/create-exam-setup-period-by-subject-router.ts b/src/app/feature/create-exam/create-exam-setup-period-by-subject/router/create-exam-setup-period-by-subject-router.ts new file mode 100644 index 0000000..e22bfe3 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-setup-period-by-subject/router/create-exam-setup-period-by-subject-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSetupPeriodBySubjectRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.html b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.html new file mode 100644 index 0000000..2fb993b --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.scss b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.spec.ts b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.spec.ts new file mode 100644 index 0000000..62fabd0 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSubjectContainer } from './create-exam-subject.container'; + +describe('CreateExamSubjectContainer', () => { + let component: CreateExamSubjectContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSubjectContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSubjectContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.ts b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.ts new file mode 100644 index 0000000..a5d37be --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/container/create-exam-subject/create-exam-subject.container.ts @@ -0,0 +1,62 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-create-exam-subject', + templateUrl: './create-exam-subject.container.html', + styleUrls: ['./create-exam-subject.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSubjectContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + edit(id){ + this.router.navigate(['create-exam-subject/edit', id]); + } + + add(){ + this.router.navigate(['create-exam-subject/add']); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrueANDOpenNull()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/create-exam-subject.module.ts b/src/app/feature/create-exam/create-exam-subject/create-exam-subject.module.ts new file mode 100644 index 0000000..679a3ef --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/create-exam-subject.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CreateExamSubjectRouter } from './router/create-exam-subject-router'; +import { CreateExamSubjectContainer } from './container/create-exam-subject/create-exam-subject.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateExamSubjectFormComponent } from './presenter/form/create-exam-subject-form/create-exam-subject-form.component'; +import { CreateExamSubjectListComponent } from './presenter/list/create-exam-subject-list/create-exam-subject-list.component'; +import { CreateExamSubjectSearchComponent } from './presenter/search/create-exam-subject-search/create-exam-subject-search.component'; +import { CreateExamSujectTableComponent } from './presenter/form/create-exam-suject-table/create-exam-suject-table.component'; + +const routes: Routes = [ + { + path: '', + component: CreateExamSubjectRouter, + children: [ + { + path: '', + component: CreateExamSubjectContainer + }, + { + path: 'add', + component: CreateExamSubjectFormComponent + }, + { + path: 'edit/:id', + component: CreateExamSubjectFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + CreateExamSubjectRouter, + CreateExamSubjectContainer, + CreateExamSubjectFormComponent, + CreateExamSubjectListComponent, + CreateExamSubjectSearchComponent, + CreateExamSujectTableComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateExamSubjectModule { } diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.html b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.html new file mode 100644 index 0000000..e2f6b79 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.html @@ -0,0 +1,11 @@ + + +
+  {{setexamform.getRawValue() | json}}
+
diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.scss b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.spec.ts b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.spec.ts new file mode 100644 index 0000000..381bfcd --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSubjectFormComponent } from './create-exam-subject-form.component'; + +describe('CreateExamSubjectFormComponent', () => { + let component: CreateExamSubjectFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSubjectFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSubjectFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.ts b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.ts new file mode 100644 index 0000000..33b9ffa --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-subject-form/create-exam-subject-form.component.ts @@ -0,0 +1,577 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {MatDialog} from '@angular/material/dialog'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; + +@Component({ + selector: 'app-create-exam-subject-form', + templateUrl: './create-exam-subject-form.component.html', + styleUrls: ['./create-exam-subject-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSubjectFormComponent extends BaseForm implements OnInit{ + subjectOldList; + testingInfoData; + subjectListSend = new Observable; + SubjectGetCheck$ = []; + setexamform: FormGroup; + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + + constructor( + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + private cdr: ChangeDetectorRef + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + } + + + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + amount: data?.amount, + random_status: data?.random_status, + grading_status: data?.grading_status, + grading_type: data?.grading_type, + announcement_type: data?.announcement_type, + grading_characteristic: data?.grading_characteristic, + random_question_code: data?.random_question_code, + random_question_type: data?.random_question_type, + random_type: data?.random_type, + }); + } + + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + this.subjectListSend = this.subjectSV.getSubjectReady(); + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + }), + tap(x => this.add3Edit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + break; + case 'add': + break; + } + } + + add3Edit(data){ + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + } + + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x){ + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US'); + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + addSubject(x){ + const form = this.setexamform.get('testing_subjects') as FormArray; + this.SubjectGetCheck$ = x.testing_subjects; + if (x.testing_subjects != null){ + for (let i = 0; i < x.testing_subjects.length; i++) { + console.log(x.testing_subjects[i]); + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + this.subjectOldList = form.getRawValue(); + } + + GetSubjectChoose(data){ + const form = this.setexamform.get('testing_subjects') as FormArray; + form.clear(); + console.log(data) + const oldSubjectlist = this.testingInfoData.testing_subjects; + console.log(oldSubjectlist) + const Newdata = data.filter(x => { + return !!oldSubjectlist.map(y => { + if (x.subject_uid === y.subject_uid){ + x.testing_subject_uid = y.testing_subject_uid; + x.amount = y.amount; + x.random_status = y.random_status; + x.grading_status = y.grading_status; + x.grading_type = y.grading_type; + x.announcement_type = y.announcement_type; + x.grading_characteristic = y.grading_characteristic; + x.random_question_code = y.random_question_code; + x.random_question_type = y.random_question_type; + x.random_status = y.random_status; + x.random_type = y.random_type; + return x; + } + }); + }); + for (let i = 0; i < Newdata.length; i++) { + form.push(this.testing_subjects(Newdata[i])); + } + } + + save(){ + switch (this.state) { + case 'edit': + console.log(this.testingInfoData); + const form2 = this.setexamform.get('testing_subjects') as FormArray; + let subjectNewList = form2.getRawValue(); + let allowedRoles = null; + let isAdd = null; + console.log(subjectNewList); + // console.log(this.subjectOldList); + // for (let i = 0; i < this.subjectOldList.length; i++) { + // subjectNewList.push(this.subjectOldList[i]) + // } + subjectNewList = subjectNewList.reduce((unique, o) => { + if (!unique.some(obj => obj.subject_uid === o.subject_uid)) { + unique.push(o); + } + return unique; + }, []); + console.log(subjectNewList); + // this.ClearSubjectBefore(subjectNewList, this.subjectOldList); + + if (this.subjectOldList.length < subjectNewList.length){ + isAdd = true; + allowedRoles = subjectNewList.filter(role => !this.subjectOldList.some(present => present.subject_uid === role.subject_uid)); + }else if (this.subjectOldList.length > subjectNewList.length){ + isAdd = false; + allowedRoles = this.subjectOldList.filter(role => !subjectNewList.some(present => present.subject_uid === role.subject_uid)); + }else{ + allowedRoles = subjectNewList.filter(role => !this.subjectOldList.some(present => present.subject_uid === role.subject_uid)); + } + // if (allowedRoles != null){ + // + // console.log(allowedRoles); + // this.CloneAndAddSeat(allowedRoles, isAdd); + // } + this.CloneAndAddSeat(allowedRoles, isAdd); + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + console.log(form1); + console.log(form1.testing_information_uid); + this.swSV.confirmSubject().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => console.log(x)), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ); + }) + ).subscribe(); + // const form1 = this.setexamform.getRawValue(); + // form1.testing_periods = form1.testing_periods.filter((member) => { + // return member.is_check === true; + // }); + // this.TestInformationSV.update2(form1).pipe( + // tap(x => this.swSV.updateSuccess()), + // tap(x => window.history.back()), + // catchError(err => { + // this.swSV.err(); + // return throwError(err); + // }) + // ).subscribe(); + break; + } + } + + ClearSubjectBefore(New, Old){ + let SubjectOldinNew = []; + SubjectOldinNew = New.filter((el) => { + return Old.some((f) => { + return f.subject_uid === el.subject_uid; + }); + }); + console.log(SubjectOldinNew); + if (SubjectOldinNew.length !== 0){ + const form = this.setexamform.get('testing_rooms') as FormArray; + const data = form.getRawValue(); + for (let i = 0; i < data.length; i++) { + console.log(1); + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < data[i].testing_seats.length; j++){ + console.log(2); + const seatandsubject = data[i].testing_seats[j]; + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + const SubjectForm = formArraySeatSubject.getRawValue(); + console.log(SubjectForm); + console.log(SubjectOldinNew); + const arr = []; + for (let k = 0; k < SubjectOldinNew.length; k++){ + const index = SubjectForm.findIndex(x => { + return x.subject_uid !== SubjectOldinNew[k].subject_uid; + }); + if (index != -1){ + arr.push(index); + } + // console.log(formArraySeatSubject.getRawValue()); + // const SubjectIndex = data[i].testing_seats[j].testing_seat_subjects[k]; + // console.log(SubjectOldinNew); + // console.log(SubjectIndex); + // const someResult = SubjectOldinNew.some((member) => { + // return member.subject_uid === SubjectIndex.subject_uid + // }); + // if (someResult === true){ + // formArraySeatSubject.removeAt(k) + // } + } + this.removeForm(formArraySeatSubject, arr); + } + } + }else { + console.log(New); + } + // allowedRoles = New.filter((word.subject_uid) => !Old.includes(word.subject_uid)); + // allowedRoles = Old.filter(role => New.some(present => present.subject_uid === role.subject_uid)); + + } + + removeForm(form, array){ + const reverse = array.reverse() + for (let a = 0 ; a < reverse.length; a++){ + console.log(reverse[a]); + // form.removeAt(reverse[a]) + } + } + + checkDuplicate2(arr){ + const isDupicate = arr. + map((value) => { + return value.testing_datetime.getTime() + value.period_id; + }).some((value, index, array) => { + return array.indexOf(value) !== array.lastIndexOf(value); + }); + return !isDupicate; + } + + CloneAndAddSeat(SubjectDiffList, isAdd){ + const form = this.setexamform.get('testing_rooms') as FormArray; + const data = form.getRawValue(); + if (isAdd === true){ + for (let i = 0; i < data.length; i++) { + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < data[i].testing_seats.length; j++){ + const seatandsubject = data[i].testing_seats[j]; + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + for (let k = 0; k < SubjectDiffList.length; k++){ + console.log(SubjectDiffList[k]); + formArraySeatSubject.push(this.testing_seat_subjects(SubjectDiffList[k])); + // for (let h = 0; h < SubjectDiffList.length; h++){ + // formArraySeatSubject.push(this.testing_seat_subjects(SubjectDiffList[h])); + // } + } + } + } + }else if (isAdd === false) { + console.log(11111) + for (let i = 0; i < data.length; i++) { + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < data[i].testing_seats.length; j++){ + const seatandsubject = data[i].testing_seats[j]; + formArray.at(i).get('is_specify_subject').setValue(false); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + for (let k = 0; k < data[i].testing_seats[j].testing_seat_subjects.length; k++){ + for (let h = 0; h < SubjectDiffList.length; h++){ + if (data[i].testing_seats[j].testing_seat_subjects[k].subject_uid === SubjectDiffList[h].subject_uid){ + formArraySeatSubject.reset(); + } + } + } + } + } + } + } + + checkSubjectAlready(seat, subject){ + const SubjectOld = seat.testing_seat_subjects; + const SubjectChange = subject; + const SubjectDiff = SubjectChange.filter(role => SubjectOld.some(present => present.subject_uid === role.subject_uid)); + console.log(SubjectDiff); + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.html b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.html new file mode 100644 index 0000000..f158f09 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.html @@ -0,0 +1,119 @@ +
+

กำหนดวิชาสอบของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+ +
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + รหัสวิชา + {{element.subject_code}} + + + ชื่อวิชา + {{element.subject_name_th}} + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + รหัสวิชา + {{element.subject_code}} + + + ชื่อวิชา + {{element.subject_name_th}} + + + + + + + + + + + + +
+
+
+ + +
+
+ + + diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.scss b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.spec.ts b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.spec.ts new file mode 100644 index 0000000..b8fa802 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSujectTableComponent } from './create-exam-suject-table.component'; + +describe('CreateExamSujectTableComponent', () => { + let component: CreateExamSujectTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSujectTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSujectTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.ts b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.ts new file mode 100644 index 0000000..65b705e --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/form/create-exam-suject-table/create-exam-suject-table.component.ts @@ -0,0 +1,175 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + OnChanges, + Input, + Output, + EventEmitter, + ViewChild, + ChangeDetectorRef +} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {SelectionModel} from '@angular/cdk/collections'; +import {MatTableDataSource} from '@angular/material/table'; +import {MatPaginator} from '@angular/material/paginator'; +import { Location } from '@angular/common'; + +@Component({ + selector: 'app-create-exam-suject-table', + templateUrl: './create-exam-suject-table.component.html', + styleUrls: ['./create-exam-suject-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSujectTableComponent extends BaseList implements OnInit , OnChanges { + @Input() dataSource2: any = []; + @Input() dataSource: any = []; + @Input() SubjectGetCheck: any = []; + column = ['1', '2', '3']; + selection = new SelectionModel(true, []); + uncheckedData:any = []; + @Output() SubjectChecked = new EventEmitter(); + @Output() save = new EventEmitter(); + @Input() testingInfoData: any; + checkedData = []; + checkedDataSource = new MatTableDataSource(this.checkedData); + checkedSelection = new SelectionModel(true, []); + + selectedRows = []; + selectedRowsChecked = []; + + @ViewChild('paginator') paginator: MatPaginator; + @ViewChild('checkedpaginator') checkedpaginator: MatPaginator; + constructor( + private cdRef: ChangeDetectorRef, + private location: Location + ) { + super(); + } + + ngOnInit(): void { + // this.uncheckedData = this.dataSource; + } + + ngOnChanges() { + // console.log(this.dataSource) + // this.uncheckedData = this.dataSource; + console.log(this.dataSource2); + if (this.dataSource2 !== null){ + this.uncheckedData = this.dataSource2 + this.dataSource = this.updateMatTable(this.dataSource2 ? this.dataSource2 : []); + const DatatableLength = this.dataSource.data; + if (DatatableLength.length !== 0 && this.SubjectChecked.length != 0){ + for (const option of this.SubjectGetCheck) { + // const exists = DatatableLength.find((x) => x.subject_uid === option.subject_uid); + const exists = Array.isArray(DatatableLength) ? DatatableLength.find((x) => x.subject_uid === option.subject_uid) : 0; + if (exists !== 0){ + this.selection.toggle(exists); + this.transferSelectedRows(); + } + } + } + this.checkedDataSource.paginator = this.checkedpaginator; + } + + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } + + isAllCheckedSelected() { + const numSelected = this.checkedSelection.selected.length; + const numRows = this.checkedDataSource.data.length; + return numSelected === numRows; + } + + + transferSelectedRows() { + console.log( this.selection.selected); + this.selection.selected.forEach(item => { + console.log(item.subject_uid) + console.log(this.uncheckedData) + this.uncheckedData.map( (d,index) => { + if (item.subject_uid === d.subject_uid){ + this.checkedData.push(this.uncheckedData[index]); + this.uncheckedData.splice(index,1); + } + }) + }); + this.selection = new SelectionModel(true, []); + this.dataSource = new MatTableDataSource(this.uncheckedData); + this.checkedDataSource = new MatTableDataSource(this.checkedData); + this.dataSource.paginator = this.paginator; + this.checkedDataSource.paginator = this.checkedpaginator; + this.sendDataback(this.checkedData); + this.isAllSelected(); + } + + + removeSelectedRows() { + this.checkedSelection.selected.forEach(item => { + const index: number = this.checkedData.findIndex(d => d === item); + this.uncheckedData.push(this.checkedData[index]); + this.checkedData.splice(index,1); + }); + + this.checkedSelection = new SelectionModel(true, []); + this.dataSource = new MatTableDataSource(this.uncheckedData); + this.checkedDataSource = new MatTableDataSource(this.checkedData); + this.dataSource.paginator = this.paginator; + this.checkedDataSource.paginator = this.checkedpaginator; + this.sendDataback(this.checkedData); + this.isAllCheckedSelected(); + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + if (this.dataSource.filter != null || this.dataSource.filter != ''){ + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.filteredData.forEach(row => this.selection.select(row)); + }else { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } + } + + masterCheckedToggle() { + if (this.dataSource.filter != null || this.dataSource.filter != ''){ + this.isAllSelected() ? + this.checkedSelection.clear() : + this.checkedDataSource.filteredData.forEach(row => this.checkedSelection.select(row)); + }else { + this.isAllSelected() ? + this.checkedSelection.clear() : + this.checkedDataSource.data.forEach(row => this.checkedSelection.select(row)); + } + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + } + + applyFilter2(event: Event) { + const filterValue2 = (event.target as HTMLInputElement).value; + this.checkedDataSource.filter = filterValue2.trim().toLowerCase(); + } + + sendDataback(datasend){ + this.SubjectChecked.emit(datasend); + } + + saveSend(){ + this.save.emit(); + } + + back(){ + this.location.back() + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.html b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.html new file mode 100644 index 0000000..dab27d8 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.html @@ -0,0 +1,90 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ + + +
+
+
diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.scss b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.spec.ts b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.spec.ts new file mode 100644 index 0000000..f10e8ce --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSubjectListComponent } from './create-exam-subject-list.component'; + +describe('CreateExamSubjectListComponent', () => { + let component: CreateExamSubjectListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSubjectListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSubjectListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.ts b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.ts new file mode 100644 index 0000000..683d75c --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/list/create-exam-subject-list/create-exam-subject-list.component.ts @@ -0,0 +1,58 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {OBJECT} from '../../../../../../core/enum/role'; + +@Component({ + selector: 'app-create-exam-subject-list', + templateUrl: './create-exam-subject-list.component.html', + styleUrls: ['./create-exam-subject-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSubjectListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + 'is_open', + 'created_datetime', + '7' + ]; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.html b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.html new file mode 100644 index 0000000..240f739 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.scss b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.spec.ts b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.spec.ts new file mode 100644 index 0000000..752d278 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateExamSubjectSearchComponent } from './create-exam-subject-search.component'; + +describe('CreateExamSubjectSearchComponent', () => { + let component: CreateExamSubjectSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateExamSubjectSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateExamSubjectSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.ts b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.ts new file mode 100644 index 0000000..3d507e6 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/presenter/search/create-exam-subject-search/create-exam-subject-search.component.ts @@ -0,0 +1,54 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-create-exam-subject-search', + templateUrl: './create-exam-subject-search.component.html', + styleUrls: ['./create-exam-subject-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSubjectSearchComponent implements OnInit { + + @Output() search = new EventEmitter(); + @Output() add = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + console.log(result); + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + onAdd(){ + this.add.emit(); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/create-exam-subject/router/create-exam-subject-router.ts b/src/app/feature/create-exam/create-exam-subject/router/create-exam-subject-router.ts new file mode 100644 index 0000000..acc3269 --- /dev/null +++ b/src/app/feature/create-exam/create-exam-subject/router/create-exam-subject-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateExamSubjectRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.html b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.html new file mode 100644 index 0000000..2c75937 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.scss b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.spec.ts b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.spec.ts new file mode 100644 index 0000000..3fa4823 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RejectExamContainer } from './reject-exam.container'; + +describe('RejectExamContainer', () => { + let component: RejectExamContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RejectExamContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RejectExamContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.ts b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.ts new file mode 100644 index 0000000..852212a --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/container/reject-exam/reject-exam.container.ts @@ -0,0 +1,74 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {catchError, concatMap, filter, tap} from "rxjs/operators"; +import {MatDialog} from '@angular/material/dialog'; +import { + NotificationCheckExamDialogComponent +} from '../../../../notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component'; +import {ConfirmRejectExamDialogComponent} from '../../presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component'; + + +@Component({ + selector: 'app-reject-exam', + templateUrl: './reject-exam.container.html', + styleUrls: ['./reject-exam.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RejectExamContainer implements OnInit { + + subjectList$ = new Observable(); + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private dialog: MatDialog, + + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getAll(); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } + + edit(id){ + this.router.navigate(['create-exam-information/edit', id]); + } + + close(id){ + this.swSV.confirmText('ต้องการปิดรอบสอบนี้ไหม').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.checkandclosetest(id).pipe( + tap(x => this.swSV.success('รอบสอบปิดแล้ว')), + tap(x => this.subjectList$ = this.TestinforSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errCloseExamDetailText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + + close2(id){ + const dialogRef = this.dialog.open(ConfirmRejectExamDialogComponent, { + width: '550px', + height: '250px', + data: id, + panelClass: 'custom-modalbox' + }); + dialogRef.afterClosed().subscribe(result => { + this.subjectList$ = this.TestinforSV.getAll(); + }); + } + +} diff --git a/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.html b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.html new file mode 100644 index 0000000..c7b0ff4 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.html @@ -0,0 +1,46 @@ +
+
+
+
กรอก Username อีกครั้งเพื่อยืนยันการปิด
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+

Username

+
+
+ +
+
+
+
+
+
+ + +
+
+ + + + + diff --git a/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.scss b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.scss new file mode 100644 index 0000000..a22b7ee --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.scss @@ -0,0 +1,11 @@ +.bgPopup{ // สีพื้นหลังหน้า list ลอง + background-color: #576071; +} + +.lock_open{ + @apply focus:outline-none text-green-700 text-sm py-1 px-2 rounded-md hover:bg-green-100 hover:bg-opacity-50 +} + +.lock_outline{ + @apply focus:outline-none text-gray-400 text-sm py-1 px-2 rounded-md hover:bg-gray-100 bg-opacity-50 +} diff --git a/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.spec.ts b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.spec.ts new file mode 100644 index 0000000..a683eaa --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfirmRejectExamDialogComponent } from './confirm-reject-exam-dialog.component'; + +describe('ConfirmRejectExamDialogComponent', () => { + let component: ConfirmRejectExamDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfirmRejectExamDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfirmRejectExamDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.ts b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.ts new file mode 100644 index 0000000..850d692 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component.ts @@ -0,0 +1,68 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {FormBuilder} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {Location} from '@angular/common'; +import {ExamNotificationService} from '../../../../../../core/service/testing-information/exam-notification.service'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-confirm-reject-exam-dialog', + templateUrl: './confirm-reject-exam-dialog.component.html', + styleUrls: ['./confirm-reject-exam-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ConfirmRejectExamDialogComponent extends BaseForm implements OnInit { + userData; + userName; + constructor( + private TestinforSV: TestingInformationService, + private appTokenSV: AppTokenService, + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + private swSV: SweetalertService, + public location: Location, + private examResultSV: ExamNotificationService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + ) { + super( + router, + activeRoute, + fb, + location + ); + this.form = this.fb.group({ + Username: null, + }); + } + + ngOnInit(): void { + this.userData = this.appTokenSV.user; + this.userName = this.userData.login + } + + save(){ + const form = this.form.getRawValue(); + this.TestinforSV.checkandclosetest(this.data).pipe( + tap(x => this.swSV.success('รอบสอบปิดแล้ว')), + tap(x => this.dialogRef.close()), + // tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errCloseExamDetailText(err.error); + return throwError(err); + }) + ).subscribe(); + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.html b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.html new file mode 100644 index 0000000..40a631a --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.html @@ -0,0 +1,80 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะ + เปิดรอบแล้ว + ปิดรอบสอบแล้ว + กำลังสร้าง + เครื่องมือ +
+ +
+ + + +
ผู้ปิดรอบ {{x.updated_by}} วันที่ {{x.updated_datetime | thaidate}}
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.scss b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.spec.ts b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.spec.ts new file mode 100644 index 0000000..9eb4927 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RejectExamListComponent } from './reject-exam-list.component'; + +describe('RejectExamListComponent', () => { + let component: RejectExamListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RejectExamListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RejectExamListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.ts b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.ts new file mode 100644 index 0000000..5dfdefe --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/list/reject-exam-list/reject-exam-list.component.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-reject-exam-list', + templateUrl: './reject-exam-list.component.html', + styleUrls: ['./reject-exam-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RejectExamListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + @Output() close = new EventEmitter(); + column = ['1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '10', + 'count_subject', + 'is_open', + '7', + '8', + '9' + ]; + reload: boolean; + constructor( + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + // console.log(this.subjectList); + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + this.subjectList.data = this.subjectList.data + .filter((x) => { + return x.is_open != null; + }).map((x) => { + if (x.is_open === false){ + return x; + }else { + x.updated_by = '' + x.updated_datetime = '' + return x; + } + }); + } + + onEdit(id){ + this.edit.emit(id); + } + + onClose(id){ + this.close.emit(id); + } + +} diff --git a/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.html b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.html new file mode 100644 index 0000000..24f5687 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.html @@ -0,0 +1,33 @@ +

ค้นหา

+
+
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
diff --git a/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.scss b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.spec.ts b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.spec.ts new file mode 100644 index 0000000..f154f4f --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RejectExamSearchComponent } from './reject-exam-search.component'; + +describe('RejectExamSearchComponent', () => { + let component: RejectExamSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RejectExamSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RejectExamSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.ts b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.ts new file mode 100644 index 0000000..82e0ba1 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/presenter/search/reject-exam-search/reject-exam-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-reject-exam-search', + templateUrl: './reject-exam-search.component.html', + styleUrls: ['./reject-exam-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RejectExamSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + academicYearList: any = []; + academicSemList: any = []; + query = { + testing_information_name: null, + academic_semester_code: null, + academic_year_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + ) { } + + ngOnInit(): void { + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + this.AcademicYearSV.getAll().subscribe( + result => { + console.log(result); + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + testing_information_name: null, + academic_semester_code: null, + academic_year_code: null + }; + } + +} diff --git a/src/app/feature/create-exam/reject-exam/reject-exam.module.ts b/src/app/feature/create-exam/reject-exam/reject-exam.module.ts new file mode 100644 index 0000000..f985e53 --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/reject-exam.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RejectExamRouter } from './router/reject-exam-router'; +import { RejectExamContainer } from './container/reject-exam/reject-exam.container'; +import { RejectExamSearchComponent } from './presenter/search/reject-exam-search/reject-exam-search.component'; +import { RejectExamListComponent } from './presenter/list/reject-exam-list/reject-exam-list.component'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ConfirmRejectExamDialogComponent } from './presenter/dialog/confirm-reject-exam-dialog/confirm-reject-exam-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: RejectExamRouter, + children: [ + { + path: '', + component: RejectExamContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + RejectExamRouter, + RejectExamContainer, + RejectExamSearchComponent, + RejectExamListComponent, + ConfirmRejectExamDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class RejectExamModule { } diff --git a/src/app/feature/create-exam/reject-exam/router/reject-exam-router.ts b/src/app/feature/create-exam/reject-exam/router/reject-exam-router.ts new file mode 100644 index 0000000..59642ec --- /dev/null +++ b/src/app/feature/create-exam/reject-exam/router/reject-exam-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RejectExamRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/default/default.module.ts b/src/app/feature/default/default.module.ts new file mode 100644 index 0000000..92a4458 --- /dev/null +++ b/src/app/feature/default/default.module.ts @@ -0,0 +1,32 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { DefaultComponent } from './presenter/default/default.component'; +import {DefaultRouter} from './router/default-router'; + +const routes : Routes =[ + { + path:'', + component: DefaultRouter, + children:[ + { + path:'', + component: DefaultComponent + }, + ] + } +] + +@NgModule({ + declarations: [ + DefaultRouter, + DefaultComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) + +export class DefaultModule { } diff --git a/src/app/feature/default/presenter/default/default.component.html b/src/app/feature/default/presenter/default/default.component.html new file mode 100644 index 0000000..42c2c15 --- /dev/null +++ b/src/app/feature/default/presenter/default/default.component.html @@ -0,0 +1,4 @@ + +

+ ยินดีต้อนรับ +

diff --git a/src/app/feature/default/presenter/default/default.component.scss b/src/app/feature/default/presenter/default/default.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/default/presenter/default/default.component.spec.ts b/src/app/feature/default/presenter/default/default.component.spec.ts new file mode 100644 index 0000000..e5e8de1 --- /dev/null +++ b/src/app/feature/default/presenter/default/default.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DefaultComponent } from './default.component'; + +describe('DefaultComponent', () => { + let component: DefaultComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DefaultComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DefaultComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/default/presenter/default/default.component.ts b/src/app/feature/default/presenter/default/default.component.ts new file mode 100644 index 0000000..f1c78fa --- /dev/null +++ b/src/app/feature/default/presenter/default/default.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-default', + templateUrl: './default.component.html', + styleUrls: ['./default.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DefaultComponent implements OnInit { + + constructor( + ) { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/default/router/default-router.ts b/src/app/feature/default/router/default-router.ts new file mode 100644 index 0000000..a7dc915 --- /dev/null +++ b/src/app/feature/default/router/default-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DefaultRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.html b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.html new file mode 100644 index 0000000..1c9bca4 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.html @@ -0,0 +1,7 @@ + + + + + + diff --git a/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.scss b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.spec.ts b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.spec.ts new file mode 100644 index 0000000..9d71ba9 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummaryTtbContainer } from './daily-summary-ttb.container'; + +describe('DailySummaryTtbContainer', () => { + let component: DailySummaryTtbContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummaryTtbContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummaryTtbContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.ts b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.ts new file mode 100644 index 0000000..6571e4a --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/container/daily-summary-ttb/daily-summary-ttb.container.ts @@ -0,0 +1,45 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import {Observable} from 'rxjs'; +import {DailySummaryService} from '../../../../../core/service/testing-register/daily-summary.service'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {tap} from 'rxjs/operators'; +import {DailySummaryTtbService} from '../../../../../core/service/testing-register/daily-summary-ttb.service'; + +@Component({ + selector: 'app-daily-summary-ttb', + templateUrl: './daily-summary-ttb.container.html', + styleUrls: ['./daily-summary-ttb.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryTtbContainer implements OnInit { + dailySummary$ + testingInfo$ = new Observable() + constructor( + private dailySummaryTtbSV: DailySummaryTtbService, + private testingInfoSV: TestingInformationService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfoSV.getAll() + this.dailySummary$ = this.dailySummaryTtbSV.getAll() + // this.dailySummary$ = this.dailySummaryTtbSV.getAll().pipe( + // tap(x => { + // console.log(x); + // const data:any = x; + // console.log(data.response.data[0]) + // this.dailySummary$ = data.response.data[0]; + // }) + // ).subscribe(); + } + + search(query){ + if(query) return this.dailySummary$ = this.dailySummaryTtbSV.searchDaily(query).pipe( + tap((x:any) => { + if(x.length == 0) this.swSV.errText('ไม่มีข้อมูล') + }) + ) + } + +} diff --git a/src/app/feature/exam-register/daily-summary-ttb/daily-summary-ttb.module.ts b/src/app/feature/exam-register/daily-summary-ttb/daily-summary-ttb.module.ts new file mode 100644 index 0000000..bb66548 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/daily-summary-ttb.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DailySummaryTtbRouter } from './router/daily-summary-ttb-router'; +import { DailySummaryTtbContainer } from './container/daily-summary-ttb/daily-summary-ttb.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { DailySummaryTtbListComponent } from './presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component'; +import { DailySummaryTtbSearchComponent } from './presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component'; + +const routes : Routes =[ + { + path: '', + component: DailySummaryTtbRouter, + children:[ + { + path:'', + component: DailySummaryTtbContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + DailySummaryTtbRouter, + DailySummaryTtbContainer, + DailySummaryTtbListComponent, + DailySummaryTtbSearchComponent + ], + imports: [ + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class DailySummaryTtbModule { } diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.html b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.html new file mode 100644 index 0000000..e4b3560 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.html @@ -0,0 +1,39 @@ +

รายงานรับเงินออนไลน์

+
+
+
+

รายการนำเข้า

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} เลขที่ใบเสร็จ2c2p {{x.invoiceNo2C2P}} หมายเลขบัตร {{x.creditCardDetails.cardNumber}} จำนวนเงิน {{x.transactionAmount.amount}} Approval Code {{x.approvalCode}} สถานะการชำระเงิน {{x.pspResponse.responseDescription}}
+ +
+ +
diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.scss b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.spec.ts b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.spec.ts new file mode 100644 index 0000000..8ce6894 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummaryTtbListComponent } from './daily-summary-ttb-list.component'; + +describe('DailySummaryTtbListComponent', () => { + let component: DailySummaryTtbListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummaryTtbListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummaryTtbListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.ts b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.ts new file mode 100644 index 0000000..436419d --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/list/daily-summary-ttb-list/daily-summary-ttb-list.component.ts @@ -0,0 +1,54 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges} from '@angular/core'; +import {PeriodicElement} from '../../../../../manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component'; +import {DialogComponent} from '../../../../daily-summary/presenter/dialog/dialog.component'; +import {filter, switchMap} from 'rxjs/operators'; +import {SelectionModel} from '@angular/cdk/collections'; +import {DailyRegisterPaymentService} from '../../../../../../core/service/report/daily-register/daily-register-payment.service'; +import {MatDialog} from '@angular/material/dialog'; +import {DailyRegisterPaymentTotalService} from '../../../../../../core/service/report/daily-register/daily-register-payment-total.service'; +import {PeriodRegisterPaymentService} from '../../../../../../core/service/report/period-register/period-register-payment.service'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-daily-summary-ttb-list', + templateUrl: './daily-summary-ttb-list.component.html', + styleUrls: ['./daily-summary-ttb-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryTtbListComponent extends BaseList implements OnInit , OnChanges { + column = ['1','2','3','4','5','6'] + @Input() dailySummary:any = []; + @Input() dailySummaryTable:any = []; + selection = new SelectionModel(true, []); + + constructor( + private dailyRegisterPaymentSV: DailyRegisterPaymentService, + private dialog: MatDialog, + private dailyRegisterPaymentTotalSV: DailyRegisterPaymentTotalService, + private periodRegisterPaymentSV: PeriodRegisterPaymentService + ) { + super(); + } + + ngOnInit(): void { + + } + + ngOnChanges() { + console.log(this.dailySummary); + if (this.dailySummary != null){ + const tableFake = []; + tableFake.push(this.dailySummary.response.data[0]) + this.dailySummaryTable = this.updateMatTable(tableFake); + } + + } + + total(){ + // const total = this.dailySummary.data.reduce((prev,cur) => { + // return prev + +cur.testing_fee + // },0) + // return total + } + +} diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.html b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.html new file mode 100644 index 0000000..16d06fd --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.html @@ -0,0 +1,21 @@ +

ค้นหา

+
+
+
+ + + + + + +
+ + + +
+ +
+ +
+ +
diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.scss b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.spec.ts b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.spec.ts new file mode 100644 index 0000000..d10b921 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummaryTtbSearchComponent } from './daily-summary-ttb-search.component'; + +describe('DailySummaryTtbSearchComponent', () => { + let component: DailySummaryTtbSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummaryTtbSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummaryTtbSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.ts b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.ts new file mode 100644 index 0000000..f053e56 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/presenter/search/daily-summary-ttb-search/daily-summary-ttb-search.component.ts @@ -0,0 +1,26 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-daily-summary-ttb-search', + templateUrl: './daily-summary-ttb-search.component.html', + styleUrls: ['./daily-summary-ttb-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryTtbSearchComponent implements OnInit { + @Output() search = new EventEmitter() + @Input() testingInfo: any = []; + query = { + payment_date: null + } + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + if(this.query.payment_date)this.query.payment_date = formatDate(this.query.payment_date, 'yyyy-MM-dd', 'en-US') + this.search.emit(this.query.payment_date) + } + +} diff --git a/src/app/feature/exam-register/daily-summary-ttb/router/daily-summary-ttb-router.ts b/src/app/feature/exam-register/daily-summary-ttb/router/daily-summary-ttb-router.ts new file mode 100644 index 0000000..0eb75ff --- /dev/null +++ b/src/app/feature/exam-register/daily-summary-ttb/router/daily-summary-ttb-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryTtbRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.html b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.html new file mode 100644 index 0000000..c985300 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.html @@ -0,0 +1,5 @@ + + + diff --git a/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.scss b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.spec.ts b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.spec.ts new file mode 100644 index 0000000..45e1f86 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummaryContainer } from './daily-summary.container'; + +describe('DailySummaryContainer', () => { + let component: DailySummaryContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummaryContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummaryContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.ts b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.ts new file mode 100644 index 0000000..15217a9 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/container/daily-summary/daily-summary.container.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable, throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { DailySummaryService } from 'src/app/core/service/testing-register/daily-summary.service'; + +@Component({ + selector: 'app-daily-summary', + templateUrl: './daily-summary.container.html', + styleUrls: ['./daily-summary.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryContainer implements OnInit { + dailySummary$ = new Observable() + testingInfo$ = new Observable() + constructor( + private dailySummarySV: DailySummaryService, + private testingInfoSV: TestingInformationService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + // this.dailySummary$ = this.dailySummarySV.getAll() + this.testingInfo$ = this.testingInfoSV.getAll() + } + + search(query){ + if(query) return this.dailySummary$ = this.dailySummarySV.searchDaily(query).pipe( + tap((x:any) => { + if(x.length == 0) this.swSV.errText('ไม่มีข้อมูล') + }) + ) + } +} diff --git a/src/app/feature/exam-register/daily-summary/daily-summary.module.ts b/src/app/feature/exam-register/daily-summary/daily-summary.module.ts new file mode 100644 index 0000000..317b4e8 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/daily-summary.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { DailySummaryRouter } from './router/daily-summary-router'; +import { DailySummaryContainer } from './container/daily-summary/daily-summary.container'; +import { DailySummaryListComponent } from './presenter/list/daily-summary-list/daily-summary-list.component'; +import { DailySummarySearchComponent } from './presenter/search/daily-summary-search/daily-summary-search.component'; +import { DialogComponent } from './presenter/dialog/dialog.component'; + +const routes : Routes =[ + { + path:'', + component: DailySummaryRouter, + children:[ + { + path:'', + component: DailySummaryContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + DailySummaryRouter, + DailySummaryContainer, + DailySummaryListComponent, + DailySummarySearchComponent, + DialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class DailySummaryModule { } diff --git a/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.html b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.html new file mode 100644 index 0000000..81c1587 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.html @@ -0,0 +1,68 @@ +
+ + +
+ +
+ + + + + กรุณาเลือก + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
+ + + +
+ + diff --git a/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.scss b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.spec.ts b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.spec.ts new file mode 100644 index 0000000..a32e0ea --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogComponent } from './dialog.component'; + +describe('DialogComponent', () => { + let component: DialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.ts b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.ts new file mode 100644 index 0000000..229afda --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/dialog/dialog.component.ts @@ -0,0 +1,74 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { tap } from 'rxjs/operators'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-dialog', + templateUrl: './dialog.component.html', + styleUrls: ['./dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogComponent implements OnInit { + counterList: any = [] + counterNo; + obj = { + counter_no: null, + period: null, + date: null, + start_date: null, + end_date: null, + is_testing_information_report: null, + testing_information_uid: null + } + etest101: boolean = false + etest102: boolean = false + etest103: boolean = false + period; + periodList; + testingInformationList; + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + if(this.data){ + if(this.data.type == '101') this.etest101 = true + if(this.data.type == '102') this.etest102 = true + if(this.data.type == '103') this.etest103 = true + } + this.testingInformationSV.getAll().pipe( + tap(x => this.testingInformationList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.counterList = [...this.data.data].filter((value,index,array) => array.findIndex(x => value.counter_no == x.counter_no) == index) + this.periodList = [...this.data.data].filter((value,index,array) => array.findIndex(x => value.period == x.period) == index) + } + + confirm(){ + this.obj.date = formatDate(this.data.data[0].payment_date, 'yyyy-MM-dd', 'en-US'); + this.dialogRef.close({obj:this.obj}) + } + + confirm102(){ + this.obj.date = formatDate(this.data.date, 'yyyy-MM-dd', 'en-US'); + // this.obj.counter_no = this.data.counter_no + this.dialogRef.close({obj:this.obj}) + } + + confirm103(){ + this.obj.start_date = formatDate(this.obj.start_date, 'yyyy-MM-dd', 'en-US') + this.obj.end_date = formatDate(this.obj.end_date, 'yyyy-MM-dd', 'en-US') + this.dialogRef.close({obj:this.obj}) + } + + display(uid){ + if (uid && this.testingInformationList) return this.testingInformationList.find(x => x.testing_information_uid === uid)?.testing_information_name + } + +} diff --git a/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.html b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.html new file mode 100644 index 0000000..2a6a810 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.html @@ -0,0 +1,93 @@ +

รายงานรับเงิน

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + หมายเลขเครื่อง {{x.counter_no}} วันที่ทำรายการ {{x.payment_date | thaidate}} คาบ {{x.period}} เวลา {{x.counter_open_time}} - {{x.counter_close_time}} ยอดรับเงินประจำคาบ(บาท) {{x.total_amount | number}} จำนวนนักศึกษาที่รับ(คน) {{x.total_student | number}} จำนวนวิชา {{x.number_of_subjects | number}}
+
+
+
+ ยอดเงินรวม + {{totalAmount() | number}} +
+ +
+ จำนวนนักศึกษาลงทะเบียน + {{totalStudent() | number}} +
+ +
+ จำนวนวิชาที่ลงทะเบียน + {{totalSubject() | number}} +
+
+ +
+ + + +
+ +
+ + diff --git a/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.scss b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.spec.ts b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.spec.ts new file mode 100644 index 0000000..dcf2520 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummaryListComponent } from './daily-summary-list.component'; + +describe('DailySummaryListComponent', () => { + let component: DailySummaryListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummaryListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummaryListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.ts b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.ts new file mode 100644 index 0000000..410de72 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/list/daily-summary-list/daily-summary-list.component.ts @@ -0,0 +1,146 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { filter, switchMap, tap } from 'rxjs/operators'; +import { DailyRegisterPaymentTotalService } from 'src/app/core/service/report/daily-register/daily-register-payment-total.service'; +import { DailyRegisterPaymentService } from 'src/app/core/service/report/daily-register/daily-register-payment.service'; +import { PeriodRegisterPaymentOnlineService } from 'src/app/core/service/report/period-register/period-register-payment-online.service'; +import { PeriodRegisterPaymentService } from 'src/app/core/service/report/period-register/period-register-payment.service'; +import { PeriodicElement } from 'src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component'; +import { DialogComponent } from '../../dialog/dialog.component'; + +@Component({ + selector: 'daily-summary-list', + templateUrl: './daily-summary-list.component.html', + styleUrls: ['./daily-summary-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryListComponent implements OnInit { + test = ['1','2','3'] + column = ['0','1','2','3','4','5','6','7'] + @Input() dailySummary : any =[]; + selection = new SelectionModel(true, []); + constructor( + private dailyRegisterPaymentSV: DailyRegisterPaymentService, + private dialog: MatDialog, + private dailyRegisterPaymentTotalSV: DailyRegisterPaymentTotalService, + private periodRegisterPaymentSV: PeriodRegisterPaymentService + ) { } + + ngOnInit(): void { + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dailySummary?.length; + return numSelected === numRows; + } + + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.dailySummary?.forEach((row:any) => this.selection.select(row)); + } + + checkboxLabel(row?: PeriodicElement): string { + if (!row) { + return `${this.isAllSelected() ? 'select' : 'deselect'} all`; + } + return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`; + } + + + reportEtest101(){ + const obj = { + data: this.dailySummary, + type: '101' + } + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj, + }); + + dialogRef.afterClosed().pipe( + filter(x => x.obj), + switchMap(x => { + if(x.obj.is_testing_information_report){ + return window.open(this.dailyRegisterPaymentSV.etest101Information(x.obj)) + }else{ + return window.open(this.dailyRegisterPaymentSV.etest101(x.obj)) + } + }) + ).subscribe() + } + + reportEtest102(){ + const obj = { + data: this.dailySummary, + type: '102', + date: this.dailySummary[0].payment_date, + counter_no: this.dailySummary[0].counter_no + } + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj, + }); + dialogRef.afterClosed().pipe( + filter(x => x.obj), + switchMap(x => { + if(x.obj.is_testing_information_report){ + return window.open(this.dailyRegisterPaymentTotalSV.etest102Information(x.obj)) + }else{ + return window.open(this.dailyRegisterPaymentTotalSV.etest102(x.obj)) + } + }) + ).subscribe() + + } + + reportEtest103(){ + const obj = { + data: this.dailySummary, + type: '103' + } + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj, + }); + + dialogRef.afterClosed().pipe( + filter(x => x.obj), + switchMap(x => { + if(x.obj.is_testing_information_report){ + return window.open(this.periodRegisterPaymentSV.etest103Information(x.obj)) + }else{ + return window.open(this.periodRegisterPaymentSV.etest103(x.obj)) + } + }) + ).subscribe() + } + + + totalAmount(){ + let sum = 0 + this.selection.selected.map((x:any) => { + sum += Number(x.total_amount) + }) + return sum + } + + totalStudent(){ + let sum = 0 + this.selection.selected.map((x:any) => { + sum += Number(x.total_student) + }) + return sum + } + + totalSubject(){ + let sum = 0 + this.selection.selected.map((x:any) => { + sum += Number(x.number_of_subjects) + }) + return sum + } +} + diff --git a/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.html b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.html new file mode 100644 index 0000000..6a352ba --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.html @@ -0,0 +1,21 @@ +

ค้นหา

+
+
+
+ + + + + + +
+ + + +
+ +
+ +
+ +
diff --git a/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.scss b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.spec.ts b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.spec.ts new file mode 100644 index 0000000..20dbd06 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DailySummarySearchComponent } from './daily-summary-search.component'; + +describe('DailySummarySearchComponent', () => { + let component: DailySummarySearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DailySummarySearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DailySummarySearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.ts b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.ts new file mode 100644 index 0000000..6718d81 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/presenter/search/daily-summary-search/daily-summary-search.component.ts @@ -0,0 +1,27 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'daily-summary-search', + templateUrl: './daily-summary-search.component.html', + styleUrls: ['./daily-summary-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummarySearchComponent implements OnInit { + @Output() search = new EventEmitter() + @Input() testingInfo: any = []; + query = { + payment_date: null + } + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + if(this.query.payment_date)this.query.payment_date = formatDate(this.query.payment_date, 'yyyy-MM-dd', 'en-US') + this.search.emit(this.query.payment_date) + } + +} diff --git a/src/app/feature/exam-register/daily-summary/router/daily-summary-router.ts b/src/app/feature/exam-register/daily-summary/router/daily-summary-router.ts new file mode 100644 index 0000000..bd61463 --- /dev/null +++ b/src/app/feature/exam-register/daily-summary/router/daily-summary-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-daily-summary-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DailySummaryRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.html b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.html new file mode 100644 index 0000000..82883af --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.html @@ -0,0 +1,11 @@ + + > + + diff --git a/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.scss b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.spec.ts b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.spec.ts new file mode 100644 index 0000000..793b1ec --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageReceiptContainer } from './manage-receipt.container'; + +describe('ManageReceiptContainer', () => { + let component: ManageReceiptContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageReceiptContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageReceiptContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.ts b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.ts new file mode 100644 index 0000000..668a9d8 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/container/manage-receipt/manage-receipt.container.ts @@ -0,0 +1,71 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {TestingRecieptService} from '../../../../../core/service/testing-register/testing-reciept.service'; +import {Observable} from 'rxjs'; +import { + TestingRegisterEnrollmentService +} from "../../../../../core/service/enrollment-api/testing-register-enrollment.service"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {concatMap, filter, map, tap} from "rxjs/operators"; +import {TestingInformationService} from "../../../../../core/service/testing-information/testing-information.service"; + +@Component({ + selector: 'app-manage-receipt', + templateUrl: './manage-receipt.container.html', + styleUrls: ['./manage-receipt.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageReceiptContainer implements OnInit { + recieptsList$ = new Observable(); + testingInformationList$ = new Observable(); + + constructor( + private testingrecieptsSV: TestingRecieptService, + private testingInformationSV: TestingInformationService, + private testingregisterEnrollSV: TestingRegisterEnrollmentService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + } + + ngOnInit(): void { + this.testingInformationList$ = this.testingInformationSV.getAll(); + // this.testingInformationSV.getAll().pipe( + // tap(x => { + // this.testingInformationList = x.map((res: any) => { + // res.nameandcode = `${res.testing_information_code} ${res.testing_information_name} `; + // return res + // }) + // }), + // tap(x => this.cdr.detectChanges()) + // ).subscribe(); + this.testingInformationList$ = this.testingInformationSV.getAll().pipe( + map((x: any) => { + return x = x.map(x => { + return { + ...x, + nameandcode: `${x.testing_information_code} ${x.testing_information_name} ` + } + }) + }), + ) + } + + search(query) { + if (query) return this.recieptsList$ = this.testingrecieptsSV.getByPaymentCode(`?${query}`); + if (!query) return this.recieptsList$ = this.testingrecieptsSV.getAll(); + } + + CancelPay(id) { + this.swSV.confirmText('ต้องการยกเลิกใบเสร็จนี้หรือไม่').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.testingregisterEnrollSV.cancleAdmin(id).pipe( + tap(x => this.swSV.success('ยกเลิกเรียบร้อย')), + tap(x => this.recieptsList$ = this.testingrecieptsSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/exam-register/manage-receipt/manage-receipt.module.ts b/src/app/feature/exam-register/manage-receipt/manage-receipt.module.ts new file mode 100644 index 0000000..cc212a9 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/manage-receipt.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ManageReceiptRouterComponent } from './router/manage-receipt-router.component'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ManageReceiptContainer } from './container/manage-receipt/manage-receipt.container'; +import { ManageReceiptSearchComponent } from './presenter/search/manage-receipt-search/manage-receipt-search.component'; +import { ManageReceiptListComponent } from './presenter/list/manage-receipt-list/manage-receipt-list.component'; + +const routes: Routes = [ + { + path: '', + component: ManageReceiptRouterComponent, + children: [ + { + path: '', + component: ManageReceiptContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ManageReceiptRouterComponent, + ManageReceiptContainer, + ManageReceiptSearchComponent, + ManageReceiptListComponent + ], + imports: [ + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class ManageReceiptModule { } diff --git a/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.html b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.html new file mode 100644 index 0000000..0ae45ac --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.html @@ -0,0 +1,53 @@ +

แสดงผลการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เลขที่ใบเสร็จ {{x.payment_code}} วันที่ออกใบเสร็จ {{x.payment_datetime | thaidate }} {{x.payment_datetime | date: 'hh:mm:ss' }} Counter {{x.counter_no}} สถานะ +
+ ยกเลิก +
+
+ ใช้งาน +
+
จำนวนเงิน(บาท) {{x.total_amount}} เครื่องมือ + + + +
+ +
+
+
diff --git a/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.scss b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.spec.ts b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.spec.ts new file mode 100644 index 0000000..28ecc71 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageReceiptListComponent } from './manage-receipt-list.component'; + +describe('ManageReceiptListComponent', () => { + let component: ManageReceiptListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageReceiptListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageReceiptListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.ts b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.ts new file mode 100644 index 0000000..125182a --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/list/manage-receipt-list/manage-receipt-list.component.ts @@ -0,0 +1,117 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {TestingRegisterService} from '../../../../../../core/service/testing-register/testing-register.service'; +import {TestingRecieptService} from '../../../../../../core/service/testing-register/testing-reciept.service'; +import {BaseList} from '../../../../../../core/base/base-list'; +import { + ReceiptByPaymentCodeService +} from '../../../../../../core/service/report/receipt-by-payment-code/receipt-by-payment-code.service'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {concatMap, filter, tap} from "rxjs/operators"; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; +import { + TestingRegisterEnrollmentService +} from "../../../../../../core/service/enrollment-api/testing-register-enrollment.service"; +import {X} from '@angular/cdk/keycodes'; + +@Component({ + selector: 'app-manage-receipt-list', + templateUrl: './manage-receipt-list.component.html', + styleUrls: ['./manage-receipt-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageReceiptListComponent extends BaseList implements OnInit, OnChanges { + @Input() recieptsList: any = []; + @Output() OnCancelPay = new EventEmitter(); + + user; + column = ['1', '2', '3', '5', '4', '6']; + test = ['1']; + + constructor( + private reportPaymentcode: ReceiptByPaymentCodeService, + private appTokenSV: AppTokenService, + private swSV: SweetalertService, + ) { + super(); + } + + ngOnInit(): void { + this.user = this.appTokenSV.getToken(); + + } + + ngOnChanges() { + console.log(this.recieptsList); + this.recieptsList = this.updateMatTable(this.recieptsList ? this.recieptsList : []); + } + + print(paymentCode, type: any) { + // console.log(paymentCode); + if (paymentCode !== null) { + this.reportPaymentcode.getPdfReportReceiptForAll(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + printReal(paymentCode, type: any) { + // console.log(paymentCode); + if (paymentCode !== null) { + this.reportPaymentcode.getPdfReportRealUat(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + printCopy(paymentCode, type: any) { + // console.log(paymentCode); + if (paymentCode !== null) { + this.reportPaymentcode.getPdfReportCopy(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + printCopyRealUat(paymentCode, type: any) { + // console.log(paymentCode); + if (paymentCode !== null) { + this.reportPaymentcode.getPdfReportCopyRealUat(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + cancelPay(registerUid) { + this.OnCancelPay.emit(registerUid); + } + + isDueDate(data) { + let current_date = new Date() + let payment_date = new Date(data.payment_datetime) + current_date.setHours(0, 0, 0, 0); + payment_date.setHours(0, 0, 0, 0); + if (current_date.getTime() === payment_date.getTime()) { + if (data.is_cancel) { + return false + } + return true + } else { + return false + } + + } + + +} diff --git a/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.html b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.html new file mode 100644 index 0000000..01c39d7 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.html @@ -0,0 +1,57 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+ +
+ + + + + กรุณาเลือก + + + {{x.nameandcode}} + + +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+ + +
+
+
+
diff --git a/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.scss b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.spec.ts b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.spec.ts new file mode 100644 index 0000000..c633215 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageReceiptSearchComponent } from './manage-receipt-search.component'; + +describe('ManageReceiptSearchComponent', () => { + let component: ManageReceiptSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageReceiptSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageReceiptSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.ts b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.ts new file mode 100644 index 0000000..f97c41a --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/presenter/search/manage-receipt-search/manage-receipt-search.component.ts @@ -0,0 +1,89 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Output, + EventEmitter, + ChangeDetectorRef, + Input +} from '@angular/core'; +import {createQueryStringFromObject} from "../../../../../../shared/util/func"; +import {AcademicYearService} from "../../../../../../core/service/settings/academic-year.service"; +import {AcademicSemesterService} from "../../../../../../core/service/settings/academic-semester.service"; +import {map, tap} from "rxjs/operators"; +import { + TestingInformationService +} from "../../../../../../core/service/testing-information/testing-information.service"; + +@Component({ + selector: 'app-manage-receipt-search', + templateUrl: './manage-receipt-search.component.html', + styleUrls: ['./manage-receipt-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageReceiptSearchComponent implements OnInit { + @Input() testingInformationList: any = []; + + query = { + payment_code: null, + counter_no: null, + academic_semester_code: null, + academic_year_code: null, + testing_information_uid: null, + }; + academicYearList = []; + academicSemList: any = []; + + @Output() search = new EventEmitter(); + + constructor( + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + ) { + } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + // this.testingInformationSV.getAll().pipe( + // tap(x => { + // this.testingInformationList = x.map((res: any) => { + // res.nameandcode = `${res.testing_information_code} ${res.testing_information_name} `; + // return res + // }) + // }), + // tap(x => this.cdr.detectChanges()) + // ).subscribe(); + } + + onSearch() { + const queryString = createQueryStringFromObject(this.query) + this.search.emit(queryString); + } + + display(uid) { + if (uid && this.testingInformationList) return this.testingInformationList.find(x => x.testing_information_uid === uid)?.nameandcode + } + + clear() { + this.query = { + payment_code: null, + counter_no: null, + academic_semester_code: null, + academic_year_code: null, + testing_information_uid: null, + }; + this.onSearch(); + } + +} diff --git a/src/app/feature/exam-register/manage-receipt/router/manage-receipt-router.component.ts b/src/app/feature/exam-register/manage-receipt/router/manage-receipt-router.component.ts new file mode 100644 index 0000000..f100300 --- /dev/null +++ b/src/app/feature/exam-register/manage-receipt/router/manage-receipt-router.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-manage-receipt-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageReceiptRouterComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.html b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.html new file mode 100644 index 0000000..d5d22ff --- /dev/null +++ b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.html @@ -0,0 +1,5 @@ + + + diff --git a/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.scss b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.spec.ts b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.spec.ts new file mode 100644 index 0000000..bd01e27 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PeriodSummaryContainer } from './period-summary.container'; + +describe('PeriodSummaryContainer', () => { + let component: PeriodSummaryContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PeriodSummaryContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PeriodSummaryContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.ts b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.ts new file mode 100644 index 0000000..d925874 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/container/period-summary/period-summary.container.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { PeriodSummaryService } from 'src/app/core/service/testing-register/period-summary.service'; + +@Component({ + selector: 'app-period-summary', + templateUrl: './period-summary.container.html', + styleUrls: ['./period-summary.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PeriodSummaryContainer implements OnInit { + periodSummary$ = new Observable() + testingInfo$ = new Observable() + constructor( + private periodSummarySV: PeriodSummaryService, + private testingInfoSV: TestingInformationService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfoSV.getAll() + } + + search(query){ + if(query) return this.periodSummary$ = this.periodSummarySV.searchSummary(query).pipe( + tap((x:any) => { + if(x.length == 0) this.swSV.errText('ไม่มีข้อมูล') + }) + ) + } + +} diff --git a/src/app/feature/exam-register/period-summary/period-summary.module.ts b/src/app/feature/exam-register/period-summary/period-summary.module.ts new file mode 100644 index 0000000..24f6479 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/period-summary.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { PeriodSummaryContainer } from './container/period-summary/period-summary.container'; +import { PeriodSummaryRouter } from './router/period-summary-router'; +import { PeriodSummaryListComponent } from './presenter/list/period-summary-list/period-summary-list.component'; +import { PeriodSummarySearchComponent } from './presenter/search/period-summary-search/period-summary-search.component'; +const routes : Routes =[ + { + path:'', + component: PeriodSummaryRouter, + children:[ + { + path:'', + component: PeriodSummaryContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + PeriodSummaryRouter, + PeriodSummaryContainer, + PeriodSummaryListComponent, + PeriodSummarySearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class PeriodSummaryModule { } diff --git a/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.html b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.html new file mode 100644 index 0000000..99ce4c7 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.html @@ -0,0 +1,158 @@ +

สรุปยอดประจำคาบ

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
หมายเลขเครื่อง {{x.counter_no}} วันที่ทำรายการ {{x.payment_date | thaidate}} คาบ {{x.period}} เวลา {{x.counter_open_time}} - {{x.counter_close_time}} ยอดรับเงินประจำคาบ(บาท) {{x.total_amount | number}} จำนวนนักศึกษาที่รับ(คน) {{x.total_student | number}} จำนวนวิชา {{x.number_of_subjects | number}}
+ +
+
+
+
+

สรุปเงินที่ได้รับ

+ +
+
+
+ 1000 + +   + + 1000 +
+ +
+ 500 + +   + + 500 +
+ +
+ 100 + +   + + 100 +
+ +
+ 50 + +   + + 50 +
+ +
+ 20 + +   + + 20 +
+ +
+ 10 + +   + + 10 +
+ +
+ 5 + +   + + 5 +
+ +
+ 2 + +   + + 2 +
+ +
+ 1 + +   + + 1 +
+ +
+ 0.50 + +   + + 1 +
+ +
+ 0.25 + +   + + 1 +
+ +
+ รวมเป็นเงิน + + บาท +
+ +
+
+
+ check_circle + cancel +
+
+
+
+ +   + + + + + +
+ + diff --git a/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.scss b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.scss new file mode 100644 index 0000000..6baa146 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.scss @@ -0,0 +1,11 @@ +@media print { + #section-to-print { + background-color: white; + height: 100%; + width: 100%; + position: fixed; + top: 0; + left: 0; + } +} + diff --git a/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.spec.ts b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.spec.ts new file mode 100644 index 0000000..382826d --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PeriodSummaryListComponent } from './period-summary-list.component'; + +describe('PeriodSummaryListComponent', () => { + let component: PeriodSummaryListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PeriodSummaryListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PeriodSummaryListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.ts b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.ts new file mode 100644 index 0000000..7f5ac10 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/list/period-summary-list/period-summary-list.component.ts @@ -0,0 +1,90 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { DailyRegisterPaymentTotalService } from 'src/app/core/service/report/daily-register/daily-register-payment-total.service'; +import { DailyRegisterPaymentService } from 'src/app/core/service/report/daily-register/daily-register-payment.service'; +import { PeriodRegisterPaymentService } from 'src/app/core/service/report/period-register/period-register-payment.service'; + +@Component({ + selector: 'period-summary-list', + templateUrl: './period-summary-list.component.html', + styleUrls: ['./period-summary-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PeriodSummaryListComponent implements OnInit,OnChanges { + @Input() periodSummary: any = []; + price1000 = 0; + price500 = 0; + price100 = 0; + price50 = 0; + price20 = 0; + price10 = 0; + price5 = 0; + price2 = 0; + price1 = 0; + price050 = 0; + price025 = 0; + column = ['1','2','3','4','5','6','7'] + // periodSummaryList$ : any = []; + sumPrice; + constructor( + private periodRegisterPaymentSV: PeriodRegisterPaymentService, + private dailyRegisterSV: DailyRegisterPaymentService, + private dailyRegisterTotalSV: DailyRegisterPaymentTotalService + ) { } + + ngOnInit(): void { + } + + ngOnChanges(changes: SimpleChanges): void { + if(this.periodSummary){ + this.sumPrice = this.periodSummary.reduce((acc,cur) => { + return acc + +cur.total_amount + },0) + } + } + + print(){ + const obj = { + start_date : formatDate(this.periodSummary[0].payment_date, 'yyyy-MM-dd', 'en-US'), + end_date : formatDate(new Date() ,'yyyy-MM-dd', 'en-US') + } + window.open(this.periodRegisterPaymentSV.etest103(obj)) + } + + sum(){ + let sum; + sum = + (this.price1000 * 1000) + + (this.price500 * 500) + + (this.price100 * 100) + + (this.price50 * 50) + + (this.price20 * 20) + + (this.price10 * 10) + + (this.price5 * 5) + + (this.price2 * 2) + + (this.price1 * 1) + + (this.price050 * 0.5) + + (this.price025 * 0.25) + return sum; + } + + reportEtest(type:string){ + const data = {...this.periodSummary[0]} + const query = { + period: data.period, + counter_no: data.counter_no, + date : data.payment_date + } + if(type == '101'){ + window.open(this.dailyRegisterSV.etest101(query)) + }else{ + window.open(this.dailyRegisterTotalSV.etest102(query)) + } + } + + + printScreen(){ + window.print() + } + +} diff --git a/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.html b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.html new file mode 100644 index 0000000..cc1a30a --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.html @@ -0,0 +1,38 @@ +

ค้นหา

+
+
+
+ + + + + + +
+ + + +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
diff --git a/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.scss b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.spec.ts b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.spec.ts new file mode 100644 index 0000000..fb18bd0 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PeriodSummarySearchComponent } from './period-summary-search.component'; + +describe('PeriodSummarySearchComponent', () => { + let component: PeriodSummarySearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PeriodSummarySearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PeriodSummarySearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.ts b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.ts new file mode 100644 index 0000000..0bc4b7d --- /dev/null +++ b/src/app/feature/exam-register/period-summary/presenter/search/period-summary-search/period-summary-search.component.ts @@ -0,0 +1,37 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, ChangeDetectorRef } from '@angular/core'; +import { tap } from 'rxjs/operators'; +import { UserCountersService } from 'src/app/core/service/permission/user-counters.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'period-summary-search', + templateUrl: './period-summary-search.component.html', + styleUrls: ['./period-summary-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PeriodSummarySearchComponent implements OnInit { + @Input() testingInfo: any = []; + period; + query = { + payment_date: null, + period: null, + counter_no: null + } + + @Output() search = new EventEmitter() + constructor( + private userCounterSV: UserCountersService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + } + + onSearch(){ + if (this.query.payment_date) {this.query.payment_date = formatDate(this.query.payment_date, 'yyyy-MM-dd', 'en-US'); } + this.search.emit(this.query); + } + + +} diff --git a/src/app/feature/exam-register/period-summary/router/period-summary-router.ts b/src/app/feature/exam-register/period-summary/router/period-summary-router.ts new file mode 100644 index 0000000..2f13d13 --- /dev/null +++ b/src/app/feature/exam-register/period-summary/router/period-summary-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-period-summary-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PeriodSummaryRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.html b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.html new file mode 100644 index 0000000..e61a468 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.html @@ -0,0 +1,23 @@ +
+ + + +
{{userData$ | json}}
+
+
+
+
+ +
+
+
diff --git a/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.scss b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.spec.ts b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.spec.ts new file mode 100644 index 0000000..fb94d02 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReceivePaymentContainer } from './receive-payment.container'; + +describe('ReceivePaymentContainer', () => { + let component: ReceivePaymentContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReceivePaymentContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReceivePaymentContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.ts b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.ts new file mode 100644 index 0000000..a4df758 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/container/receive-payment/receive-payment.container.ts @@ -0,0 +1,93 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {SharedUsercouterService} from '../../../../../core/service/testing-register/shared-usercouter.service'; +import {Observable} from 'rxjs'; +import {UserCounterLoginComponent} from '../../../register-summary/presenter/user-counter-login/user-counter-login.component'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {TestingRegisterService} from '../../../../../core/service/testing-register/testing-register.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {MatDialog} from '@angular/material/dialog'; +import {TestingRecieptService} from '../../../../../core/service/testing-register/testing-reciept.service'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-receive-payment', + templateUrl: './receive-payment.container.html', + styleUrls: ['./receive-payment.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentContainer implements OnInit { + userPaymentdata$ = new Observable(); + userData$ = null; + constructor( + private router: Router, + public sharedUsercouterSV: SharedUsercouterService, + private registerSV: TestingRegisterService, + private recieptSV: TestingRecieptService, + private swSV: SweetalertService, + public sharedCouterSV: SharedUsercouterService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + console.log(this.sharedUsercouterSV.data); + if (this.sharedUsercouterSV.data == null){ + this.dialoglogin(); + }else { + this.userData$ = this.sharedUsercouterSV.data; + this.userPaymentdata$ = this.registerSV.getAllbyUsercouter(this.userData$.user_name); + this.cdr.detectChanges(); + } + } + + dialoglogin(){ + const dialogRef = this.dialog.open(UserCounterLoginComponent, { + disableClose: true, + width: '500px', + height: '320px', + }); + dialogRef.afterClosed().pipe( + tap(x => { + if (x != null){ + console.log(x.user_name); + this.userData$ = x; + this.sharedCouterSV.data = x; + this.userPaymentdata$ = this.registerSV.getAllbyUsercouter(this.userData$.user_name); + this.cdr.detectChanges(); + this.swSV.success(`ยินดีต้อนรับ ${x.user_name}`); + }else { + return this.swSV.error('ข้อมูลไม่ถูกต้อง โปรดตรวจสอบข้อมูล'); + } + }), + ).subscribe( + result => { + this.userData$ = result; + this.cdr.detectChanges(); + } + ); + } + + search(query){ + console.log(query); + if(query) return this.userPaymentdata$ = this.registerSV.search(`?${query}`) + } + + view(id){ + this.router.navigate(['receive-payment/view', id]); + } + + recieve(id){ + console.log(id); + this.swSV.recieve().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.recieptSV.Paid(id).pipe( + tap(x => this.swSV.removeSuccess()), + // tap(x => this.subjectList$ = this.TestinforSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.html b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.html new file mode 100644 index 0000000..fafaa17 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.html @@ -0,0 +1,208 @@ +
+

ข้อมูลผู้สอบ

+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ + +
+ +
+ + +
+
+
+
+ +

กระบวนวิชาที่เลือก

+
+
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ + + +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.scss b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.spec.ts b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.spec.ts new file mode 100644 index 0000000..13342a8 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReceivePaymentDetailComponent } from './receive-payment-detail.component'; + +describe('ReceivePaymentDetailComponent', () => { + let component: ReceivePaymentDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReceivePaymentDetailComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReceivePaymentDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.ts b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.ts new file mode 100644 index 0000000..7a9b5f7 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/detail/receive-payment-detail/receive-payment-detail.component.ts @@ -0,0 +1,358 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Input} from '@angular/core'; +import {ActivatedRoute, Params} from '@angular/router'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {FacultysService} from '../../../../../../core/service/settings/facultys.service'; +import {DepartmentService} from '../../../../../../core/service/settings/department.service'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {FormArray, FormBuilder} from '@angular/forms'; +import {tap} from 'rxjs/operators'; +import {TestingRegisterService} from '../../../../../../core/service/testing-register/testing-register.service'; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; + +@Component({ + selector: 'app-receive-payment-detail', + templateUrl: './receive-payment-detail.component.html', + styleUrls: ['./receive-payment-detail.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentDetailComponent implements OnInit { + form; + AcademicSemLists; + AcademicYearLists; + AcademicYearCode; + TestInformationID; + subTestInformtionID; + TestingInformationLists: any = []; + newMaintestinginformationuID; + FacultyLists: any = []; + DepartmentLists: any = []; + TestcenterLists: any = []; + TestFieldLists: any = []; + TestRoomLists: any = []; + SubjectLists: any = []; + EducationTypeLists: any = []; + PeriodLists: any = []; + Daterange = { + testing_start_datetime: null, + testing_end_datetime: null, + }; + chooseID = { + idTest: null, + startrangedayTest: null, + endrangedayTest: null, + idSub: null, + startrangedaySub: null, + endrangedaySub: null, + }; + Lists; + @Input() userData: any = []; + constructor( + public fb: FormBuilder, + private swSV: SweetalertService, + private activeRoute: ActivatedRoute, + private cdr: ChangeDetectorRef, + private academicsemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private testinginformationSV: TestingInformationService, + private testingFieldSV: TestingFieldService, + private testingRegisterSV: TestingRegisterService, + private facultySV: FacultysService, + private departmentSV: DepartmentService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + ) { + this.form = this.fb.group({ + examinee_card: null, + student_code: null, + examinee_full_name: null, + faculty_uid: null, + department_name: null, + candidate_type_uid: null, + examinee_mobile: null, + testing_fee: '', + testing_information_uid: null, + payment_uid: 0, + user_name: null, + is_cancel: false, + testing_subject_selecteds: this.fb.array([ + this.testing_subject_selecteds() + ]), + }); + } + + testing_subject_selecteds(){ + return this.fb.group({ + testing_center_uid: null, + subject_uid: null, + testing_datetime: null, + period_id: null, + branch_uid: null, + testing_field_uid: null, + testing_seat: null, + is_cancel: false + }); + } + + ngOnInit(): void { + this.academicsemSV.getAll().subscribe( + result => this.AcademicSemLists = result + ); + this.academicYearSV.getAll().subscribe( + result => this.AcademicYearLists = result + ); + this.facultySV.getAll().subscribe( + result => { + this.FacultyLists = result; + } + ); + this.subjectSV.getAll().subscribe( + result => { + this.SubjectLists = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => { + this.TestcenterLists = result; + } + ); + this.testingFieldSV.getAll().subscribe( + result => { + this.TestFieldLists = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => { + this.TestRoomLists = result; + } + ); + this.testinginformationSV.getDatatype().subscribe( + result => this.EducationTypeLists = result + ); + this.testcenterSV.getAll().subscribe( + result => { + console.log(result); + this.PeriodLists = result; + } + ); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === true; + }); + } + ); + this.activeRoute.params.subscribe( + (params: Params) => { + console.log(params.id); + const id = params.id; + this.testingRegisterSV.get(id).pipe( + tap(x => console.log(x)), + tap(x => this.form.patchValue(x)), + tap(x => { + this.swSV.loadingStart(); + }), + ).subscribe( + async () =>{ + console.log('before delay') + await this.delay(5000); + this.cdr.detectChanges() + this.swSV.close() + // Do something after + console.log('after delay') + } + ); + } + ); + } + + delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); + } + + add(){ + const form = this.form.get('testing_subject_selecteds') as FormArray; + form.push(this.testing_subject_selecteds()); + } + removeArray(i){ + const form = this.form.get('testing_subject_selecteds') as FormArray; + form.removeAt(i); + } + + setYearSem(data){ + console.log(data); + this.TestInformationID = data; + let subMain: any = []; + this.newMaintestinginformationuID = null; + const form = this.form.get('testing_subject_selecteds') as FormArray; + this.testinginformationSV.get(data).subscribe( + result => { + console.log(1); + console.log(result); + const subjectlist: any = result; + if (subjectlist.main_testing_information_uid === null){ + console.log(3); + this.chooseID.idTest = subjectlist.testing_information_uid; + this.chooseID.startrangedayTest = this.formatDate(subjectlist.testing_start_datetime); + this.chooseID.endrangedayTest = this.formatDate(subjectlist.testing_end_datetime); + console.log(subjectlist.testing_subjects); + this.Daterange.testing_start_datetime = this.formatDate(subjectlist.testing_start_datetime); + this.Daterange.testing_end_datetime = this.formatDate(subjectlist.testing_end_datetime); + this.cdr.detectChanges(); + this.SubjectLists = subjectlist.testing_subjects; + this.AcademicYearCode = result; + } + console.log(subjectlist.testing_rooms); + this.TestcenterLists = subjectlist.testing_rooms; + this.TestFieldLists = subjectlist.testing_rooms; + this.TestRoomLists = subjectlist.testing_rooms; + this.TestcenterLists = this.TestcenterLists.reduce((unique, o) => { + if(!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []); + // console.log(this.TestcenterLists); + if (this.SubjectLists.length === 1){ + form.patchValue([ + { subject_uid: this.SubjectLists[0].subject_uid , }, + ]); + } + this.testinginformationSV.getCheckmaintrue(data).subscribe( + result => { + console.log(2); + console.log(result); + subMain = result; + this.newMaintestinginformationuID = subMain[0]; + if (subMain.length !== 0){ + this.chooseID.idSub = subMain[0].testing_information_uid; + this.chooseID.startrangedaySub = this.formatDate(subMain[0].testing_start_datetime); + this.chooseID.endrangedaySub = this.formatDate(subMain[0].testing_end_datetime); + const endDate = this.newMaintestinginformationuID.testing_end_datetime; + this.Daterange.testing_end_datetime = this.chooseID.endrangedaySub; + console.log(this.Daterange); + this.cdr.detectChanges(); + } + } + ); + } + ); + } + + setregisterdataForm(data){ + console.log(data); + console.log(this.TestcenterLists); + this.testcenterSV.get(data).subscribe( + result => { + console.log(result); + this.PeriodLists = result; + } + ); + } + + setRoom(data){ + console.log(data); + this.testcenterSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.TestRoomLists = x), + ).subscribe( + result => { + this.TestRoomLists = this.TestRoomLists.filter((x) => { + return x.testing_field_uid === data; + }); + console.log(this.TestRoomLists); + this.cdr.detectChanges(); + } + ); + } + + chooseidDate(data){ + if (this.chooseID.idSub !== null){ + const d1 = this.chooseID.startrangedayTest.split('-'); + const d2 = this.chooseID.endrangedayTest.split('-'); + const s1 = this.chooseID.startrangedaySub.split('-'); + const s2 = this.chooseID.endrangedaySub.split('-'); + const c = data.split('-'); + const from = new Date(d1[0], parseInt(d1[1]) - 1, d1[2]); // -1 because months are from 0 to 11 + const to = new Date(d2[0], parseInt(d2[1]) - 1, d2[2]); + const fromsub = new Date(s1[0], parseInt(s1[1]) - 1, s1[2]); // -1 because months are from 0 to 11 + const tosub = new Date(s2[0], parseInt(s2[1]) - 1, s2[2]); + const check = new Date(c[0], parseInt(c[1]) - 1, c[2]); + // console.log(check > from && check < to); + // console.log(check > fromsub && check < tosub); + if (check >= from && check <= to){ + console.log(check >= from && check <= to); + this.form.get('testing_information_uid').setValue(this.chooseID.idTest); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === true; + }); + } + ); + }else if (check >= fromsub && check <= tosub){ + console.log(check >= fromsub && check <= tosub); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === false; + }); + } + ); + this.form.get('testing_information_uid').setValue(this.chooseID.idSub); + } + } + } + + setInformation(data){ + console.log(data); + let search = ''; + if (data === '6dff8faf-0b30-4fb1-8274-42df8debe8a0'){ + search = 'นักศึกษา'; + }else if (data === 'd056ba6d-5a15-4df6-ade0-c9e8c239d1b1'){ + search = 'บุคคลทั่วไป'; + }else if (data === '5fc44678-8f36-41f6-b0e5-0901ea2231b4'){ + search = 'นักศึกษาโครงการพิเศษ'; + } + const Detail = this.userData.details; + console.log(Detail); + this.testinginformationSV.querytypeofexaminee(search).subscribe( + res => { + console.log(res); + this.TestingInformationLists = res; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === true; + }); + this.TestingInformationLists = this.TestingInformationLists.filter((el) => { + return Detail.some((f) => { + return f.testing_information_uid === el.testing_information_uid; + }); + }); + this.cdr.detectChanges(); + } + ); + } + + formatDate(date) { + let d = new Date(date), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); + + if (month.length < 2) { + month = '0' + month; + } + if (day.length < 2) { + day = '0' + day; + } + + return [year, month, day].join('-'); + } + +} diff --git a/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.html b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.html new file mode 100644 index 0000000..0339469 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.html @@ -0,0 +1,56 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสนักศึกษา {{x.student_code}} หมายเลขบัตรประชาชน {{x.student_code}} ชื่อ-นามสกุล {{x.examinee_full_name}} ประเภทผู้สอบ {{x.candidate_type_uid}} รอบสอบ {{x.testing_information_uid}} การชำระเงิน {{x.is_cancel}} ยอดค่าใช้จ่าย {{x.testing_fee}} Action + + +
+ +
+
+
diff --git a/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.scss b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.scss new file mode 100644 index 0000000..fb5c0a5 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.scss @@ -0,0 +1,3 @@ +//.mat-row:hover { +// background-color: darkgrey; +//} diff --git a/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.spec.ts b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.spec.ts new file mode 100644 index 0000000..dab6462 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReceivePaymentListComponent } from './receive-payment-list.component'; + +describe('ReceivePaymentListComponent', () => { + let component: ReceivePaymentListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReceivePaymentListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReceivePaymentListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.ts b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.ts new file mode 100644 index 0000000..4628b5f --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/list/receive-payment-list/receive-payment-list.component.ts @@ -0,0 +1,44 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {MatDialog} from '@angular/material/dialog'; +import {VEligibleCandidatesService} from '../../../../../../core/service/testing-register/v-eligible-candidates.service'; + +@Component({ + selector: 'app-receive-payment-list', + templateUrl: './receive-payment-list.component.html', + styleUrls: ['./receive-payment-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentListComponent extends BaseList implements OnInit, OnChanges { + @Input() userPaymentdata: any = []; + @Output() view = new EventEmitter(); + @Output() onRecieve = new EventEmitter(); + + column = [ '1', '2', '3', '4', '5', '6', '7', '0']; + constructor( + private dialog: MatDialog, + private cdf: ChangeDetectorRef, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.userPaymentdata = this.updateMatTable(this.userPaymentdata ? this.userPaymentdata : []); + this.cdf.detectChanges(); + } + + onClickPublisher(data){ + console.log(data) + const id = data.testing_register_uid; + this.view.emit(id); + } + + recieve(id){ + this.onRecieve.emit(id); + } + + +} diff --git a/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.html b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.html new file mode 100644 index 0000000..6cd0b6f --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.html @@ -0,0 +1,24 @@ +

ค้นหา

+
+
+
+
+ + +
+
+
+ +
+
+ + +
+
+ +
+ + +
+
+
diff --git a/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.scss b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.spec.ts b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.spec.ts new file mode 100644 index 0000000..b5a2074 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReceivePaymentSearchComponent } from './receive-payment-search.component'; + +describe('ReceivePaymentSearchComponent', () => { + let component: ReceivePaymentSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReceivePaymentSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReceivePaymentSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.ts b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.ts new file mode 100644 index 0000000..be8fbe0 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/search/receive-payment-search/receive-payment-search.component.ts @@ -0,0 +1,33 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-receive-payment-search', + templateUrl: './receive-payment-search.component.html', + styleUrls: ['./receive-payment-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + query = { + student_code: null, + examinee_card: null + }; + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query) ; + } + + clear(){ + this.query = { + student_code: null, + examinee_card: null + }; + } + +} diff --git a/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.html b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.html new file mode 100644 index 0000000..f68d746 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.html @@ -0,0 +1,47 @@ +
+
+
+ + + + +

+ +
+ +
+
+
+ + + +

+ + +
+
+
+
+ + + + +

+ +
+
+
+
+
diff --git a/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.scss b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.scss new file mode 100644 index 0000000..2e0039a --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.scss @@ -0,0 +1,11 @@ +.fontsummary{ + font-size: 30px; + font-max-size: 30px; + font-min-size: 20px; + color: #529F6E; +} +.fontHeadsummary{ + font-size: 30px; + font-max-size: 30px; + font-min-size: 20px; +} diff --git a/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.spec.ts b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.spec.ts new file mode 100644 index 0000000..3e23b3e --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReceivePaymentSummaryComponent } from './receive-payment-summary.component'; + +describe('ReceivePaymentSummaryComponent', () => { + let component: ReceivePaymentSummaryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReceivePaymentSummaryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReceivePaymentSummaryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.ts b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.ts new file mode 100644 index 0000000..05d7879 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/presenter/summary/receive-payment-summary/receive-payment-summary.component.ts @@ -0,0 +1,51 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, ChangeDetectorRef, Input} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {TestingRegisterService} from '../../../../../../core/service/testing-register/testing-register.service'; +import {tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-receive-payment-summary', + templateUrl: './receive-payment-summary.component.html', + styleUrls: ['./receive-payment-summary.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentSummaryComponent extends BaseList implements OnInit , OnChanges{ + @Input() userData: any = []; + @Input() registerList: any = []; + listsummary; + totalfee:number = 0 ; + studentcount = 0; + subjectcount = 0; + constructor( + private tesingregisterSV: TestingRegisterService, + private cdr: ChangeDetectorRef + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.registerList); + if (this.registerList != null){ + this.studentcount = +this.registerList.length; + for (let i = 0; i < this.registerList.length; i++) { + const fee: number = +this.registerList[i].testing_fee; + this.tesingregisterSV.get(this.registerList[i].testing_register_uid).pipe( + tap(x => { + const countSub: any = x; + this.subjectcount += countSub.testing_subject_selecteds.length; + }), + tap(x => { + this.cdr.detectChanges(); + }), + ).subscribe( + ); + this.totalfee += fee; + } + this.cdr.detectChanges(); + } + } + +} diff --git a/src/app/feature/exam-register/receive-payment/receive-payment.module.ts b/src/app/feature/exam-register/receive-payment/receive-payment.module.ts new file mode 100644 index 0000000..cf3f4fe --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/receive-payment.module.ts @@ -0,0 +1,44 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReceivePaymentRouterComponent } from './router/receive-payment-router.component'; +import {RouterModule, Routes} from '@angular/router'; +import {SharedModule} from '../../../shared/shared.module'; +import { ReceivePaymentContainer } from './container/receive-payment/receive-payment.container'; +import { ReceivePaymentListComponent } from './presenter/list/receive-payment-list/receive-payment-list.component'; +import { ReceivePaymentSummaryComponent } from './presenter/summary/receive-payment-summary/receive-payment-summary.component'; +import { ReceivePaymentDetailComponent } from './presenter/detail/receive-payment-detail/receive-payment-detail.component'; +import { ReceivePaymentSearchComponent } from './presenter/search/receive-payment-search/receive-payment-search.component'; + + +const routes: Routes = [ + { + path: '', + component: ReceivePaymentRouterComponent, + children: [ + { + path: '', + component: ReceivePaymentContainer + }, + { + path: 'view/:id', + component: ReceivePaymentDetailComponent + }, + ] + } +]; +@NgModule({ + declarations: [ + ReceivePaymentRouterComponent, + ReceivePaymentContainer, + ReceivePaymentListComponent, + ReceivePaymentSummaryComponent, + ReceivePaymentDetailComponent, + ReceivePaymentSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class ReceivePaymentModule { } diff --git a/src/app/feature/exam-register/receive-payment/router/receive-payment-router.component.ts b/src/app/feature/exam-register/receive-payment/router/receive-payment-router.component.ts new file mode 100644 index 0000000..d7868c5 --- /dev/null +++ b/src/app/feature/exam-register/receive-payment/router/receive-payment-router.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-receive-payment-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReceivePaymentRouterComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.html b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.html new file mode 100644 index 0000000..5f0349d --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.html @@ -0,0 +1,8 @@ + + diff --git a/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.scss b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.spec.ts b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.spec.ts new file mode 100644 index 0000000..6597e85 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterCancelContainer } from './register-cancel.container'; + +describe('RegisterCancelContainer', () => { + let component: RegisterCancelContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterCancelContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterCancelContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.ts b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.ts new file mode 100644 index 0000000..d77fb23 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/container/register-cancel/register-cancel.container.ts @@ -0,0 +1,31 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import {StudentPaymentNotPaidService} from '../../../../../core/service/student-payment/student-payment-not-paid.service'; + +@Component({ + selector: 'app-register-cancel', + templateUrl: './register-cancel.container.html', + styleUrls: ['./register-cancel.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterCancelContainer implements OnInit { + studentRegisterList$ + query + constructor( + private studentPaymentNotPaidSV: StudentPaymentNotPaidService, + ) { } + + ngOnInit(): void { + } + + search(query){ + this.query = query; + if(this.query) return this.studentRegisterList$ = this.studentPaymentNotPaidSV.search(`?${this.query}`); + if(!this.query) return this.studentRegisterList$ = this.studentPaymentNotPaidSV.getAll(); + } + + getData(){ + if(this.query) return this.studentRegisterList$ = this.studentPaymentNotPaidSV.search(`?${this.query}`); + if(!this.query) return this.studentRegisterList$ = this.studentPaymentNotPaidSV.getAll(); + } + +} diff --git a/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.html b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.html new file mode 100644 index 0000000..2fbed8a --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.html @@ -0,0 +1,71 @@ + +
+
+
+

แสดงผลรายการค้นหา

+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + ลำดับ {{i+1}} รหัสผู้เข้าสอบ {{x.student_code}} ชื่อ-นามสกุล {{x.full_name}} ref1 {{x.ref1}} จำนวนเงิน {{x.testing_fee | number}} วันที่ลงทะเบียน {{x.created_datetime | thaidate}}
+ + +
+
+
+ + diff --git a/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.scss b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.spec.ts b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.spec.ts new file mode 100644 index 0000000..7aaeff1 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterCancelListComponent } from './register-cancel-list.component'; + +describe('RegisterCancelListComponent', () => { + let component: RegisterCancelListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterCancelListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterCancelListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.ts b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.ts new file mode 100644 index 0000000..0b41f42 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/list/register-cancel-list/register-cancel-list.component.ts @@ -0,0 +1,86 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {SelectionModel} from '@angular/cdk/collections'; +import {PeriodicElement} from '../../../../../manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {StudentPaymentNotPaidService} from '../../../../../../core/service/student-payment/student-payment-not-paid.service'; + +@Component({ + selector: 'app-register-cancel-list', + templateUrl: './register-cancel-list.component.html', + styleUrls: ['./register-cancel-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterCancelListComponent extends BaseList implements OnInit, OnChanges { + @Input() studentRegisterList: any = []; + @Output() OngetData = new EventEmitter(); + + + selection = new SelectionModel(true, []); + + /** Whether the number of selected elements matches the total number of rows. */ + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.studentRegisterList?.data?.length; + return numSelected === numRows; + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.studentRegisterList.data.forEach(row => this.selection.select(row)); + } + + /** The label for the checkbox on the passed row */ + checkboxLabel(row?: PeriodicElement): string { + if (!row) { + return `${this.isAllSelected() ? 'select' : 'deselect'} all`; + } + return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${ + row.position + 1 + }`; + } + column = ['1', '2', '3', '4', '5', '6', '7']; + constructor( + private studentPaymentNotPaidSV: StudentPaymentNotPaidService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.studentRegisterList = this.updateMatTable(this.studentRegisterList); + this.selection.clear() + } + + confirmCancel(){ + let rowData:any = this.selection.selected; + rowData = rowData.map((x) => { + return x.user_testing_register_uid; + }); + if (rowData.length !== 0){ + this.swSV.confirmText(`ต้องการยกเลิก ${this.selection.selected.length} รายการหรือไม่`).pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.studentPaymentNotPaidSV.putNotPaids(rowData).pipe( + tap(x => this.swSV.success('ยกเลิกเรียบร้อย')), + tap(x => this.selection.clear()), + tap(x => this.OngetData.emit()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + }else { + this.swSV.error('กรุณาเลือกผู้สอบ') + } + } + +} diff --git a/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.html b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.html new file mode 100644 index 0000000..6acc40c --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.html @@ -0,0 +1,19 @@ +

ค้นหา

+
+
+
+ + + + + + +
+
+
+
+ +
+
+
+
diff --git a/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.scss b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.spec.ts b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.spec.ts new file mode 100644 index 0000000..9c8517f --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterCancelSearchComponent } from './register-cancel-search.component'; + +describe('RegisterCancelSearchComponent', () => { + let component: RegisterCancelSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterCancelSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterCancelSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.ts b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.ts new file mode 100644 index 0000000..f38b40d --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/presenter/search/register-cancel-search/register-cancel-search.component.ts @@ -0,0 +1,29 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-register-cancel-search', + templateUrl: './register-cancel-search.component.html', + styleUrls: ['./register-cancel-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterCancelSearchComponent implements OnInit { + query = { + date: null + }; + @Output() search = new EventEmitter(); + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + if (this.query.date != null){ + this.query.date = formatDate(this.query.date, 'yyyy-MM-dd', 'en-US'); + } + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + +} diff --git a/src/app/feature/exam-register/register-cancel/register-cancel.module.ts b/src/app/feature/exam-register/register-cancel/register-cancel.module.ts new file mode 100644 index 0000000..7baf588 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/register-cancel.module.ts @@ -0,0 +1,41 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import {ManageReceiptRouterComponent} from '../manage-receipt/router/manage-receipt-router.component'; +import {ManageReceiptContainer} from '../manage-receipt/container/manage-receipt/manage-receipt.container'; +import { RegisterCancelRouter } from './router/register-cancel-router'; +import { RegisterCancelContainer } from './container/register-cancel/register-cancel.container'; +import { RegisterCancelListComponent } from './presenter/list/register-cancel-list/register-cancel-list.component'; +import { RegisterCancelSearchComponent } from './presenter/search/register-cancel-search/register-cancel-search.component'; + +const routes: Routes = [ + { + path: '', + component: RegisterCancelRouter, + children: [ + { + path: '', + component: RegisterCancelContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + + RegisterCancelRouter, + + RegisterCancelContainer, + + RegisterCancelListComponent, + + RegisterCancelSearchComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class RegisterCancelModule { } diff --git a/src/app/feature/exam-register/register-cancel/router/register-cancel-router.ts b/src/app/feature/exam-register/register-cancel/router/register-cancel-router.ts new file mode 100644 index 0000000..82d4c14 --- /dev/null +++ b/src/app/feature/exam-register/register-cancel/router/register-cancel-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterCancelRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.html b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.html new file mode 100644 index 0000000..07d55bb --- /dev/null +++ b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.html @@ -0,0 +1,45 @@ + + + +
+ + + + + + +
+
+
+
+ +
+
+
+ diff --git a/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.scss b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.spec.ts b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.spec.ts new file mode 100644 index 0000000..8090016 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterSummaryContainer } from './register-summary.container'; + +describe('RegisterSummaryContainer', () => { + let component: RegisterSummaryContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterSummaryContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterSummaryContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.ts b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.ts new file mode 100644 index 0000000..381e972 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/container/register-summary/register-summary.container.ts @@ -0,0 +1,457 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + ViewChild, + Output, + EventEmitter +} from '@angular/core'; +import {TestingRegisterService} from '../../../../../core/service/testing-register/testing-register.service'; +import {catchError, concatMap, filter, switchMap, tap} from 'rxjs/operators'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {from, Observable, throwError} from 'rxjs'; +import {MatDialog} from '@angular/material/dialog'; +import { + DialogChangeRoomComponent +} from '../../../../candidate-list/candidate-list/presenter/dialog/dialog-change-room/dialog-change-room.component'; +import {UserCounterLoginComponent} from '../../presenter/user-counter-login/user-counter-login.component'; +import {SharedUsercouterService} from '../../../../../core/service/testing-register/shared-usercouter.service'; +import {createQueryStringFromObject} from 'src/app/shared/util/func'; +import {RecieptService} from '../../../../../core/service/report/reciept/reciept.service'; +import {GetstudentService} from '../../../../../core/service/student/getstudent.service'; +import { + TestingRegisterIsPayService +} from '../../../../../core/service/testing-register/testing-register-is-pay.service'; +import {ActivatedRoute} from '@angular/router'; +import {RegisterSummaryFormComponent} from '../../presenter/form/register-summary-form/register-summary-form.component'; +import Swal, {SweetAlertResult} from 'sweetalert2'; +import {TableSummaryComponent} from '../../presenter/table-summary/table-summary/table-summary.component'; +import {formatDate} from "@angular/common"; +import { + ReceiptByPaymentCodeService +} from '../../../../../core/service/report/receipt-by-payment-code/receipt-by-payment-code.service'; +import { + TestingRegisterEnrollmentService +} from '../../../../../core/service/enrollment-api/testing-register-enrollment.service'; +import {UserCounterLoginService} from '../../../../../core/service/permission/user-counter-login.service'; +import {UserCountersService} from '../../../../../core/service/permission/user-counters.service'; +import { + RegisterSummarySummaryComponent +} from '../../presenter/summary/register-summary-summary/register-summary-summary.component'; + + +@Component({ + selector: 'app-register-summary', + templateUrl: './register-summary.container.html', + styleUrls: ['./register-summary.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterSummaryContainer implements OnInit { + @ViewChild(RegisterSummaryFormComponent) + childForm: RegisterSummaryFormComponent; + @ViewChild(RegisterSummarySummaryComponent) + childForm2: RegisterSummarySummaryComponent; + @ViewChild(TableSummaryComponent) + childForm3: TableSummaryComponent; + @Output() isPrint = false; + @Output() isCancel = false; + @Output() isMoney = false; + CandidateTypeName; + @Output() isHidebutton = false; + @Output() isPaymentBill = false; + @Output() onNewRegister = new EventEmitter(); + registerList$ = new Observable(); + userData$ = null; + studentData$: any = null; + summaryData$ = null; + ResetEvent; + + constructor( + private reportPaymentcode: ReceiptByPaymentCodeService, + private registerSV: TestingRegisterService, + private userCounterSV: UserCountersService, + private testingIsPaySV: TestingRegisterIsPayService, + private testingregisterEnrollSV: TestingRegisterEnrollmentService, + private reportRecieptSV: RecieptService, + private swSV: SweetalertService, + private activeRoute: ActivatedRoute, + private tesingregisterSV: TestingRegisterService, + public sharedCouterSV: SharedUsercouterService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private getStudentSV: GetstudentService, + ) { + } + + ngOnInit(): void { + const Logindata = this.sharedCouterSV.data; + if (Logindata == null) { + this.dialoglogin(); + } else { + this.userData$ = Logindata; + console.log(Logindata) + console.log(this.userData$) + this.registerList$ = this.userCounterSV.getCounterSummary(this.userData$.counter_no, this.userData$.counter_uid, this.userData$.counter_periods[0].period); + this.cdr.detectChanges(); + } + } + + emitEventToChild() { + this.ResetEvent.next(); + } + + dialoglogin() { + const dialogRef = this.dialog.open(UserCounterLoginComponent, { + disableClose: true, + width: '500px', + height: '250px', + }); + dialogRef.afterClosed().subscribe( + result => { + this.sharedCouterSV.data = result; + this.userData$ = result; + this.cdr.detectChanges(); + } + ); + } + + checkDate(dateOpen, dateClose) { + const dateFrom: any = formatDate(dateOpen, 'mm/dd/yyyy', 'en-US'); + const dateTo: any = formatDate(dateClose, 'mm/dd/yyyy', 'en-US'); + const dateCheck: any = formatDate(new Date(), 'mm/dd/yyyy', 'en-US'); + var d1 = dateFrom.split("/"); + var d2 = dateTo.split("/"); + var c = dateCheck.split("/"); + var from = new Date(d1[2], parseInt(d1[1]) - 1, d1[0]); // -1 because months are from 0 to 11 + var to = new Date(d2[2], parseInt(d2[1]) - 1, d2[0]); + var check = new Date(c[2], parseInt(c[1]) - 1, c[0]); + return check > from && check < to; + } + + + setCanditdatetypeName(data) { + this.CandidateTypeName = data; + } + + confirm(data) { + const recieveData = data.form; + + switch (data.status) { + case true: { + this.registerSV.add(recieveData).pipe( + tap(x => this.swSV.saveSuccess()), + // tap(x => this.childForm.isHidebutton = true), + catchError(err => { + this.childForm.confirm(false) + this.swSV.error(err.error); + return throwError(err); + }) + ).subscribe( + result => { + console.log(result); + this.summaryData$ = result; + this.childForm.updateForm(result); + console.log(this.summaryData$); + this.cdr.detectChanges(); + } + ); + break; + } + case 'update': { + this.registerSV.update2(recieveData).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.registerSV.get(recieveData.testing_register_uid).pipe( + tap(y => this.cdr.detectChanges()), + ).subscribe( + )), + // tap(x => this.childForm.isHidebutton = true), + catchError(err => { + this.childForm.confirm(false); + this.swSV.error(err.error); + return throwError(err); + }) + ).subscribe( + result => { + console.log(result); + this.summaryData$ = result; + this.childForm.updateForm(result); + this.cdr.detectChanges(); + } + ); + break; + } + } + } + + + recieveMoney(type) { + console.log(this.summaryData$); + const registerUid = this.summaryData$.testing_register_uid; + switch (type) { + case 'cash': + Swal.fire({ + icon: 'warning', + title: 'ยืนยันการรับเงินนี้ไหม?', + showDenyButton: true, + heightAuto: false, + confirmButtonText: 'ตกลง', + denyButtonText: `ยกเลิก`, + }).then((result) => { + if (result.isConfirmed) { + this.testingIsPaySV.recievedMoney(registerUid).pipe( + tap(x => this.isPrint = true), + // tap(x => this.isCancel = true), + tap(x => this.isMoney = true), + tap(x => console.log(x)), + tap(x => { + const data: any = x + this.summaryData$.payment_code = data.payment_code + }), + tap(x => this.isPaymentBill = true), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + Swal.fire({ + icon: 'success', + title: 'รับเงินเรียบร้อยแล้ว', + timer: 1000, + heightAuto: false + }).then(result => { + this.childForm2.updateSummary(); + // Swal.fire({ + // icon: 'warning', + // showDenyButton: true, + // heightAuto: false, + // confirmButtonText: 'สมัครผู้สมัครใหม่', + // denyButtonText: `ดูใบเสร็จ`, + // }).then((result) => { + // if (result.isConfirmed) { + // // this.testingIsPaySV.recievedMoney(registerUid).pipe( + // // tap(x => this.childForm.confirm('reset')), + // // tap(x => this.summaryData$ = null), + // // tap(x => this.isPrint = true), + // // tap(x => + // // Swal.fire('พร้อมสมัครคนถัดไป', '', 'success') + // // ), + // // tap(x => this.cdr.detectChanges()), + // // ).subscribe(); + // this.childForm.confirm('reset') + // this.summaryData$ = null + // this.isPaymentBill = true + // this.cdr.detectChanges() + // } else if (result.isDenied) { + // this.print(); + // this.summaryData$ = null + // // this.childForm.confirm('reset') + // } + // }); + // this.print(); + // this.isPaymentBill = true + // this.summaryData$ = null + // this.childForm.confirm('reset') + }) + } + }) + // code block + break; + case 'credit': + Swal.fire({ + icon: 'warning', + title: 'ยืนยันการชำระผ่าน Credit-Card', + showDenyButton: true, + heightAuto: false, + confirmButtonText: 'ตกลง', + denyButtonText: `ยกเลิก`, + }).then((result) => { + if (result.isConfirmed) { + Swal.fire({ + icon: 'warning', + title: 'ช่องทางการชำระเงินนี้ยังไม่พร้อมใช้งาน', + timer: 1000, + heightAuto: false + }).then(result => { + // this.isPaymentBill = true; + // this.isPrint = true; + // this.isMoney = true; + // this.childForm2.updateSummary(); + this.cdr.detectChanges() + }) + } + }) + break; + case 'paypal': + Swal.fire({ + icon: 'warning', + title: 'ยืนยันการชำระผ่าน Paypal', + showDenyButton: true, + heightAuto: false, + confirmButtonText: 'ตกลง', + denyButtonText: `ยกเลิก`, + }).then((result) => { + if (result.isConfirmed) { + Swal.fire({ + icon: 'warning', + title: 'ช่องทางการชำระเงินนี้ยังไม่พร้อมใช้งาน', + timer: 1000, + heightAuto: false + }).then(result => { + // this.isPaymentBill = true; + // this.isPrint = true; + // this.isMoney = true; + // this.childForm2.updateSummary(); + this.cdr.detectChanges() + }) + } + }) + break; + } + + } + + newRegister() { + this.summaryData$ = null; + this.isPrint = false; + this.isCancel = false; + this.isMoney = false; + this.isPaymentBill = false; + this.isHidebutton = false; + this.childForm.confirm('reset') + this.cdr.detectChanges(); + } + + cancelMoney() { + const registerUid = this.summaryData$.testing_register_uid; + Swal.fire({ + icon: 'warning', + title: 'ยืนยันการยกเลิกรายการนี้?', + showDenyButton: true, + heightAuto: false, + confirmButtonText: 'ตกลง', + denyButtonText: `ยกเลิก`, + }).then((result) => { + if (result.isConfirmed) { + this.testingregisterEnrollSV.deleteAdmin(registerUid).pipe( + tap(x => this.isPrint = true), + tap(x => this.isCancel = false), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + Swal.fire({ + icon: 'success', + title: 'ยกเลิกเรียบร้อย', + timer: 1000, + heightAuto: false + }).then(result => { + this.childForm2.updateSummary(); + this.summaryData$ = null; + this.isPaymentBill = false + this.childForm.confirm('reset') + }) + } + }) + } + + print() { + console.log(this.summaryData$); + const registerUid = this.summaryData$.testing_register_uid; + const paymentcode = this.summaryData$.payment_code; + // paymentcode = paymentcode.replace(/^..../g, ''); + // this.reportRecieptSV.getPdfReport(registerUid).subscribe(res => { + // const fileURL = URL.createObjectURL(res); + // window.open(fileURL, '_blank'); + // }); + this.reportPaymentcode.getPdfReport(paymentcode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } + + printreal() { + console.log(this.summaryData$); + const registerUid = this.summaryData$.testing_register_uid; + const paymentcode = this.summaryData$.payment_code; + // paymentcode = paymentcode.replace(/^..../g, ''); + this.reportPaymentcode.getPdfReportReceiptForAll(registerUid).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + // this.reportPaymentcode.getPdfReport(paymentcode).subscribe(res => { + // const fileURL = URL.createObjectURL(res); + // window.open(fileURL, '_blank'); + // }); + } + + search(query) { + console.log(query); + // this.getStudentSV.get(query).subscribe( + // result => { + // this.studentData$ = result; + // this.cdr.detectChanges(); + // }, + // error => { + // this.swSV.error('ไม่พบข้อมูล'); + // } + // ); + this.studentData$ = + { + student_name_th: 'นางสาวรุ่งอรุณ สว่าง', + student_name_en: 'MISS RUNGARUN SAWANG', + mobile_no: '0610656832', + student_code: query, + faculty_name_th: 'คณะมนุษยศาสตร์', + major_name_th: 'ภาษาอังกฤษ', + allow_register: [ + { + subject_name_th: 'ความรู้ความสามารถทั่วไป 2', + subject_name_en: 'string', + subject_code: 'GK002', + credit: 1 + }, + { + subject_name_th: 'ความรู้ความสามารถทั่วไป 1', + subject_name_en: 'string', + subject_code: 'GK001', + credit: 1 + } + ] + }; + this.cdr.detectChanges(); + } + + ResetRegister() { + this.childForm.confirm('reset'); + } + + logoutcouter() { + Swal.fire({ + icon: 'warning', + title: `ยืนยันการออกเค้าเตอร์ ${this.userData$.counter_pin}`, + showDenyButton: true, + heightAuto: false, + confirmButtonText: 'ตกลง', + denyButtonText: `ยกเลิก`, + }).then((result) => { + if (result.isConfirmed) { + this.userCounterSV.logout(this.userData$.counter_pin).pipe( + tap(x => this.isCancel = false), + tap(x => this.isPrint = true), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + Swal.fire({ + icon: 'success', + title: 'ออกเค้าเตอร์เรียบร้อย', + timer: 1000, + heightAuto: false + }).then(result => { + this.sharedCouterSV.data = null; + this.userData$ = null; + this.childForm.confirm('reset'); + this.cdr.detectChanges() + }); + } + }); + // this.userData$ = null; + // this.childForm.confirm('reset'); + // this.cdr.detectChanges(); + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.html b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.html new file mode 100644 index 0000000..9a9186f --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.html @@ -0,0 +1,25 @@ +
+
+

ค้นหาใบเสร็จสำหรับเคาเตอร์ {{this.query.counter_no}}

+
+
+ +
+
+ + +
+
+
+ +
+
+ +
+ + + +
diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.scss b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.spec.ts new file mode 100644 index 0000000..1507de7 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogCheckPaymentCounterComponent } from './dialog-check-payment-counter.component'; + +describe('DialogCheckPaymentCounterComponent', () => { + let component: DialogCheckPaymentCounterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogCheckPaymentCounterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogCheckPaymentCounterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.ts new file mode 100644 index 0000000..8ac0e93 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component.ts @@ -0,0 +1,61 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Inject} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {EnrollmentCounterPaymentsService} from '../../../../../../core/service/testing-register/enrollment-counter-payments.service'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {TestingRegisterEnrollmentService} from '../../../../../../core/service/enrollment-api/testing-register-enrollment.service'; +import {TestingRecieptService} from '../../../../../../core/service/testing-register/testing-reciept.service'; +import {ReceiptByPaymentCodeService} from '../../../../../../core/service/report/receipt-by-payment-code/receipt-by-payment-code.service'; + +@Component({ + selector: 'app-dialog-check-payment-counter', + templateUrl: './dialog-check-payment-counter.component.html', + styleUrls: ['./dialog-check-payment-counter.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogCheckPaymentCounterComponent implements OnInit { + paymentData$ = new Observable(); + + query = { + student_code: null, + counter_no: null, + counter_pin: null, + }; + + constructor( + private swSV: SweetalertService, + private testingrecieptsSV: TestingRecieptService, + private reportPaymentcode: ReceiptByPaymentCodeService, + private enrollentCounterPaymentSV: EnrollmentCounterPaymentsService, + private testingregisterEnrollSV: TestingRegisterEnrollmentService, + private cdr: ChangeDetectorRef, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { } + + ngOnInit(): void { + this.query.counter_no = this.data.data.counter_no; + this.query.counter_pin = this.data.data.counter_pin; + } + + search(){ + const query = createQueryStringFromObject(this.query); + console.log(query); + if(query) return this.paymentData$ = this.testingrecieptsSV.search(`?${query}`); + } + + print(paymentCode){ + // console.log(paymentCode); + if (paymentCode !== null){ + this.reportPaymentcode.getPdfReportReceiptForAll(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + }else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.html b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.html new file mode 100644 index 0000000..2baf61e --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.html @@ -0,0 +1,51 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เลขที่ใบเสร็จ {{x.payment_code}} วันที่ออกใบเสร็จ {{x.payment_datetime | thaidate }} {{x.payment_datetime | date: 'hh:mm:ss' }} Counter {{x.counter_no}} สถานะ +
+ ยกเลิก +
+
+ ใช้งาน +
+
จำนวนเงิน(บาท) {{x.total_amount}} เครื่องมือ + +
+ +
+
diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.scss b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.spec.ts new file mode 100644 index 0000000..7080a94 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListPaymentCounterComponent } from './list-payment-counter.component'; + +describe('ListPaymentCounterComponent', () => { + let component: ListPaymentCounterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListPaymentCounterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListPaymentCounterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.ts new file mode 100644 index 0000000..797961a --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component.ts @@ -0,0 +1,62 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../../core/base/base-list'; +import { + ReceiptByPaymentCodeService +} from '../../../../../../../core/service/report/receipt-by-payment-code/receipt-by-payment-code.service'; +import {SweetalertService} from '../../../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-list-payment-counter', + templateUrl: './list-payment-counter.component.html', + styleUrls: ['./list-payment-counter.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListPaymentCounterComponent extends BaseList implements OnInit, OnChanges { + @Output() reprint = new EventEmitter(); + @Output() OnCancelPay = new EventEmitter(); + @Input() paymentData: any = []; + column = ['0', '1', '2', '3', '4', '5']; + constructor( + private reportPaymentcode: ReceiptByPaymentCodeService, + private swSV: SweetalertService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.paymentData) + this.paymentData = this.updateMatTable(this.paymentData ? this.paymentData : []); + } + + print(paymentCode, type: any){ + // console.log(paymentCode); + if (paymentCode !== null){ + this.reportPaymentcode.getPdfReportReceiptForAll(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + }else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + printReal(paymentCode, type: any){ + // console.log(paymentCode); + if (paymentCode !== null){ + this.reportPaymentcode.getPdfReportRealUat(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + }else { + this.swSV.error('กรุณากดรับเงินใหม่'); + } + } + + cancelPay(registerUid){ + console.log(registerUid) + this.OnCancelPay.emit(registerUid); + } +} diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.html b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.html new file mode 100644 index 0000000..0f9232d --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.html @@ -0,0 +1,32 @@ +
+
+

ค้นหารายการนักศึกษา

+
+
+ +
+
+ + +
+ + + + +
+ + +
+
+
+ +
+
+
+ + + +
diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.scss b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.spec.ts new file mode 100644 index 0000000..5f8d662 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogEnrollmentCounterPaymentComponent } from './dialog-enrollment-counter-payment.component'; + +describe('DialogEnrollmentCounterPaymentComponent', () => { + let component: DialogEnrollmentCounterPaymentComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogEnrollmentCounterPaymentComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogEnrollmentCounterPaymentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.ts new file mode 100644 index 0000000..45b286a --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component.ts @@ -0,0 +1,66 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {Observable, throwError} from 'rxjs'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {EnrollmentCounterPaymentsService} from '../../../../../../core/service/testing-register/enrollment-counter-payments.service'; + +@Component({ + selector: 'app-dialog-enrollment-counter-payment', + templateUrl: './dialog-enrollment-counter-payment.component.html', + styleUrls: ['./dialog-enrollment-counter-payment.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogEnrollmentCounterPaymentComponent implements OnInit { + enrollmentData$ = new Observable() + + query = { + student_code: null, + id_card: null, + payment_code: null, + }; + constructor( + private swSV: SweetalertService, + private enrollentCounterPaymentSV: EnrollmentCounterPaymentsService, + private cdr: ChangeDetectorRef, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { } + + ngOnInit(): void { + console.log(this.data); + + } + + search(){ + const query = createQueryStringFromObject(this.query); + console.log(query); + if(query) return this.enrollmentData$ = this.enrollentCounterPaymentSV.search(`?${query}`); + } + + pay(registerUid){ + this.swSV.confirmText('ยืนยันการรับเงินใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.enrollentCounterPaymentSV.postRecieve( + registerUid, + this.data.data.counter_no, + this.data.data.counter_pin, + this.data.data.counter_periods[0].period).pipe( + tap(x => this.swSV.success('รับเงินสำเร็จ')), + tap(x => { + const query = createQueryStringFromObject(this.query); + this.enrollmentData$ = this.enrollentCounterPaymentSV.search(`?${query}`); + }), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.html b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.html new file mode 100644 index 0000000..f7e39c2 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.html @@ -0,0 +1,40 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + +
ชื่อ - นามสกุล {{x.full_name}} รอบสอบ {{x.testing_information_name}} ค่าธรรมเนียม {{x.testing_fee}} เครื่องมือ +
+ + +
+
+ +
+
diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.scss b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.spec.ts new file mode 100644 index 0000000..49fd631 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListEnrollmentCounterPaymentComponent } from './list-enrollment-counter-payment.component'; + +describe('ListEnrollmentCounterPaymentComponent', () => { + let component: ListEnrollmentCounterPaymentComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListEnrollmentCounterPaymentComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListEnrollmentCounterPaymentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.ts b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.ts new file mode 100644 index 0000000..9afa404 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component.ts @@ -0,0 +1,46 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../../core/service/security/app-token.service'; +import { + ReceiptByPaymentCodeService +} from '../../../../../../../core/service/report/receipt-by-payment-code/receipt-by-payment-code.service'; + +@Component({ + selector: 'app-list-enrollment-counter-payment', + templateUrl: './list-enrollment-counter-payment.component.html', + styleUrls: ['./list-enrollment-counter-payment.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListEnrollmentCounterPaymentComponent extends BaseList implements OnInit, OnChanges { + @Output() pay = new EventEmitter(); + + @Input() enrollmentData: any = []; + column = ['0', '1', '2', '3']; + + constructor( + private reportPaymentcode: ReceiptByPaymentCodeService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.enrollmentData) + this.enrollmentData = this.updateMatTable(this.enrollmentData ? this.enrollmentData : []); + } + + onPay(testRegisterUid){ + this.pay.emit(testRegisterUid); + } + + onPrint(paymentCode){ + // const paymentcode = paymentCode.replace(/^..../g, ''); + this.reportPaymentcode.getPdfReportReceiptForAll(paymentCode).subscribe(res => { + const fileURL = URL.createObjectURL(res); + window.open(fileURL, '_blank'); + }); + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.html b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.html new file mode 100644 index 0000000..74580cf --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.html @@ -0,0 +1,456 @@ +
+  {{userData | json}}
+
+
+  {{PeriodListsNews | json}}
+
+
+ + + + + + + + +
+
+
+ + +
+
+
+
+ + + +
+
+
+
+        {{this.chooseID | json}}
+    
+
+
+ + +
+
+
+ + +
+ +
+ + + + + + + + + + +
+
+
+
+ +
+

ตรวจสอบรหัสนักศึกษาโครงการ

+
+
+
+ + + +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + + + + + +
+ +
+ + + + + +
+ +
+ + +
+ +
+ + + + + + + + + + +
+
+
+
+ + + + + + + + +
+ + + +
+
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + + +
+
+ +
+
+ + +
+ +
+ + + + + + + + +
+
+ + + + + + + +
+ + +

กระบวนวิชาที่เลือก

+
+
+
+
+
+ + + + + +
+ +
+ + + + + + + + --เลือกวิชา-- + + + {{x.subject_code}} - {{x.subject_name_th}} + + + +
+ +
+ +
+
+ + +
+ +
+ + + + + --เลือกศูนย์สอบ-- + + + {{x.branch_name_th}} + + + +
+ +
+ + +
+
+ + + + + --เลือกสนามสอบ-- + + + {{x.testing_field_name_th}} + + + +
+
+ +
+
+ + + + + + + +
+
+ + + + + --เลือก Section-- + + + Section {{x.period_id}} {{x.start_time}} + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + +
+
+
+
+
+
+
+ {{isHidebutton}} +
+
+ + + + + + + +
+ +
+ +
+ +
{{form.getRawValue() | json}}
+ + + diff --git a/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.scss b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.scss new file mode 100644 index 0000000..0180161 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.scss @@ -0,0 +1,14 @@ +::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline { + background-color: white; + border-radius: 5px; +} + +iframe.noScrolling { + width: 250px; /*or any other size*/ + height: 300px; /*or any other size*/ + overflow: hidden; +} + +iframe { + overflow: hidden; +} diff --git a/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.spec.ts new file mode 100644 index 0000000..7700276 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterSummaryFormComponent } from './register-summary-form.component'; + +describe('RegisterSummaryFormComponent', () => { + let component: RegisterSummaryFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterSummaryFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterSummaryFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.ts b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.ts new file mode 100644 index 0000000..086e81f --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/form/register-summary-form/register-summary-form.component.ts @@ -0,0 +1,1396 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Output, + EventEmitter, + Input, + OnChanges +} from '@angular/core'; +import {FormArray, FormBuilder, FormGroup, NG_VALIDATORS, Validators} from '@angular/forms'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {FacultysService} from '../../../../../../core/service/settings/facultys.service'; +import {DepartmentService} from '../../../../../../core/service/settings/department.service'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {UploadService} from '../../../../../../core/service/upload/upload.service'; +import {MatDialog} from '@angular/material/dialog'; +import {PreviewImageComponent} from '../../preview/preview-image/preview-image.component'; +import {CheckAvailableRoomService} from '../../../../../../core/service/testing-register/check-available-room.service'; +import {formatDate} from '@angular/common'; +import {realCitizenIdValidator} from '../../../../../../shared/validator/real-citizen-id.validator'; +import {StudentService} from '../../../../../../core/service/student/student.service'; +import {Subject, throwError} from 'rxjs'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import { + TestingSubjectAddDateService +} from '../../../../../../core/service/testing-information/testing-subject-add-date.service'; +import { + ApproveDialogComponent +} from '../../../../../approve-examination/feature/dialog/approve-dialog/approve-dialog.component'; +import { + DialogEnrollmentCounterPaymentComponent +} from '../../dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component'; +import { + DialogCheckPaymentCounterComponent +} from '../../dialog/dialog-check-payment-counter/dialog-check-payment-counter.component'; +import { + CheckSubjectAndDateService +} from "../../../../../../core/service/testing-register/check-subject-and-date.service"; + +@Component({ + selector: 'app-register-summary-form', + templateUrl: './register-summary-form.component.html', + styleUrls: ['./register-summary-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterSummaryFormComponent extends BaseForm implements OnInit, OnChanges { + isStudentSpecial = false; + isupdateForm = false; + @Output() candidateTypeName = new EventEmitter(); + today = formatDate(new Date(), 'yyyy-MM-dd', 'en-US'); + @Input() updateDataForm; + @Input() isMoney = false; + @Input() isHidebutton = false; + isLimit = null; + isLimitData; + isSubTestInfor = null; + + constructor( + public fb: FormBuilder, + private swSV: SweetalertService, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + public dialog: MatDialog, + private cdr: ChangeDetectorRef, + private academicsemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private testinginformationSV: TestingInformationService, + private testingsubjectadddateSV: TestingSubjectAddDateService, + private testingFieldSV: TestingFieldService, + private studentSV: StudentService, + private facultySV: FacultysService, + private departmentSV: DepartmentService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private educationtypeSV: EducationTypesService, + private uploadSV: UploadService, + private checkAvRoomSV: CheckAvailableRoomService, + private checkSubandDateSV: CheckSubjectAndDateService, + ) { + super( + router, + activeRoute, + fb, + location + ); + this.form = this.fb.group({ + // status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_register_uid: null, + photo1_url: null, + photo1_name: null, + photo2_url: null, + photo2_name: null, + // examinee_card: [null, [Validators.required, realCitizenIdValidator]], + // examinee_card: [null, Validators.required], + student_code: [null, Validators.required], + check_student_code: null, + examinee_full_name: [null, Validators.required], + faculty_uid: null, + department_name: null, + agency_name: null, + candidate_type_uid: [null, Validators.required], + examinee_mobile: null, + counter_no: null, + counter_pin: null, + counter_period: null, + testing_fee: '', + testing_information_uid: [null, Validators.required], + payment_uid: 0, + user_name: null, + is_cancel: false, + testing_subject_selecteds: this.fb.array([ + this.testing_subject_selecteds() + ]), + }); + } + + form; + LimitPeriodData = []; + imageSrc2: string; + imageSrc1: string; + selectfile; + AcademicSemLists; + AcademicYearLists; + AcademicYearCode; + AcademicSemCode; + TestInformationID; + subTestInformtionID; + TestingInformationLists: any = []; + newMaintestinginformationuID; + FacultyLists: any = []; + DepartmentLists: any = []; + TestcenterLists: any = []; + TestFieldLists: any = []; + TestRoomLists: any = []; + SubjectLists: any = []; + EducationTypeLists: any = []; + PeriodLists: any = []; + PeriodListsNews: any = []; + Daterange = { + testing_start_datetime: null, + testing_end_datetime: null, + }; + chooseID = { + idTest: null, + startrangedayTest: null, + endrangedayTest: null, + isLimit: null, + idSub: null, + startrangedaySub: null, + endrangedaySub: null, + }; + queryForChecklimit = { + testing_information_uid: null, + subject_uid: null, + testing_date: null, + subject_code: null, + testing_subject_uid: null, + }; + Lists; + daywithout2 = []; + @Input() userData: any = []; + @Input() studentData: any = []; + @Output() onConfirm = new EventEmitter(); + @Output() delete = new EventEmitter(); + myFilter = (d: Date): boolean => { + if (this.daywithout2.length != 0) { + const time = d.getTime(); + return !this.daywithout2.find(x => x.getTime() === time); + } else { + return !this.daywithout2.find(x => x.getTime() === null); + } + + } + + testing_subject_selecteds() { + return this.fb.group({ + testing_subject_selected_uid: null, + testing_register_uid: null, + testing_center_uid: [null, Validators.required], + is_main: true, + subject_uid: [null, Validators.required], + subject_code: [null, Validators.required], + testing_datetime: [null, Validators.required], + period_id: [null, Validators.required], + branch_uid: [null, Validators.required], + testing_field_uid: [null, Validators.required], + testing_seat: null, + is_cancel: false + }); + } + + ngOnInit(): void { + // console.log(this.studentData); + // this.form.disable(); + this.academicsemSV.getAll().subscribe( + result => { + this.AcademicSemLists = result; + this.cdr.detectChanges(); + } + ); + this.academicYearSV.getAll().subscribe( + result => { + this.AcademicYearLists = result; + this.cdr.detectChanges(); + } + ); + this.facultySV.getAll().subscribe( + result => { + this.FacultyLists = result; + this.cdr.detectChanges(); + } + ); + this.testinginformationSV.getDatatype().subscribe( + result => { + const data: any = result; + data.splice(data.findIndex(e => e.candidate_type_name_th === 'นักศึกษา'), 1); + this.EducationTypeLists = data; + this.cdr.detectChanges(); + } + ); + } + + ngOnChanges() { + if (this.userData !== '') { + console.log(this.userData); + this.form.get('counter_no').setValue(this.userData.counter_no); + this.form.get('counter_pin').setValue(this.userData.counter_pin); + this.form.get('counter_period').setValue(this.userData.counter_periods[0].period); + } + console.log(this.studentData); + if (this.studentData != null) { + this.setInformationbyStudentData(this.studentData.allow_register); + this.form.get('student_code').setValue(this.studentData.student_code); + this.form.get('examinee_full_name').setValue(this.studentData.student_name_th); + this.form.get('examinee_mobile').setValue(this.studentData.mobile_no); + this.form.get('department_name').setValue(this.studentData.major_name_th); + } + this.cdr.detectChanges(); + } + + add(index) { + const form = this.form.get('testing_subject_selecteds') as FormArray; + const TestInforUid = this.form.get('testing_information_uid').value; + // const FormarraySelect = form.at(index).value; + // const indexSec = this.sectionsFake.findIndex((x) => { + // return x.period_id === FormarraySelect.period_id; + // }); + // this.sectionsFake[indexSec].is_check = false; + this.testinginformationSV.get(this.chooseID.idTest).pipe( + tap(x => { + const subjectlist: any = x; + this.TestcenterLists.push(subjectlist.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, [])) + this.TestFieldLists.push(subjectlist.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.testing_field_uid === o.testing_field_uid)) { + unique.push(o); + } + return unique; + }, [])) + }), + ).subscribe(); + + form.push(this.testing_subject_selecteds()); + } + + removeArray(i) { + const form = this.form.get('testing_subject_selecteds') as FormArray; + const Form = this.form.getRawValue(); + const Formarray2 = form.at(i) as FormGroup; + const FormarraySelect = form.at(i).value; + console.log(FormarraySelect) + if (FormarraySelect.subject_uid != null) { + const foundIndex = this.SubjectLists.findIndex(x => x.subject_uid === FormarraySelect.subject_uid); + this.SubjectLists[foundIndex].status_id = true + const filteredList = this.PeriodLists; + this.PeriodListsNews[i] = filteredList; + const array = this.PeriodListsNews; + const firstIndex = i; + } + this.testinginformationSV.get(this.chooseID.idTest).pipe( + tap(x => { + const data: any = x; + this.TestcenterLists[i] = data.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []); + this.TestFieldLists[i] = data.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.testing_field_uid === o.testing_field_uid)) { + unique.push(o); + } + return unique; + }, []); + }), + ).subscribe(); + form.removeAt(i); + this.cdr.detectChanges(); + } + + onDelete(id) { + this.delete.emit(id); + } + + confirm(status) { + switch (status) { + case true: { + console.log('confirm'); + this.isHidebutton = true; + // this.onConfirm.emit({'this.form','any'}); + this.onConfirm.emit({form: this.form.getRawValue(), status}); + break; + } + case false: { + this.isHidebutton = false; + this.cdr.detectChanges() + console.log('cancel'); + break; + } + case 'reset': { + this.form.reset(); + if (this.userData !== '') { + console.log(this.userData); + this.isHidebutton = false; + this.form.get('counter_no').setValue(this.userData.counter_no); + this.form.get('counter_pin').setValue(this.userData.counter_pin); + this.form.get('counter_period').setValue(this.userData.counter_periods[0].period); + const form = this.form.get('testing_subject_selecteds') as FormArray; + this.imageSrc1 = null; + this.imageSrc2 = null; + form.clear(); + form.push(this.testing_subject_selecteds()) + this.TestcenterLists = []; + this.TestFieldLists = []; + this.SubjectLists = []; + this.cdr.detectChanges() + } else { + this.swSV.error('กรุณาล็อคอินใหม่'); + } + // this.form.get('user_name').setValue(this.userData.user_name); + this.isHidebutton = false; + this.cdr.detectChanges(); + break; + } + case 'update': { + console.log('update'); + this.isHidebutton = true; + this.onConfirm.emit({form: this.form.getRawValue(), status}); + break; + } + default: { + console.log('FAIL'); + break; + } + } + } + + updateForm(FormResult) { + this.form.get('testing_register_uid').setValue(FormResult.testing_register_uid); + const PresentForm = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + let NewForm = []; + NewForm = FormResult.testing_subject_selecteds.filter(x => { + return !!PresentForm.testing_subject_selecteds.map((y, index) => { + if (x.subject_uid === y.subject_uid) { + x.formindex = index + y.testing_subject_selected_uid = x.testing_subject_selected_uid; + y.testing_seat = x.testing_seat; + x.testing_register_uid = FormResult.testing_register_uid; + return x; + } + }); + }); + if (NewForm.length != 0) { + for (let i = 0; i < NewForm.length; i++) { + Formarray.at(NewForm[i].formindex).get('testing_subject_selected_uid').setValue(NewForm[i].testing_subject_selected_uid); + Formarray.at(NewForm[i].formindex).get('testing_register_uid').setValue(NewForm[i].testing_register_uid); + Formarray.at(NewForm[i].formindex).get('testing_seat').setValue(NewForm[i].testing_seat); + } + } + } + + setDepartment(data) { + this.departmentSV.query(`?faculty_uid=${data}`).subscribe( + result => { + this.DepartmentLists = result; + } + ); + } + + setYearSem(data) { + // console.log(data); + // console.log(this.studentData); + this.SubjectLists = []; + this.TestcenterLists = []; + this.TestFieldLists = []; + this.PeriodListsNews = []; + this.PeriodLists = []; + this.daywithout2 = []; + this.TestInformationID = data; + let subMain: any = []; + this.newMaintestinginformationuID = null; + const form = this.form.get('testing_subject_selecteds') as FormArray; + form.clear() + form.push(this.testing_subject_selecteds()); + this.testinginformationSV.get(data).pipe( + tap(x => { + // for (let i = 0; i < form.getRawValue().length; i++) { + // form.at(i).get('branch_uid').setValue(null); + // form.at(i).get('testing_field_uid').setValue(null); + // } + console.log('เตรียม PeriodLists') + const data: any = x; + this.PeriodLists = data.testing_periods; + for (let i = 0; i < this.PeriodLists.length; i++) { + this.PeriodLists[i].status_id = true; + } + }), + tap(x => { + console.log('เตรียม PeriodListsNews') + let ArrayTest = []; + const data: any = x; + for (let i = 0; i < data.testing_subjects.length; i++) { + this.PeriodListsNews.push(this.PeriodLists); + // Array1 = [...Array1 , ...this.PeriodLists] + } + // const myClonedArray = Object.assign([], ArrayTest); + }), + tap(x => { + console.log('เตรียม วันห้ามสอบ') + const data: any = x; + if (data.days_without_testings.length !== 0) { + // this.daywithout2 = []; + for (let i = 0; i < data.days_without_testings.length; i++) { + const newDate = formatDate(data.days_without_testings[i].date_without_testing, 'M/d/yy', 'en-US'); + const FilterDate = new Date(newDate); + this.daywithout2.push(FilterDate); + console.log(this.daywithout2); + this.cdr.detectChanges(); + } + } + }), + tap(x => { + // เช็คว่าโครงการที่เลือกอันนี้เป็นรอบสอบหลัก หรือ รอบสอบขยาย + console.log('เช็คว่าโครงการที่เลือกอันนี้เป็นรอบสอบหลัก หรือ รอบสอบขยาย') + const subjectlist: any = x; + if (subjectlist.main_testing_information_uid === null) { + this.chooseID.idTest = subjectlist.testing_information_uid; + this.chooseID.startrangedayTest = this.formatDate(subjectlist.testing_start_datetime); + this.chooseID.endrangedayTest = this.formatDate(subjectlist.testing_end_datetime); + this.SubjectLists = subjectlist.testing_subjects; + for (let i = 0; i < this.SubjectLists.length; i++) { + this.SubjectLists[i].status_id = true; + } + this.Daterange.testing_start_datetime = this.formatDate(subjectlist.testing_start_datetime); + this.Daterange.testing_end_datetime = this.formatDate(subjectlist.testing_end_datetime); + this.cdr.detectChanges(); + this.AcademicYearCode = subjectlist; + } + }), + tap(x => { + // เช็คว่าโครงการที่เลือกอันนี้เป็นรอบสอบหลัก หรือ รอบสอบขยาย + console.log('เตรียมสถานที่สอบ') + + const subjectlist: any = x; + // นำข้อมูล สถานที่สอบมาใส่ใน Fill + // this.TestcenterLists = subjectlist.testing_rooms; + // this.TestcenterLists.push(subjectlist.testing_rooms); + // this.TestFieldLists = subjectlist.testing_rooms.reduce((unique, o) => { + // if (!unique.some(obj => obj.testing_field_uid === o.testing_field_uid)) { + // console.log(o) + // unique.push(o); + // } + // return unique; + // }, []); + if (this.TestcenterLists.length == 0) { + this.TestcenterLists.push(subjectlist.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, [])) + } + // if (this.TestFieldLists.length == 0){ + // this.TestFieldLists.push(subjectlist.testing_rooms.reduce((unique, o) => { + // if (!unique.some(obj => obj.testing_field_uid === o.testing_field_uid)) { + // unique.push(o); + // } + // return unique; + // }, [])) + // } + // this.TestRoomLists = subjectlist.testing_rooms; + // this.TestRoomLists.push(subjectlist.testing_rooms); + // this.TestcenterLists = this.TestcenterLists.reduce((unique, o) => { + // if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + // unique.push(o); + // } + // return unique; + // }, []); + + }), + tap(x => { + console.log(6) + + // นำข้อมูล Student ที่ Import มาขัดตามวิชาที่อนุญาต + if (this.studentData !== null) { + this.SubjectLists = this.SubjectLists.filter(item1 => + !!this.studentData.allow_register.find(item2 => item1.subject_code === item2.subject_code) + ); + } + if (this.SubjectLists.length === 1) { + form.patchValue([ + {subject_uid: this.SubjectLists[0].subject_uid,}, + ]); + } + }), + tap(x => { + console.log(7) + // นำข้อมูล Student ที่ Import มาขัดตามวิชาที่อนุญาต + if (this.studentData !== null) { + this.SubjectLists = this.SubjectLists.filter(item1 => + !!this.studentData.allow_register.find(item2 => item1.subject_code === item2.subject_code) + ); + } + if (this.SubjectLists.length === 1) { + form.patchValue([ + {subject_uid: this.SubjectLists[0].subject_uid,}, + ]); + } + }), + tap(x => { + // Check มีรอบสอบที่เลือกมีรอบสอบขยายหรือเปล่า + console.log(8) + this.testinginformationSV.getCheckmaintrue(data).subscribe( + result => { + subMain = result; + this.newMaintestinginformationuID = subMain[0]; + // มีรอบสอบขยาย + if (subMain.length !== 0) { + this.chooseID.idSub = subMain[0].testing_information_uid; + this.chooseID.startrangedaySub = this.formatDate(subMain[0].testing_start_datetime); + this.chooseID.endrangedaySub = this.formatDate(subMain[0].testing_end_datetime); + this.Daterange.testing_end_datetime = this.chooseID.endrangedaySub; + this.cdr.detectChanges(); + } + } + ); + }), + ).subscribe(); + this.cdr.detectChanges(); + } + + filterbystudentData(subjectlist) { + const filterSubject = this.studentData.allow_register; + console.log(filterSubject); + console.log(subjectlist); + return subjectlist.filter(x => filterSubject.some(y => y.subject_code === x.subject_code)); + // return subjectfiltered; + } + + setregisterdataForm(data) { + console.log(data); + console.log(this.TestcenterLists); + this.testcenterSV.get(data).subscribe( + result => { + console.log(result); + this.PeriodLists = result; + // this.testingFieldSV.getAll().subscribe( + // result => { + // console.log(result); + // this.TestFieldLists = result; + // this.cdr.detectChanges(); + // } + // ); + } + ); + } + + setSection(data, index) { + const Form = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + const FormarraySelect = Formarray.at(index).value; + FormarraySelect.testing_information_uid = Form.testing_information_uid; + FormarraySelect.testing_datetime = this.formatDate(FormarraySelect.testing_datetime); + this.checkAvRoomSV.add(FormarraySelect).subscribe( + result => { + Formarray2.get('testing_center_uid').setValue(result[0].testing_center_uid); + this.swSV.success('ค้นหาห้องพบ'); + }, + error => { + this.swSV.errTextandSub('ห้องสอบเต็ม', 'กรุณาเลือกวันสอบหรือ Section อื่น'); + + } + ); + } + + setInformationbyStudentData(data) { + this.TestingInformationLists = this.TestingInformationLists.filter(item1 => + !!data.find(item2 => item1.academic_year_code === item2.academic_year) + ); + } + + checkavailableroom(index: any) { + let DoFloat = null; + const Form = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + const FormarraySelect = Formarray2.getRawValue(); + if (Form.testing_information_uid != null) { + DoFloat = this.checkSameDayandPeriod(index); + console.log(DoFloat); + if (DoFloat === true) { + if (FormarraySelect.testing_datetime == null) { + console.log('กรุณาเลือกวันที่1') + + return this.swSV.error('กรุณาเลือกวันที่'); + } else { + if (FormarraySelect.period_id != null) { + if (FormarraySelect.is_main === true) { + FormarraySelect.testing_information_uid = this.chooseID.idTest; + } else { + FormarraySelect.testing_information_uid = this.chooseID.idSub; + } + FormarraySelect.testing_datetime = this.formatDate(FormarraySelect.testing_datetime); + console.log(FormarraySelect); + if (FormarraySelect.testing_datetime !== null) { + this.checkAvRoomSV.add(FormarraySelect).subscribe( + result => { + const responData: any = result; + if (responData.length !== 0) { + Formarray2.get('testing_center_uid').setValue(responData[0].testing_center_uid); + // this.swSV.success('ค้นหาห้องพบ').pi; + this.swSV.successThen('ค้นหาห้องพบ').pipe( + filter(x => x.isConfirmed), + concatMap(async (x) => { + this.checkSubandDateSV.add(this.form.getRawValue()).pipe( + catchError(err => { + console.log('ERR') + console.log(err) + this.swSV.errText(err.error); + const foundIndex = this.SubjectLists.findIndex(x => x.subject_uid === FormarraySelect.subject_uid); + this.SubjectLists[foundIndex].status_id = true + const backupIsmain = Formarray2.get('is_main').value; + Formarray2.reset(); + Formarray2.get('is_main').setValue(backupIsmain); + return throwError(err); + }) + ).subscribe(); + // this.swSV.success('AFA') + }) + ).subscribe(); + } else { + Formarray2.get('period_id').setValue(null); + this.swSV.errTextandSub('ห้องสอบเต็ม', 'กรุณาเลือกวันสอบหรือ Section อื่น'); + + } + }, + error => { + console.log(error) + this.swSV.errTextandSub('ห้องสอบเต็ม', 'กรุณาเลือกวันสอบหรือ Section อื่น'); + } + ); + } else { + console.log('กรุณาเลือกวันที่2') + + return this.swSV.errorBig('กรุณาเลือกวันที่'); + } + } + } + } else { + Formarray2.get('period_id').setValue(null); + return this.swSV.errorBig('มีวันที่สอบกับSection ซ้ำกัน'); + + } + } + + } + + checkSameDayandPeriod(index) { + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Data = Formarray.getRawValue(); + let arr = Formarray.getRawValue(); + arr = arr.filter(x => { + if (x.testing_datetime !== null && x.period_id !== null) { + return x + } + }) + return this.checkDuplicate2(arr); + } + + checkDuplicate2(arr) { + const isDupicate = arr.map((value) => { + if (value.testing_datetime != null && value.period_id != null) { + return value.testing_datetime.getTime() + value.period_id; + } + }).some((value, index, array) => { + return array.indexOf(value) !== array.lastIndexOf(value); + }); + return !isDupicate; + } + + checkDuplicate(arr) { + const checkDuplicate = (array) => { + return array + .map((value) => { + console.log(value) + + // console.log("value: ", value.testing_datetime.getTime() + value.period_id); + if (value.testing_datetime != null && value.period_id != null) { + console.log(value.testing_datetime.getTime() + value.period_id) + + return value.testing_datetime.getTime() + value.period_id; + } else { + console.log(value) + return 'FAIL' + } + }) + .some((value, index, array) => { + // console.log("value: ", value); + // console.log("Array: ", array); + // console.log("A: ", array.indexOf(value)); + // console.log("B: ", array.lastIndexOf(value)); + return array.indexOf(value) !== array.lastIndexOf(value); + }); + }; + // console.log("checkDuplicate: ", checkDuplicate(arr)); + console.log('checkDuplicate: ', checkDuplicate(arr)); + return !checkDuplicate; + } + + + switchTestInfor(data, index) { + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + const FormarraySelect = Formarray2.getRawValue(); + console.log(Formarray2.getRawValue()); + console.log(this.chooseID); + + } + + // เช็คว่ามีการ Limit Period หรือเปล่า + checkIsLimit(date, index) { + const Form = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + const SubjectCode = Formarray2.get('subject_code').value; + const testInforUid = Form.testing_information_uid; + const result = new Subject(); + this.testingsubjectadddateSV.FindLimitPeriod(testInforUid, date, SubjectCode).subscribe( + res => { + if (res) { + const data: any = res + if (data.length !== 0) { + this.isLimit = true + } else { + this.isLimit = false + this.PeriodListsNews[index] = this.PeriodLists + } + result.next(res) + } + } + ); + return result.asObservable(); + } + + compareIsLimitandIsChoose(index, dateselect) { + let newArray = []; + const firstIndex = index; + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + // console.log(this.PeriodListsNews[index][0].status_id) + // มีวิชาที่จำกัด + if (this.isLimit && this.chooseID.idSub !== null) { + console.log('มีวิชาที่จำกัดแต่มีรอบสอบขยาย'); + if (this.chooseID.idSub !== null) { + const d1 = this.chooseID.startrangedayTest.split('-'); + const d2 = this.chooseID.endrangedayTest.split('-'); + const s1 = this.chooseID.startrangedaySub.split('-'); + const s2 = this.chooseID.endrangedaySub.split('-'); + const c = dateselect.split('-'); + const from = new Date(d1[0], parseInt(d1[1]) - 1, d1[2]); // -1 because months are from 0 to 11 + const to = new Date(d2[0], parseInt(d2[1]) - 1, d2[2]); + const fromsub = new Date(s1[0], parseInt(s1[1]) - 1, s1[2]); // -1 because months are from 0 to 11 + const tosub = new Date(s2[0], parseInt(s2[1]) - 1, s2[2]); + const check = new Date(c[0], parseInt(c[1]) - 1, c[2]); + console.log(check > from && check < to); + console.log(check > fromsub && check < tosub); + // ไม่อยู่ในช่วงขยาย + if (check >= from && check <= to) { + console.log(check >= from && check <= to); + } else if (check >= fromsub && check <= tosub) { + console.log(check >= fromsub && check <= tosub); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === false; + }); + } + ); + + this.testinginformationSV.get(this.chooseID.idSub).pipe( + tap(x => { + Formarray.at(index).get('is_main').setValue(false); + Formarray.at(index).get('branch_uid').setValue(null); + Formarray.at(index).get('testing_field_uid').setValue(null); + }), + tap(x => { + const Testinfordata: any = x; + // this.TestcenterLists[index] = Testinfordata.testing_rooms + this.TestcenterLists[index] = Testinfordata.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []) + this.TestFieldLists[index] = Testinfordata.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []) + this.cdr.detectChanges() + + }) + ).subscribe(); + this.form.get('testing_information_uid').setValue(this.chooseID.idSub); + this.cdr.detectChanges(); + } + } + if (this.isLimit) { + const filteredList = this.PeriodLists.filter(item1 => + !!this.isLimitData[0].period.find(item2 => item1.period_id === item2) + ); + this.PeriodListsNews[index] = filteredList; + } + + + } else if (!this.isLimit && this.chooseID.idSub !== null) { + console.log('ไม่มีวิชาที่จำกัดแต่มีรอบสอบขยาย'); + if (this.chooseID.idSub !== null) { + const d1 = this.chooseID.startrangedayTest.split('-'); + const d2 = this.chooseID.endrangedayTest.split('-'); + const s1 = this.chooseID.startrangedaySub.split('-'); + const s2 = this.chooseID.endrangedaySub.split('-'); + const c = dateselect.split('-'); + const from = new Date(d1[0], parseInt(d1[1]) - 1, d1[2]); // -1 because months are from 0 to 11 + const to = new Date(d2[0], parseInt(d2[1]) - 1, d2[2]); + const fromsub = new Date(s1[0], parseInt(s1[1]) - 1, s1[2]); // -1 because months are from 0 to 11 + const tosub = new Date(s2[0], parseInt(s2[1]) - 1, s2[2]); + const check = new Date(c[0], parseInt(c[1]) - 1, c[2]); + console.log(check > from && check < to); + console.log(check > fromsub && check < tosub); + // ไม่อยู่ในช่วงขยาย + if (check >= from && check <= to) { + console.log(check >= from && check <= to); + } else if (check >= fromsub && check <= tosub) { + console.log(check >= fromsub && check <= tosub); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === false; + }); + } + ); + this.testinginformationSV.get(this.chooseID.idSub).pipe( + tap(x => { + Formarray.at(index).get('is_main').setValue(false); + Formarray.at(index).get('branch_uid').setValue(null); + Formarray.at(index).get('testing_field_uid').setValue(null); + }), + tap(x => { + const Testinfordata: any = x; + // this.TestcenterLists[index] = Testinfordata.testing_rooms + this.TestcenterLists[index] = Testinfordata.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []) + this.TestFieldLists[index] = Testinfordata.testing_rooms.reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []) + this.cdr.detectChanges() + + }) + ).subscribe() + this.form.get('testing_information_uid').setValue(this.chooseID.idSub); + this.cdr.detectChanges() + } + } + console.log(this.isLimitData[0]); + if (this.isLimit) { + const filteredList = this.PeriodLists.filter(item1 => + !!this.isLimitData[0].period.find(item2 => item1.period_id === item2) + ); + this.PeriodListsNews[index] = filteredList; + } + this.cdr.detectChanges() + } else if (this.isLimit && !this.chooseID.idSub !== null) { + console.log('มีวิชาที่จำกัดและไม่มีรอบสอบขยาย'); + const ArrayindexNotFound = []; + const filteredList = this.PeriodLists.filter(item1 => + !!this.isLimitData[0].period.find(item2 => item1.period_id === item2) + ); + this.PeriodListsNews[index] = filteredList; + this.cdr.detectChanges() + } + } + + async newChooseDate(date, index) { + if (this.form.get('testing_information_uid').value != null) { + console.log(date, index); + + const Form = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + console.log(Formarray2) + console.log(Formarray2.get('subject_uid').value); + if (Formarray2.get('testing_datetime').value != null && Formarray2.get('period_id').value != null) { + Formarray2.get('period_id').setValue(null); + } + const subjectcode = Formarray2.get('subject_code').value; + this.isLimitData = null; + const isDateSelect = this.formatDate(date); + await this.checkIsLimit(isDateSelect, index).subscribe( + res => { + this.isLimitData = res + // let isFoundSubject = false; + // isFoundSubject = this.isLimitData.some((member) => { + // return member.subject_code === subjectcode; + // }) + // console.log(isFoundSubject) + this.compareIsLimitandIsChoose(index, isDateSelect) + } + ); + // await this.compareIsLimitandIsChoose() + } + + + } + + chooseidDate(data, index) { + const Form = this.form.getRawValue(); + const Formarray = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = Formarray.at(index) as FormGroup; + const SubjectCode = Formarray2.get('subject_code').value; + const FormarraySelect = Formarray2.getRawValue(); + console.log(FormarraySelect); + console.log(data); + const testInforUid = Form.testing_information_uid; + data = this.formatDate(data); + // this.queryForChecklimit.testing_date = data + // this.queryForChecklimit.testing_information_uid = testInforUid + // const query = this.createQueryStringFromObject(this.queryForChecklimit) + const queryPeriodLimitFound: any = []; + // this.testingsubjectadddateSV.FindLimitPeriod(testInforUid, data).pipe( + // tap(x => { + // queryPeriodLimitFound = x; + // console.log(x); + // if (queryPeriodLimitFound.length !== 0){ + // isLimit = true; + // } + // }) + // ).subscribe(); + const dateSubjectadd = this.testingsubjectadddateSV.FindLimitPeriod(testInforUid, data, SubjectCode).toPromise(); + console.log(dateSubjectadd); + console.log(queryPeriodLimitFound); + + // ตรวจสอบวันที่ว่าอยู่ในรอบขยายหรือเปล่า + if (this.chooseID.idSub !== null) { + const d1 = this.chooseID.startrangedayTest.split('-'); + const d2 = this.chooseID.endrangedayTest.split('-'); + const s1 = this.chooseID.startrangedaySub.split('-'); + const s2 = this.chooseID.endrangedaySub.split('-'); + const c = data.split('-'); + const from = new Date(d1[0], parseInt(d1[1]) - 1, d1[2]); // -1 because months are from 0 to 11 + const to = new Date(d2[0], parseInt(d2[1]) - 1, d2[2]); + const fromsub = new Date(s1[0], parseInt(s1[1]) - 1, s1[2]); // -1 because months are from 0 to 11 + const tosub = new Date(s2[0], parseInt(s2[1]) - 1, s2[2]); + const check = new Date(c[0], parseInt(c[1]) - 1, c[2]); + console.log(check > from && check < to); + console.log(check > fromsub && check < tosub); + // ไม่อยู่ในช่วงขยาย + if (check >= from && check <= to) { + console.log(check >= from && check <= to); + // this.form.get('testing_information_uid').setValue(this.chooseID.idTest); + // this.testinginformationSV.getAll().subscribe( + // result => { + // this.TestingInformationLists = result; + // this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + // return x.is_main === true; + // }); + // } + // ); + // อยู่ในช่วงขยาย + } else if (check >= fromsub && check <= tosub) { + console.log(check >= fromsub && check <= tosub); + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === false; + }); + } + ); + this.form.get('testing_information_uid').setValue(this.chooseID.idSub); + } + } + if (FormarraySelect.period_id != null) { + Formarray2.get('period_id').setValue(null); + } + } + + chcekPeriodLimit(date, testingInforUid, SubjectUid) { + this.queryForChecklimit.testing_date = date; + this.queryForChecklimit.testing_information_uid = testingInforUid; + this.queryForChecklimit.subject_uid = SubjectUid; + const query = this.createQueryStringFromObject(this.queryForChecklimit); + this.testingsubjectadddateSV.search(`?${query}`).pipe( + tap(x => { + console.log(x); + }) + ).subscribe(); + } + + openPreview(id: any): void { + // let obj = this.buffer2 + console.log(id); + const dialogRef = this.dialog.open(PreviewImageComponent, { + panelClass: 'custom-dialog-container', + width: '70%', + height: '70%', + data: id + + }); + + } + + onFileChanged(event, photoChoose) { + const file = event.target.files[0]; + if (photoChoose === 1) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + const formData: FormData = new FormData(); + formData.append('filecard', this.selectfile, this.selectfile.name); + this.uploadSV.add(formData).pipe( + tap((x: any) => this.form.get('photo1_url').setValue(x[0].file_name)), + tap((x: any) => this.imageSrc1 = x[0].file_name), + tap((x: any) => this.form.get('photo1_name').setValue(x[0].name)), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + } else if (photoChoose === 2) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + const formData: FormData = new FormData(); + formData.append('fileConfirm', this.selectfile, this.selectfile.name); + this.uploadSV.add(formData).pipe( + tap((x: any) => this.form.get('photo2_url').setValue(x[0].file_name)), + tap((x: any) => this.imageSrc2 = x[0].file_name), + tap((x: any) => this.form.get('photo2_name').setValue(x[0].name)), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + } + } + + DeleteImage(photoChoose) { + if (photoChoose === 1) { + this.form.get('photo1_url').setValue(null) + this.imageSrc1 = null; + this.form.get('photo1_name').setValue(null) + } else if (photoChoose === 2) { + this.form.get('photo2_url').setValue(null) + this.imageSrc2 = null; + this.form.get('photo2_name').setValue(null) + } + } + + onUpload() { + // upload code goes here + } + + clearChooseID() { + this.chooseID = { + idTest: null, + startrangedayTest: null, + endrangedayTest: null, + isLimit: null, + idSub: null, + startrangedaySub: null, + endrangedaySub: null, + }; + } + + setInformation(data) { + this.clearChooseID(); + let search = ''; + if (data === '6dff8faf-0b30-4fb1-8274-42df8debe8a0') { + search = 'นักศึกษา'; + } else if (data === 'd056ba6d-5a15-4df6-ade0-c9e8c239d1b1') { + search = 'บุคคลทั่วไป'; + } else if (data === '5fc44678-8f36-41f6-b0e5-0901ea2231b4') { + search = 'นักศึกษาโครงการพิเศษ'; + } + this.candidateTypeName.emit(search); + // const Detail = this.userData.details; + // this.confirm('reset'); + this.testinginformationSV.querytypeofexamineeUid(data).subscribe( + res => { + this.TestingInformationLists = res; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === true; + }); + // if (Detail.length != 0){ + // this.TestingInformationLists = this.TestingInformationLists.filter((el) => { + // return Detail.some((f) => { + // return f.testing_information_uid === el.testing_information_uid; + // }); + // }); + // } + this.form.get('check_student_code').reset(); + this.form.get('testing_information_uid').reset(); + this.form.get('photo1_name').reset(); + this.form.get('photo2_name').reset(); + this.form.get('student_code').reset(); + this.form.get('examinee_full_name').reset(); + this.form.get('faculty_uid').reset(); + this.form.get('department_name').reset(); + this.form.get('agency_name').reset(); + this.form.get('examinee_mobile').reset(); + this.form.get('agency_name').reset(); + const form = this.form.get('testing_subject_selecteds') as FormArray; + this.imageSrc1 = null; + this.imageSrc2 = null; + form.clear(); + form.push(this.testing_subject_selecteds()); + this.cdr.detectChanges(); + } + ); + } + + filterSubject(subjectId, index) { + const form = this.form.get('testing_subject_selecteds') as FormArray; + const Formarray2 = form.at(index) as FormGroup; + this.subjectSV.get(subjectId).pipe( + tap(x => { + const data: any = x; + Formarray2.get('subject_code').setValue(data.subject_code); + }) + ).subscribe(); + const subjectUidArray = []; + for (let i = 0; i < form.getRawValue().length; i++) { + if (form.at(i).get('subject_uid').value != null) { + subjectUidArray.push(form.at(i).get('subject_uid').value) + } + } + if (subjectUidArray.length !== 0) { + let NewSubjectLists = this.SubjectLists.map((x) => { + x.status_id = true + return x + }); + console.log(NewSubjectLists); + for (let i = 0; i < subjectUidArray.length; i++) { + NewSubjectLists = this.SubjectLists.map((x) => { + if (x.subject_uid === subjectUidArray[i]) + x.status_id = false + return x + }); + } + this.SubjectLists = NewSubjectLists; + } + + // const filteredList = this.SubjectLists + // .filter((x) => { + // return !!subjectUidArray.find(y => x.subject_uid === y) + // }).map((x) => { + // console.log(x) + // x.status_id = false; + // return x + // } + // ); + // console.log(filteredList); + + // Formarray2.get('subject_code') = + // cost subjectSelect = + + // const foundIndex = this.SubjectLists.findIndex(x => x.subject_uid === subjectId); + // this.SubjectLists[foundIndex].status_id = false; + } + + checkStudent() { + const testInforUID = this.form.get('testing_information_uid').value; + const studentCode = this.form.get('check_student_code').value; + if (studentCode !== null) { + this.testinginformationSV.get(this.TestInformationID).pipe( + tap(x => console.log(x)), + tap((x: any) => this.SubjectLists = x.testing_subjects), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe( + result => { + this.studentSV.checkStudentCode(studentCode, testInforUID).pipe( + tap((x: any) => this.AfterFoundcheckStudent(x)), + tap((x: any) => this.swSV.success('พบข้อมูล')), + catchError(err => { + this.swSV.errText('ไม่พบข้อมูล'); + return throwError(err); + }) + ).subscribe(); + } + ); + } else { + return this.swSV.errText('กรุณาใส่รหัสนักศึกษา'); + } + } + + AfterFoundcheckStudent(data) { + this.form.get('student_code').setValue(data.student_code); + this.form.get('examinee_full_name').setValue(data.student_name_th); + this.SubjectLists = this.SubjectLists.filter((el) => { + return data.subjects.some((f) => { + return f.subject_code === el.subject_code; + }); + }); + this.SubjectLists = this.SubjectLists + .map((x) => { + x.status_id = true; + return x; + }); + this.cdr.detectChanges(); + + } + + openDialogCheckPayment() { + const dialog = this.dialog.open(DialogEnrollmentCounterPaymentComponent, { + width: '50%', + data: { + data: this.userData, + } + }); + } + + openDialogCheckReprint() { + const dialog = this.dialog.open(DialogCheckPaymentCounterComponent, { + width: '50%', + data: { + data: this.userData, + } + }); + } + + + formatDate(date) { + let d = new Date(date), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); + + if (month.length < 2) { + month = '0' + month; + } + if (day.length < 2) { + day = '0' + day; + } + + return [year, month, day].join('-'); + } + + createQueryStringFromObject(object: any) { + let queryStr = ''; + + for (const key in object) { + if (object[key]) { + queryStr += `${key}=${object[key]}&`; + } + } + const lastIndex = queryStr.lastIndexOf('&'); + queryStr = queryStr.slice(0, lastIndex); + return queryStr; + } + + findInvalidControls() { + const invalid = []; + const controls = this.form.controls; + for (const name in controls) { + if (controls[name].invalid) { + invalid.push(name); + } + } + console.log(invalid) + return invalid; + } + + filterTestingFiled(data, index) { + const formArray = this.form.get('testing_subject_selecteds') as FormArray; + formArray.at(index).get('testing_field_uid').setValue(null); + if (formArray.at(index).get('testing_datetime').value != null) { + if (this.chooseID.idSub != null) { + const dateselect = formArray.at(index).get('testing_datetime').value; + const s1 = this.chooseID.startrangedaySub.split('-'); + const s2 = this.chooseID.endrangedaySub.split('-'); + const c = dateselect.split('-'); + const fromsub = new Date(s1[0], parseInt(s1[1]) - 1, s1[2]); // -1 because months are from 0 to 11 + const tosub = new Date(s2[0], parseInt(s2[1]) - 1, s2[2]); + const check = new Date(c[0], parseInt(c[1]) - 1, c[2]); + // อยู่ในช่วง + if (check >= fromsub && check <= tosub) { + this.testinginformationSV.get(this.chooseID.idTest).pipe( + tap(x => { + const Testinfordata: any = x; + this.TestFieldLists[index] = Testinfordata.testing_rooms + .filter((member) => member.branch_uid === data) + .reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []); + this.cdr.detectChanges() + + }) + ).subscribe(); + } else { + this.testinginformationSV.get(this.chooseID.idSub).pipe( + tap(x => { + const Testinfordata: any = x; + this.TestFieldLists[index] = Testinfordata.testing_rooms + .filter((member) => member.branch_uid === data) + .reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []); + console.log(this.TestFieldLists[index]); + this.cdr.detectChanges(); + + }) + ).subscribe(); + } + + + } + + } else { + this.testinginformationSV.get(this.chooseID.idTest).pipe( + tap(x => { + const Testinfordata: any = x; + this.TestFieldLists[index] = Testinfordata.testing_rooms + .filter((member) => member.branch_uid === data) + .reduce((unique, o) => { + if (!unique.some(obj => obj.branch_uid === o.branch_uid)) { + unique.push(o); + } + return unique; + }, []); + this.cdr.detectChanges() + + }) + ).subscribe(); + } + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.html b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.html new file mode 100644 index 0000000..1c1b163 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.html @@ -0,0 +1,4 @@ +
+ +
diff --git a/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.scss b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.scss new file mode 100644 index 0000000..1382d34 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.scss @@ -0,0 +1,4 @@ +pdf-viewer { + display: block; + height: 100vh; +} diff --git a/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.spec.ts new file mode 100644 index 0000000..82573ae --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PreviewImageComponent } from './preview-image.component'; + +describe('PreviewImageComponent', () => { + let component: PreviewImageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PreviewImageComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PreviewImageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.ts b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.ts new file mode 100644 index 0000000..54253b3 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/preview/preview-image/preview-image.component.ts @@ -0,0 +1,41 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Inject} from '@angular/core'; +import {BaseForm} from "../../../../../../core/base/base-form"; +import {FormBuilder} from "@angular/forms"; +import {ActivatedRoute, Router} from "@angular/router"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {Location} from "@angular/common"; + +@Component({ + selector: 'app-preview-image', + templateUrl: './preview-image.component.html', + styleUrls: ['./preview-image.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PreviewImageComponent extends BaseForm implements OnInit { + + constructor( + public activeRoute:ActivatedRoute, + public fb: FormBuilder, + public location: Location, + public router:Router, + private cdRef: ChangeDetectorRef, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + super( + router, + activeRoute, + fb, + location, + ); + } + + ngOnInit(): void { + // console.log(this.data) + } + + onNoClick(): void { + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.html b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.html new file mode 100644 index 0000000..c6fecfc --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.html @@ -0,0 +1,22 @@ +

ลงทะเบียนสอบ

+
+
+
+ + + +
+
+
+ +
+
+
+
+ + + +
+
+
+
diff --git a/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.scss b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.spec.ts new file mode 100644 index 0000000..bb73879 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterSummarySearchComponent } from './register-summary-search.component'; + +describe('RegisterSummarySearchComponent', () => { + let component: RegisterSummarySearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterSummarySearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterSummarySearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.ts b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.ts new file mode 100644 index 0000000..7fdbdcc --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/search/register-summary-search/register-summary-search.component.ts @@ -0,0 +1,25 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-register-summary-search', + templateUrl: './register-summary-search.component.html', + styleUrls: ['./register-summary-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterSummarySearchComponent implements OnInit { + @Output() search = new EventEmitter(); + query = { + student_code: null + }; + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + // let query = createQueryStringFromObject(this.query); + this.search.emit(this.query.student_code); + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.html b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.html new file mode 100644 index 0000000..e6075fe --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.html @@ -0,0 +1,61 @@ +
+ +
+
+ {{CandidateTypeName}} +
+
+ โปรดระบุ ประเภทผู้สอบ +
+
+ +
+
+
+
+ + + + +

+ +
+ +
+
+
+ + + +

+ + +
+
+
+
+ + + + +

+ +
+
+
+
+
diff --git a/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.scss b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.scss new file mode 100644 index 0000000..2e0039a --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.scss @@ -0,0 +1,11 @@ +.fontsummary{ + font-size: 30px; + font-max-size: 30px; + font-min-size: 20px; + color: #529F6E; +} +.fontHeadsummary{ + font-size: 30px; + font-max-size: 30px; + font-min-size: 20px; +} diff --git a/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.spec.ts new file mode 100644 index 0000000..e09d5d1 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RegisterSummarySummaryComponent } from './register-summary-summary.component'; + +describe('RegisterSummarySummaryComponent', () => { + let component: RegisterSummarySummaryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RegisterSummarySummaryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterSummarySummaryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.ts b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.ts new file mode 100644 index 0000000..6c897ce --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/summary/register-summary-summary/register-summary-summary.component.ts @@ -0,0 +1,76 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {TestingRegisterService} from '../../../../../../core/service/testing-register/testing-register.service'; +import {tap} from 'rxjs/operators'; +import {any} from 'codelyzer/util/function'; +import {UserCountersService} from '../../../../../../core/service/permission/user-counters.service'; + +@Component({ + selector: 'app-register-summary-summary', + templateUrl: './register-summary-summary.component.html', + styleUrls: ['./register-summary-summary.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterSummarySummaryComponent extends BaseList implements OnInit , OnChanges { + @Input() userData: any = []; + @Input() CandidateTypeName: any = []; + @Input() registerList: any = []; + @Output() onLogoutcouter = new EventEmitter(); + counterDetail; + listsummary; + totalfee:number = 0 ; + studentcount = 0; + subjectcount = 0; + constructor( + private tesingregisterSV: TestingRegisterService, + private userCounterSV: UserCountersService, + private cdr: ChangeDetectorRef + ) { + super(); + } + + ngOnInit() { + } + + ngOnChanges(){ + console.log(this.userData); + if (this.userData.counter_no != null && this.userData.counter_uid != null){ + this.userCounterSV.getCounterSummary(this.userData.counter_no, this.userData.counter_uid , this.userData.counter_periods[0].period).pipe( + tap(x => this.counterDetail = x), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + + // if (this.registerList != null){ + // this.studentcount = +this.registerList.length; + // for (let i = 0; i < this.registerList.length; i++) { + // const fee: number = +this.registerList[i].testing_fee; + // this.tesingregisterSV.get(this.registerList[i].testing_register_uid).pipe( + // tap(x => { + // const countSub: any = x; + // this.subjectcount += countSub.testing_subject_selecteds.length; + // }), + // tap(x => { + // this.cdr.detectChanges(); + // }), + // ).subscribe( + // ); + // this.totalfee += fee; + // } + // this.cdr.detectChanges(); + // } + } + + updateSummary(){ + this.userCounterSV.getCounterSummary(this.userData.counter_no, this.userData.counter_uid, this.userData.counter_periods[0].period).pipe( + tap(x => this.counterDetail = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + logoutcounter(){ + this.onLogoutcouter.emit(); + } + + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.html b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.html new file mode 100644 index 0000000..d9dce29 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.html @@ -0,0 +1,76 @@ +
+ + + + + + + + + + + + + +
+
+

รายการค่าธรรมเนียม

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i + 1}} รหัสวิชา - ชื่อวิชา {{x.subject_code}} - {{x.subject_name_th}} เวลาสอบ {{x.testing_datetime | thaidate}} ({{x.start_time}}) คาบสอบ {{x.period_id}} ค่าธรรมเนียม {{x.fee}} จำนวน {{x.total_subject}} ค่าใช้จ่าย {{x.total_fee}}
+ +
+
+
+ + + + + + + + +
+
+ + + + + diff --git a/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.scss b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.spec.ts new file mode 100644 index 0000000..3cd133a --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TableSummaryComponent } from './table-summary.component'; + +describe('TableSummaryComponent', () => { + let component: TableSummaryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TableSummaryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TableSummaryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.ts b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.ts new file mode 100644 index 0000000..05320d7 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/table-summary/table-summary/table-summary.component.ts @@ -0,0 +1,86 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {TestingRegisterService} from '../../../../../../core/service/testing-register/testing-register.service'; + +@Component({ + selector: 'app-table-summary', + templateUrl: './table-summary.component.html', + styleUrls: ['./table-summary.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TableSummaryComponent extends BaseList implements OnInit,OnChanges{ + @Input() summaryData: any = []; + @Output() recieveMoney = new EventEmitter(); + @Output() cancel = new EventEmitter(); + @Output() Onprint = new EventEmitter(); + @Output() Onprintreal = new EventEmitter(); + @Output() onNewRegister = new EventEmitter(); + @Input( ) isPrint = false; + @Input( ) isHidebutton = false; + @Input( ) isCancel = false; + @Input( ) isMoney = false; + @Input( ) isPaymentBillChild = false; + + paymentList = []; + column = ['1', '2', '22', '23', '3', '4', '5']; + + constructor( + private cdr: ChangeDetectorRef, + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.summaryData != null) + + if (this.summaryData != null){ + this.paymentList = this.updateMatTable(this.summaryData.fee_details ? this.summaryData.fee_details : []); + console.log(this.paymentList) + this.cdr.detectChanges(); + } + } + + recievemoney(type){ + // this.recieveMoney.emit({summaryData : this.summaryData}); + this.recieveMoney.emit(type); + } + + cancelMoney(){ + this.cancel.emit(); + } + + register(){ + this.summaryData = null; + this.isPrint = false; + this.isMoney = false; + this.isCancel = false; + this.isHidebutton = false; + this.isPaymentBillChild = false; + this.onNewRegister.emit(); + } + + print(){ + // this.recieveMoney.emit({summaryData : this.summaryData}); + // this.Onprint.emit(); + this.Onprintreal.emit(); + } + + changeisPrint(){ + this.isPrint = true; + } + + changeisCancel(){ + this.isPrint = true; + } + + resetFornewRegister(){ + this.isPrint = false; + this.isMoney = false; + this.isCancel = false; + this.isPaymentBillChild = false; + } + +} diff --git a/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.html b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.html new file mode 100644 index 0000000..05f3414 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.html @@ -0,0 +1,18 @@ +
+
+

ล็อคอิน เคาเตอร์

+
+
+
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.scss b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.spec.ts b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.spec.ts new file mode 100644 index 0000000..19cd436 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCounterLoginComponent } from './user-counter-login.component'; + +describe('UserCounterLoginComponent', () => { + let component: UserCounterLoginComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserCounterLoginComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserCounterLoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.ts b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.ts new file mode 100644 index 0000000..468b2c7 --- /dev/null +++ b/src/app/feature/exam-register/register-summary/presenter/user-counter-login/user-counter-login.component.ts @@ -0,0 +1,135 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {MatDialogRef} from '@angular/material/dialog'; +import {UserCounterLoginService} from '../../../../../core/service/permission/user-counter-login.service'; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {formatDate} from "@angular/common"; +import {UserCountersService} from "../../../../../core/service/permission/user-counters.service"; +import {tap} from "rxjs/operators"; + +@Component({ + selector: 'app-user-counter-login', + templateUrl: './user-counter-login.component.html', + styleUrls: ['./user-counter-login.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCounterLoginComponent implements OnInit { + form; + constructor( + private fb: FormBuilder, + private swSV: SweetalertService, + private userCounterSV: UserCountersService, + protected userCouterLoginSV: UserCounterLoginService, + private dialogRef: MatDialogRef, + ) { + this.form = this.fb.group({ + pin: null, + }); + } + + ngOnInit(): void { + } + + login(){ + let datasendBack: any = null; + console.log(this.form.getRawValue()); + this.userCouterLoginSV.checkpin(this.form.get('pin').value).subscribe( + result => { + datasendBack = result; + console.log(datasendBack) + if (datasendBack.counter_periods.length === 0){ + console.log(1) + this.userCounterSV.logout(this.form.get('pin').value).subscribe(); + this.swSV.errText('PIN นี้ไม่อยู่ในช่วงเวลาที่เข้าสู่ระบบได้'); + this.dialogRef.close(); + }else { + const isdayOk = this.checkDate(datasendBack.counter_open_date, datasendBack.counter_close_date); + console.log(datasendBack.counter_periods[0]); + if (isdayOk === false){ + this.userCounterSV.logout(this.form.get('pin').value).subscribe(); + return this.swSV.errText('PIN นี้ไม่อยู่ในช่วงวันที่เข้าสู่ระบบได้'); + }else { + if (datasendBack.counter_periods[0] === null){ + this.userCounterSV.logout(this.form.get('pin').value).subscribe(); + return this.swSV.errText('PIN นี้ไม่อยู่ในช่วงเวลาที่เข้าสู่ระบบได้'); + }else { + const isTimeOk = this.checkTime(datasendBack.counter_periods[0].counter_open_time, datasendBack.counter_periods[0].counter_close_time); + console.log(isTimeOk) + if (isdayOk && isTimeOk){ + console.log(2) + this.dialogRef.close(datasendBack); + }else { + console.log(3) + this.userCounterSV.logout(this.form.get('pin').value).subscribe(); + this.swSV.errText('PIN นี้ไม่อยู่ในช่วงเวลาที่เข้าสู่ระบบได้'); + this.dialogRef.close(); + } + } + } + } + }, + error => { + this.swSV.errTextAndDetail('เกิดข้อผิดพลาด', 'PIN นี้ไม่มีอยู่ในระบบหรือมีการใช้งานอยู่'); + this.dialogRef.close(); + } + ); + } + + checkDate(dateOpen, dateClose){ + console.log(dateOpen) + console.log(dateClose) + const dateDate = new Date(); + + + // const dateFrom: any = formatDate(dateOpen, 'mm/dd/yyyy', 'en-US'); + const dateFrom2: any = formatDate(dateOpen, 'MM-dd-yyyy', 'en-US'); + + // const dateTo: any = formatDate(dateClose, 'mm/dd/yyyy', 'en-US'); + const dateTo2: any = formatDate(dateClose, 'MM-dd-yyyy', 'en-US'); + + + // const dateCheck: any = formatDate(dateDate, 'mm/dd/yyyy', 'en-US'); + // const dateCheck2: any = formatDate(dateDate, 'yyyy-MM-dd', 'en-US'); + const dateCheck2: any = formatDate(dateDate, 'MM-dd-yyyy', 'en-US'); + + + // const d1 = dateFrom.split("/"); + // const d2 = dateTo.split("/"); + // const c = dateCheck.split("/"); + const d1 = dateFrom2.split('-'); + const d2 = dateTo2.split('-'); + const c = dateCheck2.split('-'); + console.log(d1) + console.log(d2) + console.log(c) + // const froms = new Date(d1[2], parseInt(d1[1])-1, d1[0]); // -1 because months are from 0 to 11 + // const to = new Date(d2[2], parseInt(d2[1])-1, d2[0]); + // const check = new Date(c[2], parseInt(c[1])-1, c[0]); + const froms = d1[2]+d1[0]+d1[1]; + const to = d2[2]+d2[0]+d2[1]; + const check = c[2]+c[0]+c[1]; + // console.log(+froms,'from'); + // console.log(+to,'to'); + // console.log(+check,'check'); + // console.log(+check > +froms && +check < +to); + + return check >= froms && check < to; + } + + checkTime(start, end){ + const dateCheck2: any = formatDate(new Date(), 'HH:mm:ss', 'en-US'); + // console.log(Date.parse(`01/01/2011 ${dateCheck2}`),'check') + // console.log(Date.parse(`01/01/2011 ${start}`),'from') + // console.log(Date.parse(`01/01/2011 ${end}`),'to') + const from = Date.parse(`01/01/2011 ${start}`) + const to = Date.parse(`01/01/2011 ${end}`) + const check = Date.parse(`01/01/2011 ${dateCheck2}`) + return check > from && check < to; + + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/exam-register/register-summary/register-summary.module.ts b/src/app/feature/exam-register/register-summary/register-summary.module.ts new file mode 100644 index 0000000..16b933f --- /dev/null +++ b/src/app/feature/exam-register/register-summary/register-summary.module.ts @@ -0,0 +1,52 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RegisterSummaryRouterComponent } from './router/register-summary-router.component'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { RegisterSummaryContainer } from './container/register-summary/register-summary.container'; +import { RegisterSummaryFormComponent } from './presenter/form/register-summary-form/register-summary-form.component'; +import { RegisterSummarySearchComponent } from './presenter/search/register-summary-search/register-summary-search.component'; +import { RegisterSummarySummaryComponent } from './presenter/summary/register-summary-summary/register-summary-summary.component'; +import { UserCounterLoginComponent } from './presenter/user-counter-login/user-counter-login.component'; +import { TableSummaryComponent } from './presenter/table-summary/table-summary/table-summary.component'; +import { PreviewImageComponent } from './presenter/preview/preview-image/preview-image.component'; +import { DialogEnrollmentCounterPaymentComponent } from './presenter/dialog/dialog-enrollment-counter-payment/dialog-enrollment-counter-payment.component'; +import { ListEnrollmentCounterPaymentComponent } from './presenter/dialog/dialog-enrollment-counter-payment/list-enrollment-counter-payment/list-enrollment-counter-payment.component'; +import { DialogCheckPaymentCounterComponent } from './presenter/dialog/dialog-check-payment-counter/dialog-check-payment-counter.component'; +import { ListPaymentCounterComponent } from './presenter/dialog/dialog-check-payment-counter/list-payment-counter/list-payment-counter.component'; + + +const routes: Routes = [ + { + path: '', + component: RegisterSummaryRouterComponent, + children: [ + { + path: '', + component: RegisterSummaryContainer + }, + ] + } +]; +@NgModule({ + declarations: [ + RegisterSummaryRouterComponent, + RegisterSummaryContainer, + RegisterSummaryFormComponent, + RegisterSummarySearchComponent, + RegisterSummarySummaryComponent, + UserCounterLoginComponent, + TableSummaryComponent, + PreviewImageComponent, + DialogEnrollmentCounterPaymentComponent, + ListEnrollmentCounterPaymentComponent, + DialogCheckPaymentCounterComponent, + ListPaymentCounterComponent, + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class RegisterSummaryModule { } diff --git a/src/app/feature/exam-register/register-summary/router/register-summary-router.component.ts b/src/app/feature/exam-register/register-summary/router/register-summary-router.component.ts new file mode 100644 index 0000000..3f644bc --- /dev/null +++ b/src/app/feature/exam-register/register-summary/router/register-summary-router.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-register-summary-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RegisterSummaryRouterComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-register/routes.ts b/src/app/feature/exam-register/routes.ts new file mode 100644 index 0000000..916f948 --- /dev/null +++ b/src/app/feature/exam-register/routes.ts @@ -0,0 +1,59 @@ +import { Routes } from "@angular/router"; +export const examRegisterRoutes: Routes = [ + { + path: "receive-payment", + loadChildren: () => + import("./receive-payment/receive-payment.module").then( + (m) => m.ReceivePaymentModule + ), + data: { + menu: "ลงทะเบียนสอบ", + sub_menu: "รับชำระเงิน", + }, + }, + { + path: "register-summary", + loadChildren: () => + import("./register-summary/register-summary.module").then( + (m) => m.RegisterSummaryModule + ), + data: { + menu: "ลงทะเบียนสอบ", + sub_menu: "ลงทะเบียนสอบ", + }, + }, + { + path: "period-summary", + loadChildren: () => + import("./period-summary/period-summary.module").then( + (m) => m.PeriodSummaryModule + ), + data: { + menu: "ลงทะเบียนสอบ", + sub_menu: "สรุปยอดประจำคาบ", + }, + }, + { + path: "daily-summary", + loadChildren: () => + import("./daily-summary/daily-summary.module").then( + (m) => m.DailySummaryModule + ), + data: { + menu: "ลงทะเบียนสอบ", + sub_menu: "รายงานรับเงิน", + }, + }, + { + path: "manage-receipt", + loadChildren: () => + import("./manage-receipt/manage-receipt.module").then( + (m) => m.ManageReceiptModule + ), + data: { + menu: "ลงทะเบียนสอบ", + sub_menu: "จัดการใบเสร็จ", + }, + }, +]; +export default examRegisterRoutes; diff --git a/src/app/feature/exam-setting/change-exam-information/change-exam-information.module.ts b/src/app/feature/exam-setting/change-exam-information/change-exam-information.module.ts new file mode 100644 index 0000000..f4e237a --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/change-exam-information.module.ts @@ -0,0 +1,56 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ChangeExamInformationRouter } from './router/change-exam-information-router'; +import {RouterModule, Routes} from '@angular/router'; +import { ChangeExamInformationContainer } from './container/change-exam-information/change-exam-information.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {MatTabsModule} from '@angular/material/tabs'; +import { ChangeExamInformationListComponent } from './presenter/list/change-exam-information-list/change-exam-information-list.component'; +import { ChangeExamInformationFormComponent } from './presenter/form/change-exam-information-form/change-exam-information-form.component'; +import { ChangeExamInformationSearchComponent } from './presenter/search/change-exam-information-search/change-exam-information-search.component'; +import { IsMainTrueComponent } from './presenter/list/is-main-true/is-main-true.component'; +import { IsMainFalseComponent } from './presenter/list/is-main-false/is-main-false.component'; + +const routes: Routes = [ + { + path: '', + component: ChangeExamInformationRouter, + children: [ + { + path: '', + component: ChangeExamInformationContainer + }, + { + path: 'edit/:id', + component: ChangeExamInformationFormComponent + }, + { + path: 'info/:id', + component: ChangeExamInformationFormComponent + }, + { + path: 'expand/:id', + component: ChangeExamInformationFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + ChangeExamInformationRouter, + ChangeExamInformationContainer, + ChangeExamInformationListComponent, + ChangeExamInformationFormComponent, + ChangeExamInformationSearchComponent, + IsMainTrueComponent, + IsMainFalseComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatTabsModule + ] +}) +export class ChangeExamInformationModule { } diff --git a/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.html b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.html new file mode 100644 index 0000000..6543b00 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.html @@ -0,0 +1,15 @@ + + + + diff --git a/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.scss b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.spec.ts b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.spec.ts new file mode 100644 index 0000000..65a8699 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamInformationContainer } from './change-exam-information.container'; + +describe('ChangeExamInformationContainer', () => { + let component: ChangeExamInformationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamInformationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamInformationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.ts b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.ts new file mode 100644 index 0000000..334c34e --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/container/change-exam-information/change-exam-information.container.ts @@ -0,0 +1,73 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {concatMap, filter, tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-change-exam-information', + templateUrl: './change-exam-information.container.html', + styleUrls: ['./change-exam-information.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamInformationContainer implements OnInit { + Tab = 0; + subjectList$ = new Observable(); + subjectListFalse$ = new Observable(); + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrue(); + this.subjectListFalse$ = this.TestinforSV.getMainfalse(); + } + + add(){ + this.router.navigate(['change-exam-information/add']); + } + + edit(id){ + this.router.navigate(['change-exam-information/edit', id]); + } + + info(id){ + this.router.navigate(['change-exam-information/info', id]); + } + + expand(id){ + this.router.navigate(['change-exam-information/expand', id]); + } + + search(query){ + if (this.Tab != 1){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}&is_main=true`); + if(!query) return this.subjectList$ = this.TestinforSV.getMaintrue(); + }else { + if(query) return this.subjectListFalse$ = this.TestinforSV.search(`?${query}&is_main=false`); + if(!query) return this.subjectListFalse$ = this.TestinforSV.getMainfalse(); + } + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getMaintrue()), + tap(x => this.subjectListFalse$ = this.TestinforSV.getMainfalse()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + tab(index){ + this.Tab = index.index; + } +} diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.html b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.html new file mode 100644 index 0000000..8b635c2 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.html @@ -0,0 +1,321 @@ +

จัดการวันกำหนดสอบของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+ +
+ + +
+
+
+ +
+
+ + +
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+ + +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+ +
+
+ + + + + + +
+
+
+
+ +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+ +
+
+
+
+ +
+
+ + + + + + +
+
+
+
+
+ +
+
+
+ + + + + --กรุณาเลือก-- + + + {{subject.branch_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject2.testing_field_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{subject3.testing_room_name_th}} + + +
+ +
+ +
+
+ + +
+
+
+ +
+
+
+
+ +

แสดงรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{element.branch_name_th}} สนามสอบ {{element.testing_field_name_th}} ห้องสอบ {{element.testing_room_name_th}} ผู้คุมสอบ {{element.testing_auth_name}} สุ่มที่นั่งสอบ + + + จัดการที่นั่งสอบ* + + +
+ +
+
ไม่มีข้อมูล
+
+
+
+
+ +
+ + +
+
{{setexamform.getRawValue() | json}}
diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.scss b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.spec.ts b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.spec.ts new file mode 100644 index 0000000..c3b5bf4 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamInformationFormComponent } from './change-exam-information-form.component'; + +describe('ChangeExamInformationFormComponent', () => { + let component: ChangeExamInformationFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamInformationFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamInformationFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.ts b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.ts new file mode 100644 index 0000000..458aa75 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/form/change-exam-information-form/change-exam-information-form.component.ts @@ -0,0 +1,743 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import { formatDate } from '@angular/common'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {FormArray, FormBuilder} from '@angular/forms'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {tap} from 'rxjs/operators'; +import {MatTableDataSource} from '@angular/material/table'; +import {SetExamInformationDialogComponent} from '../../../../../set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import {SelectionModel} from '@angular/cdk/collections'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {CandidateTypeService} from '../../../../../../core/service/enrollment-api/candidate-type.service'; + +@Component({ + selector: 'app-change-exam-information-form', + templateUrl: './change-exam-information-form.component.html', + styleUrls: ['./change-exam-information-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamInformationFormComponent extends BaseForm implements OnInit { + selection = new SelectionModel(true, []); + isInfo = false; + dateBeforestartRegister; + dateBeforestartTesting; + subjectselectList; + setexamform; + setroomcenterForm; + testingInfoData; + eductionTypeList: any = []; + academicYearList: any = []; + calendarLists: any = []; + EducationTypeLists: any = []; + academicSemList: any = []; + subjectList: any = []; + subjectList2: any = []; + subjectList3: any = []; + dataSource3 = new MatTableDataSource(); + displayedColumns3: string[] = ['1', '2', '3', '4', '5', '6', '7']; + candidateTypes: any = []; + setupdata = { + testing_center_uid: null, + testing_center_name_th: null, + testing_room_name_th: null, + testing_auth_name: null, + testing_field_name_th: null, + branch_name_th: null, + branch_uid: null, + testing_field_uid: null, + testing_room_uid: null, + }; + public model = [ + ]; + constructor( + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + private CandidateTypeSV: CandidateTypeService, + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: null, + testing_information_code: null, + academic_semester_code: null, + academic_year_code: null, + testing_information_status: null, + type_of_examinee: null, + is_student_code: true, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_main: false, + main_testing_information_uid: null, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars() + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.setroomcenterForm = this.formBuilder.group({ + branch_name_th: null, + branch_uid: null, + testing_center_id: null, + testing_field_name_th: null, + testing_field_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + is_random_seat: null, + }); + } + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + return this.formBuilder.group({ + testing_subject_uid: data?.testing_subject_uid, + status_id: null, + subject_uid: data?.subject_uid, + amount: data?.amount, + testing_information_uid: data?.testing_information_uid, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + + this.EductiontionTypeSV.getAll().subscribe( + result => { + this.eductionTypeList = result; + } + ); + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + this.CandidateTypeSV.getAll().subscribe( + result => { + this.candidateTypes = result; + } + ); + this.branchSV.getAll().pipe( + tap(x => this.subjectList = x), + ).subscribe(); + this.testFiledSV.getAll().pipe( + tap(x => this.subjectList2 = x), + ).subscribe(); + this.testcenterSV.getAll().pipe( + tap(x => this.subjectList3 = x), + ).subscribe(); + switch (this.state) { + case 'edit': + this.activeRoute.url.subscribe(params => { + console.log(params[0].path); + if (params[0].path === 'info'){ + this.isInfo = true + } + }); + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + // tap(x => this.add3Edit(x)), + tap(x => { + const subjectList: any = x; + this.subjectselectList = subjectList.testing_subjects; + }), + tap(x => { + form.clear(); + // form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + // tap(x => this.setexamform.patchValue(x)), + tap(x => { + const data: any = x; + data.registration_start_datetime = this.formatDate(data.registration_start_datetime); + data.registration_end_datetime = this.formatDate(data.registration_end_datetime); + this.dateBeforestartRegister = data.registration_end_datetime; + data.testing_start_datetime = this.formatDate(data.testing_start_datetime); + data.testing_end_datetime = this.formatDate(data.testing_end_datetime); + this.dateBeforestartTesting = data.testing_end_datetime; + this.setexamform.patchValue(data); + }), + tap(x => { + const testInfo: any = x; + if (testInfo.main_testing_information_uid != null){ + this.add3Edit(x); + } + }), + tap(x => this.selectValueEdit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + case 'add': + break; + case 'expand': + this.TestInformationSV.get(this.id).pipe( + // tap(x => this.add3Edit(x)), + tap(x => { + const subjectList: any = x; + this.subjectselectList = subjectList.testing_subjects; + }), + tap(x => { + // form.clear(); + // form2.clear(); + form3.clear(); + }), + // tap(x => this.setexamform.patchValue(x)), + tap(x => { + const data: any = x; + data.registration_start_datetime = this.formatDate(data.registration_start_datetime); + data.registration_end_datetime = this.formatDate(data.registration_end_datetime); + this.dateBeforestartRegister = data.registration_end_datetime; + data.testing_start_datetime = this.formatDate(data.testing_start_datetime); + data.testing_end_datetime = this.formatDate(data.testing_end_datetime); + this.dateBeforestartTesting = data.testing_end_datetime; + this.setexamform.patchValue(data); + }), + // tap(x => this.addCalendaEdit(x)), + tap(x => { + const testInfo: any = x; + if (testInfo.main_testing_information_uid != null){ + this.add3Edit(x); + } + }), + // tap(x => this.add3Edit(x)), + tap(x => this.selectValueEdit(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + } + } + + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = this.formatDate(x.testing_calendars[i].start_datetime); + x.testing_calendars[i].start_datetime = this.formatDate( x.testing_calendars[i].start_datetime); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + // this.cdRef.detectChanges(); + } + + addPeriodEdit(x){ + console.log(x.testing_periods); + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + form.push(this.testing_periods(x.testing_periods[i])); + } + } + + selectValueEdit(x){ + // this.selection.clear() + // this.dataSource2.data.forEach(x => this.selection.select(x.testing_subjects[0])); + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + subjectForm.clear(); + for (let i = 0; i < x.testing_subjects.length ; i++) { + this.selection.selected.push(x.testing_subjects[i]); + subjectForm.push(this.testing_subjects(x.testing_subjects[i])); + // this.selection.select(x.testing_subjects[i]); + } + // this.selection.clear() : + // this.dataSource2.data.forEach(row => this.selection.select(row)); + console.log(this.selection.selected); + this.cdRef.detectChanges(); + } + + save(){ + const form = this.setexamform.getRawValue(); + this.setexamform.get('testing_information_uid').setValue(null); + this.setexamform.get('is_main').setValue(false); + this.setexamform.get('main_testing_information_uid').setValue(form.testing_information_uid); + const datestartRegister = this.Increasedate(this.dateBeforestartRegister); + const datestartTesting = this.Increasedate(this.dateBeforestartTesting); + this.setexamform.get('registration_start_datetime').setValue(datestartRegister); + this.setexamform.get('testing_start_datetime').setValue(datestartTesting); + // console.log(this.setexamform.getRawValue()); + this.TestInformationSV.add(this.setexamform.getRawValue()).pipe( + tap(x => this.swSV.updateSuccess()), + ).subscribe(); + } + + formatDate(date) { + let d = new Date(date), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); + + if (month.length < 2) { + month = '0' + month; + } + if (day.length < 2) { + day = '0' + day; + } + + return [year, month, day].join('-'); + } + + setFormtestcentername(testcenterData, choose){ + console.log(testcenterData); + console.log(choose); + if (choose === 'branch_name_th'){ + this.setupdata.branch_name_th = testcenterData.branch_name_th; + this.setupdata.branch_uid = testcenterData.branch_uid; + this.testFiledSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe( + result => { + this.subjectList2 = this.subjectList2.filter((x) => { + return x.branch_uid === testcenterData.branch_uid; + }); + } + ); + // array.push(testcenterData); + // this.subjectList3 = array; + } + if (choose === 'testing_field_name_th'){ + this.setroomcenterForm.get('testing_room_name_th').reset(); + this.setupdata.testing_field_name_th = testcenterData.testing_field_name_th; + this.setupdata.testing_field_uid = testcenterData.testing_field_uid; + this.testcenterSV.getAll().pipe( + tap(x => console.log(x)), + tap(x => this.subjectList3 = x), + ).subscribe( + result => { + this.subjectList3 = this.subjectList3.filter((x) => { + return x.testing_field_uid === testcenterData.testing_field_uid; + }); + } + ); + } + if (choose === 'testing_room_name_th'){ + this.setupdata.testing_room_name_th = testcenterData.testing_room_name_th; + this.setupdata.testing_room_uid = testcenterData.testing_center_uid; + this.setupdata.testing_center_uid = testcenterData.testing_center_uid; + } + } + + add3(){ + const form = this.setroomcenterForm.getRawValue(); + const form3 = this.setexamform.get('testing_rooms') as FormArray; + this.setupdata.testing_auth_name = form.testing_auth_name; + form3.push(this.testing_rooms(this.setupdata)); + const table = form3.getRawValue(); + this.dataSource3.data = table; + } + add3Edit(data){ + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[0])); + } + } + const table = form.getRawValue(); + console.log(table); + this.dataSource3.data = table; + } + removeArray3(i){ + const form = this.setexamform.get('testing_rooms') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + selectionValue(data, i){ + switch (this.state) { + case 'edit': + let israndom = true; + if (data.is_random_seat === true){ + israndom = false; + }else if (data.is_random_seat === false){ + israndom = true; + } + const form = this.setexamform.get('testing_rooms') as FormArray; + form.at(i).get('is_random_seat').setValue(israndom); + const table = form.getRawValue(); + this.dataSource3.data = table; + break; + case 'add': + break; + } + console.log(i); + console.log(data); + } + + openDialogexam(id: any, index: any){ + const form = this.setexamform.get('testing_rooms') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form2raw = form2.getRawValue(); + const centerList: any = form.getRawValue(); + const switchstate = centerList[0].testing_seat_uid; + console.log(this.subjectselectList); + switch (this.state) { + case 'edit': + console.log(6666); + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id : id, + centerList : centerList[index], + subjectlist : this.subjectselectList, + state : switchstate === null ? 'add' : 'edit', + } + }); + dialogRefedit.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(0).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + // for (let i = 0; i < form.getRawValue().length; i++) { + // const formArray = form.controls[i].get('testing_seats') as FormArray; + // for (let j = 0; j < testseat.testing_seat.length; j++) { + // formArray.push(testseatdata.get('testing_seat').controls[j]); + // } + // } + this.cdRef.detectChanges(); + } + ); + break; + case 'add': + const dialogRefadd = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + subjectlist : this.subjectselectList, + state : this.state, + } + }); + dialogRefadd.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(0).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + for (let i = 0; i < form.getRawValue().length; i++) { + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + } + this.cdRef.detectChanges(); + } + ); + break; + case 'expand': + console.log(5555); + const dialogRefaddd = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + subjectlist : this.subjectselectList, + state : this.state, + } + }); + dialogRefaddd.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(0).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + for (let i = 0; i < form.getRawValue().length; i++) { + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + } + this.cdRef.detectChanges(); + } + ); + break; + } + } + + + Increasedate(date_str: any){ + const parts = date_str.split('-'); + const dt = new Date( + parseInt(parts[0], 10), // year + parseInt(parts[1], 10) - 1, // month (starts with 0) + parseInt(parts[2], 10) // date + ); + dt.setDate(dt.getDate() + 1); + parts[0] = '' + dt.getFullYear(); + parts[1] = '' + (dt.getMonth() + 1); + if (parts[1].length < 2) { + parts[1] = '0' + parts[1]; + } + parts[2] = '' + dt.getDate(); + if (parts[2].length < 2) { + parts[2] = '0' + parts[2]; + } + return parts.join('-'); + } + + + incr_dateRegis(setNew, date){ + let countRe = 0; + let countTe = 0; + let RegisStartTime = null; + let TestStartTime = null; + console.log(setNew); + // Set registration_start_datetime , testing_start_datetime + RegisStartTime = this.setexamform.get('registration_end_datetime').value; + TestStartTime = this.setexamform.get('testing_end_datetime').value; + let parts = date.split('-'); + if (setNew === 'registration_start_datetime'){ + parts = RegisStartTime.split('-'); + }else if (setNew === 'testing_start_datetime'){ + parts = TestStartTime.split('-'); + } + const dt = new Date( + parseInt(parts[0], 10), // year + parseInt(parts[1], 10) - 1, // month (starts with 0) + parseInt(parts[2], 10) // date + ); + dt.setDate(dt.getDate() + 1); + parts[0] = '' + dt.getFullYear(); + parts[1] = '' + (dt.getMonth() + 1); + if (parts[1].length < 2) { + parts[1] = '0' + parts[1]; + } + parts[2] = '' + dt.getDate(); + if (parts[2].length < 2) { + parts[2] = '0' + parts[2]; + } + parts.join('-'); + const newDate = parts.join('-'); + console.log(newDate); + if (setNew === 'registration_start_datetime'){ + this.setexamform.get('registration_start_datetime').setValue(newDate); + }else if (setNew === 'testing_start_datetime'){ + this.setexamform.get('testing_start_datetime').setValue(newDate); + } + countRe++; + countTe++; + } + + incr_dateTest(setNew, date){ + let countRe = 0; + let countTe = 0; + let RegisStartTime = null; + let TestStartTime = null; + console.log(setNew); + // Set registration_start_datetime , testing_start_datetime + RegisStartTime = this.setexamform.get('registration_end_datetime').value; + TestStartTime = this.setexamform.get('testing_end_datetime').value; + let parts = date.split('-'); + if (setNew === 'registration_start_datetime'){ + parts = RegisStartTime.split('-'); + }else if (setNew === 'testing_start_datetime'){ + parts = TestStartTime.split('-'); + } + const dt = new Date( + parseInt(parts[0], 10), // year + parseInt(parts[1], 10) - 1, // month (starts with 0) + parseInt(parts[2], 10) // date + ); + dt.setDate(dt.getDate() + 1); + parts[0] = '' + dt.getFullYear(); + parts[1] = '' + (dt.getMonth() + 1); + if (parts[1].length < 2) { + parts[1] = '0' + parts[1]; + } + parts[2] = '' + dt.getDate(); + if (parts[2].length < 2) { + parts[2] = '0' + parts[2]; + } + parts.join('-'); + const newDate = parts.join('-'); + console.log(newDate); + if (setNew === 'registration_start_datetime'){ + this.setexamform.get('registration_start_datetime').setValue(newDate); + }else if (setNew === 'testing_start_datetime'){ + this.setexamform.get('testing_start_datetime').setValue(newDate); + } + countRe++; + countTe++; + } + + back() { + this.location.back() + } + +} diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.html b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.html new file mode 100644 index 0000000..f2aee22 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.html @@ -0,0 +1,27 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + +
+
diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.scss b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.spec.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.spec.ts new file mode 100644 index 0000000..ce065e6 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamInformationListComponent } from './change-exam-information-list.component'; + +describe('ChangeExamInformationListComponent', () => { + let component: ChangeExamInformationListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamInformationListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamInformationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.ts new file mode 100644 index 0000000..da19479 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/change-exam-information-list/change-exam-information-list.component.ts @@ -0,0 +1,83 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Input, + Output, + EventEmitter, + OnChanges, + AfterViewInit, + ChangeDetectorRef +} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {MatTableDataSource} from '@angular/material/table'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-change-exam-information-list', + templateUrl: './change-exam-information-list.component.html', + styleUrls: ['./change-exam-information-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamInformationListComponent extends BaseList implements OnInit, OnChanges , AfterViewInit{ + @Output() Tab = new EventEmitter(); + @Input() subjectList: any = []; + @Input() subjectListFalse: any = []; + @Output() edit = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() info = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = ['1', '2', '3', '4', '5', '6']; + column2 = ['1', '2', '3', '4', '5', '6']; + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super(); + } + + ngOnInit(): void { + this.Tab.emit(0); + } + + ngOnChanges(){ + // if (this.Tab === 0){ + // console.log(this.subjectListFalse) + // }else if (this.Tab === 1){ + // console.log(this.subjectList) + // } + console.log(this.subjectListFalse) + console.log(this.subjectList) + } + + ngAfterViewInit() { + } + + onEdit(id){ + this.edit.emit(id); + } + + onInfo(id){ + this.info.emit(id); + } + + onExpand(id){ + this.expand.emit(id); + } + + + onDelete(id){ + this.delete.emit(id); + } + + onTabChanged(event){ + this.Tab.emit(event); + } + + +} diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.html b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.html new file mode 100644 index 0000000..14cc479 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.html @@ -0,0 +1,85 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบการสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
สถานะ + หลัก + รอง + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ + + ไม่มีข้อมูล +
+ +
diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.scss b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.spec.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.spec.ts new file mode 100644 index 0000000..e40a531 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { IsMainFalseComponent } from './is-main-false.component'; + +describe('IsMainFalseComponent', () => { + let component: IsMainFalseComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ IsMainFalseComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(IsMainFalseComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.ts new file mode 100644 index 0000000..d690f37 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-false/is-main-false.component.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-is-main-false', + templateUrl: './is-main-false.component.html', + styleUrls: ['./is-main-false.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class IsMainFalseComponent extends BaseList implements OnInit, OnChanges { + @Input() dataFalse: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + @Output() info = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '12', + 'count_subject', + 'is_open', + 'is_main', + 'created_by', + 'created_datetime', + '8' + ]; + reload: boolean; + constructor() { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.dataFalse = this.updateMatTable(this.dataFalse ? this.dataFalse : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onInfo(id){ + this.info.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.html b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.html new file mode 100644 index 0000000..e57133b --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.html @@ -0,0 +1,85 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบการสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
สถานะ + หลัก + รอง + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ + + ไม่มีข้อมูล +
+ +
diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.scss b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.spec.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.spec.ts new file mode 100644 index 0000000..feabe79 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { IsMainTrueComponent } from './is-main-true.component'; + +describe('IsMainTrueComponent', () => { + let component: IsMainTrueComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ IsMainTrueComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(IsMainTrueComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.ts b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.ts new file mode 100644 index 0000000..f58b4f5 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/list/is-main-true/is-main-true.component.ts @@ -0,0 +1,58 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-is-main-true', + templateUrl: './is-main-true.component.html', + styleUrls: ['./is-main-true.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class IsMainTrueComponent extends BaseList implements OnInit, OnChanges { + @Input() dataTrue: any = []; + @Output() edit = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '12', + 'count_subject', + 'is_open', + 'is_main', + 'created_by', + 'created_datetime', + '8' + ]; + reload: boolean; + constructor() { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + console.log(this.dataTrue); + this.dataTrue = this.updateMatTable(this.dataTrue ? this.dataTrue : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onExpand(id){ + this.expand.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.html b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.html new file mode 100644 index 0000000..19f4e39 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.scss b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.spec.ts b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.spec.ts new file mode 100644 index 0000000..26437b8 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeExamInformationSearchComponent } from './change-exam-information-search.component'; + +describe('ChangeExamInformationSearchComponent', () => { + let component: ChangeExamInformationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeExamInformationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeExamInformationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.ts b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.ts new file mode 100644 index 0000000..88c2543 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/presenter/search/change-exam-information-search/change-exam-information-search.component.ts @@ -0,0 +1,54 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, OnChanges} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; + +@Component({ + selector: 'app-change-exam-information-search', + templateUrl: './change-exam-information-search.component.html', + styleUrls: ['./change-exam-information-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamInformationSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList = []; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + + +} diff --git a/src/app/feature/exam-setting/change-exam-information/router/change-exam-information-router.ts b/src/app/feature/exam-setting/change-exam-information/router/change-exam-information-router.ts new file mode 100644 index 0000000..7129970 --- /dev/null +++ b/src/app/feature/exam-setting/change-exam-information/router/change-exam-information-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-change-exam-information-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeExamInformationRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.html b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.html new file mode 100644 index 0000000..7c98255 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.html @@ -0,0 +1,2 @@ + + diff --git a/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.scss b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.spec.ts b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.spec.ts new file mode 100644 index 0000000..63cc20f --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeSummaryContainer } from './grade-summary.container'; + +describe('GradeSummaryContainer', () => { + let component: GradeSummaryContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeSummaryContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeSummaryContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.ts b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.ts new file mode 100644 index 0000000..6c5ea60 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/container/grade-summary/grade-summary.container.ts @@ -0,0 +1,29 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { SubjectsService } from 'src/app/core/service/settings/subjects.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-grade-summary', + templateUrl: './grade-summary.container.html', + styleUrls: ['./grade-summary.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummaryContainer implements OnInit { + testingInfo$ = new Observable() + constructor( + private testingInformationSV: TestingInformationService + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInformationSV.getAll() + } + + search(query){ + + if(query) return this.testingInfo$ = this.testingInformationSV.search(`?${query}`) + if(!query) return this.testingInfo$ = this.testingInformationSV.getAll() + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/grade-summary.module.ts b/src/app/feature/exam-setting/grade-summary/grade-summary.module.ts new file mode 100644 index 0000000..403f804 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/grade-summary.module.ts @@ -0,0 +1,65 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {RouterModule, Routes} from '@angular/router'; +import {MatTabsModule} from '@angular/material/tabs'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { GradeSummaryContainer } from './container/grade-summary/grade-summary.container'; +import { GradeSummaryRouter } from './router/router'; +import { GradeSummarySubjectListComponent } from './presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component'; +import { GradeSummarySearchComponent } from './presenter/search/grade-summary-search/grade-summary-search.component'; +import { GradeSummaryListComponent } from './presenter/list/grade-summary-list/grade-summary-list.component'; +import { GradeSummaryComponent } from './presenter/grade/grade-summary/grade-summary.component'; +import { ViewComponent } from './presenter/view/view/view.component'; +import { GradeDialogComponent } from './presenter/grade-dialog/grade-dialog.component'; +import { GradeListComponent } from './presenter/grade-list/grade-list/grade-list.component'; + + +const routes: Routes = [ + { + path: '', + component: GradeSummaryRouter, + children: [ + { + path: '', + component: GradeSummaryContainer + }, + { + path: ':id', + component: GradeSummarySubjectListComponent + }, + { + path: 'summary/:id/:uid', + component: GradeSummaryComponent + }, + { + path: 'grade/:id/:uid', + component: GradeListComponent + }, + { + path: 'view/:id', + component: ViewComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + GradeSummaryContainer, + GradeSummaryRouter, + GradeSummarySubjectListComponent, + GradeSummarySearchComponent, + GradeSummaryListComponent, + GradeSummaryComponent, + ViewComponent, + GradeDialogComponent, + GradeListComponent +], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatTabsModule + ] +}) +export class GradeSummaryModule { } diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.html b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.html new file mode 100644 index 0000000..272d60e --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.html @@ -0,0 +1,13 @@ +
+ + +
+
+
+ + +
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.spec.ts new file mode 100644 index 0000000..f1a4ff2 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeDialogComponent } from './grade-dialog.component'; + +describe('GradeDialogComponent', () => { + let component: GradeDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.ts new file mode 100644 index 0000000..112a715 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-dialog/grade-dialog.component.ts @@ -0,0 +1,45 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { tap } from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { GradingService } from 'src/app/core/service/testing-information/grading.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-grade-dialog', + templateUrl: './grade-dialog.component.html', + styleUrls: ['./grade-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeDialogComponent implements OnInit { + testingList: any = []; + gradeData; + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private swSV: SweetalertService, + private gradingSV: GradingService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + // console.log(this.data) + this.gradingSV.search(`?subject_uid=${this.data}`).pipe( + tap(x => this.testingList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + confirm(){ + this.gradingSV.get(this.gradeData).pipe( + tap(x => this.dialogRef.close({grade_data: x})) + ).subscribe() + } + + cancel(){ + this.dialogRef.close() + } + + +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.html b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.html new file mode 100644 index 0000000..8b55dad --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.html @@ -0,0 +1,67 @@ +

กำหนดการตัดเกรด ของวิชา {{data?.subject_name_th}}

+ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ +
+
ลำดับ {{this.getIndex(i)}} รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} ลักษณะการตัดเกรด {{x.grading_characteristic == 1? 'กำหนดช่วงคะแนน' : 'กำหนดช่วงเปอร์เซ็นต์'}} ประเภทเกรด ทั่วไป (เช่น A-F) {{x.announcement_type == 1 ? 'ประกาศผลหลังจากส่งข้อสอบ' : 'รอประกาศผลสอบ'}} รหัสเงื่อนไข {{x.grading_code}} สถานะ + + + check_circle + + +
+ +
+
+
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.spec.ts new file mode 100644 index 0000000..4f8a83e --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeListComponent } from './grade-list.component'; + +describe('GradeListComponent', () => { + let component: GradeListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.ts new file mode 100644 index 0000000..78684a0 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade-list/grade-list/grade-list.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { concatMap, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { GradingService } from 'src/app/core/service/testing-information/grading.service'; + +@Component({ + selector: 'app-grade-list', + templateUrl: './grade-list.component.html', + styleUrls: ['./grade-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeListComponent extends BaseList implements OnInit { + column = ['0', '1', '2', '3', '4', '5', '6','7']; + gradeList: any = []; + data; + constructor( + public activeRoute: ActivatedRoute, + private cdr: ChangeDetectorRef, + private router: Router, + private gradingSV: GradingService, + private swSV: SweetalertService + ) { + super() + } + + ngOnInit(): void { + this.activeRoute.paramMap.pipe( + concatMap((x:any) => this.gradingSV.search('?subject_uid='+x.params.id+'&testing_information_uid='+x.params.uid)), + tap(x => this.data = x[0]), + tap(x => this.gradeList = this.updateMatTable(x)) + ).subscribe() + } + + onView(id){ + this.router.navigate(['grade-summary/view',id]) + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.html b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.html new file mode 100644 index 0000000..fdb41c6 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.html @@ -0,0 +1,98 @@ +
+ +

กำหนดการตัดเกรด

+
+
+
+ + +
+ +
+ + +
+
+ + +
+

ลักษณะการตัดเกรด

+
+ +
+
+
+ + กำหนดช่วงคะแนน + กำหนดช่วงเปอร์เซ็นต์ + +
+ +

ประเภทเกรด

+
+ + ทั่วไป (เช่น A-F) + + + ประกาศผลหลังจากส่งข้อสอบ +
+ รอประกาศผลสอบ +
+ + + + + +
+
+
+
+
+

กำหนดคะแนน

+
+
+ +
+
+ + +
+
+
+ +
+
+ สูงกว่าหรือเท่ากับ + + + + {{form.get('grading_characteristic').value == 1? 'คะแนน' : 'เปอร์เซ็น'}} + +
+ +
+
+
+ +
+
+   +
+
+
+
+
+
+ + +
+ +
+ + +
+
+
+ diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.spec.ts new file mode 100644 index 0000000..36e7586 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeSummaryComponent } from './grade-summary.component'; + +describe('GradeSummaryComponent', () => { + let component: GradeSummaryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeSummaryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeSummaryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.ts new file mode 100644 index 0000000..f5bd632 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/grade/grade-summary/grade-summary.component.ts @@ -0,0 +1,266 @@ +import { E, I } from '@angular/cdk/keycodes'; +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormArray, FormBuilder, Validators } from '@angular/forms'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { ActivatedRoute, Router } from '@angular/router'; +import { of, Subject, throwError } from 'rxjs'; +import { tap } from 'rxjs/internal/operators/tap'; +import { catchError, concatMap, debounceTime, filter } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { SubjectsService } from 'src/app/core/service/settings/subjects.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { GradingService } from 'src/app/core/service/testing-information/grading.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { GradeDialogComponent } from '../../grade-dialog/grade-dialog.component'; + +@Component({ + selector: 'app-grade-summary', + templateUrl: './grade-summary.component.html', + styleUrls: ['./grade-summary.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummaryComponent extends BaseForm implements OnInit { + subject; + oldData; + testingInformationUid; + testingInformationData; + subjectUid; + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + private subjectSV: SubjectsService, + private cdr: ChangeDetectorRef, + private gradingSV: GradingService, + private swSV: SweetalertService, + private dialog: MatDialog, + private testingInformationSV: TestingInformationService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.subjectSV.get(this.id).pipe( + tap(x => this.subject = x), + tap(x => this.form.get('subject_uid').setValue(this.subject.subject_uid)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.activeRoute.params.pipe( + tap(x => this.form.get('testing_information_uid').setValue(x.uid)), + tap(x => this.testingInformationUid = x.uid), + tap(x => this.subjectUid = x.id), + concatMap((x:any) => { + return this.testingInformationSV.get(this.testingInformationUid).pipe( + tap(x => this.testingInformationData = x) + ) + }), + concatMap((x:any) => this.gradingSV.search('?subject_uid='+this.subjectUid+'&testing_information_uid='+this.testingInformationUid+'&is_use=true')), + concatMap((x:any) => { + if(x.length > 0) return this.gradingSV.get(x[0].grading_uid) + if(x.length == 0) return of() + }), + tap(x => this.oldData = x), + ).subscribe() + + } + + gradingTypeChange(event){ + const form = this.form.get('grading_details') as FormArray + if(event.value == 1){ + form.clear() + this.addGradeTemplate() + } else { + form.clear() + } + } + + gradingCharacteristicChange(event){ + const form = this.form.get('grading_details') as FormArray + form.clear() + this.addGradeTemplate() + } + + announcementChange(event){ + if(event.value == 1) { + this.form.get('announcement_date').clearValidators() + this.form.get('announcement_date').updateValueAndValidity() + return this.form.get('announcement_date').setValue(null) + } + this.form.get('announcement_date').setValidators(Validators.required) + this.form.get('announcement_date').updateValueAndValidity() + } + + checkValidate(value,form,index){ + const isPercent = this.form.get('grading_characteristic').value == 2 + const gradingDetailsForm = this.form.get('grading_details') as FormArray + const gradingDetailsRawValue = (this.form.get('grading_details') as FormArray).getRawValue() + const gradeEndBefore = gradingDetailsRawValue[index !== 0 ? index-1 : index].grade_end + const gradeEndAfter = gradingDetailsRawValue[index !== gradingDetailsRawValue.length-1 ? index+1 : index].grade_end + const valueGreaterEqualThan = (grade_end:number) => +value >= grade_end + const valueLessEqualThan = (grade_end:number) => +value <= grade_end + // grade A + if(index === 0){ + if(valueLessEqualThan(gradeEndAfter)){ + gradingDetailsForm.at(index+1).get('grade_end').setValue(null) + }else{ + if(isPercent){ + if(+value > 100){ + return form.get('grade_end').setValue(100) + } + } + form.get('grade_end').setValue(+value) + } + } + + // grade F + if(index === gradingDetailsRawValue.length-1){ + // if(valueGreaterEqualThan(gradeEndBefore) && (typeof gradeEndBefore === 'number')){ + // gradingDetailsForm.at(index).get('grade_end').setValue(null) + // } + + gradingDetailsForm.at(index).get('grade_end').setValue(0) + } + + // grade B,C,D + if(index !== 0 && index !== gradingDetailsRawValue.length-1){ + if((typeof gradeEndBefore === 'number') && valueGreaterEqualThan(gradeEndBefore)){ + form.get('grade_end').setValue(null) + } + if(valueLessEqualThan(gradeEndAfter)){ + gradingDetailsForm.at(index+1).get('grade_end').setValue(null) + } + } + + } + + createForm(){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + grading_uid: null, + testing_information_uid: null, + subject_uid: null, + grading_characteristic: [null,Validators.required], + grading_type: [1,Validators.required], + announcement_type : [null,Validators.required], + announcement_date: null, + grading_details: this.fb.array([]) + }) + } + + addGradeTemplate(){ + const form = this.form.get('grading_details') as FormArray + form.push(this.createDetail('A')) + form.push(this.createDetail('B+')) + form.push(this.createDetail('B')) + form.push(this.createDetail('C+')) + form.push(this.createDetail('C')) + form.push(this.createDetail('D+')) + form.push(this.createDetail('D')) + form.push(this.createDetail('F')) + } + + add(){ + const form = this.form.get('grading_details') as FormArray + form.push(this.createDetail()) + } + + remove(i){ + const form = this.form.get('grading_details') as FormArray + form.removeAt(i) + form.at(form.length-1 >= 0? form.length-1 : 0).get('grade_end').setValue(0) + } + + createDetail(x?){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + grading_detail_uid: null, + grading_uid: null, + grading_name: [x,Validators.required], + grade_start: [null], + grade_end: [null,Validators.required], + }) + } + + save(){ + const form = this.form.getRawValue() + if(this.oldData){ + form.grading_uid = this.oldData.grading_uid + this.gradingSV.update2(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + }else{ + this.gradingSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.location.back() + } + + selectGrade(){ + const dialogRef = this.dialog.open(GradeDialogComponent, { + width: '700px', + data: this.subject.subject_uid, + }); + + dialogRef.afterClosed().pipe( + filter(x => x), + tap(x => this.setupGrade(x.grade_data)) + ).subscribe() + } + + setupGrade(x){ + // announcement_date + // announcement_type + // this.form.patchValue(x)grading_type + this.form.get('grading_type').setValue(x.grading_type) + this.form.get('announcement_type').setValue(x.announcement_type) + this.form.get('announcement_date').setValue(x.announcement_date) + this.form.get('grading_characteristic').setValue(x.grading_characteristic) + this.form.setControl('grading_details',this.fb.array(x?.grading_details.map(z => this.createSelectGradeDetail(z)))) + } + + createSelectGradeDetail(x){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + grading_detail_uid: null, + grading_uid: null, + grading_name: x.grading_name, + grade_start: x.grade_start, + grade_end: x.grade_end, + }) + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.html b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.html new file mode 100644 index 0000000..34955b7 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.html @@ -0,0 +1,64 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ +
+
ลำดับ {{this.getIndex(i)}} รหัสรอบการสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} จำนวนวิชาที่สร้าง {{x.count_grading}}/{{x.count_subject}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}}
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.spec.ts new file mode 100644 index 0000000..80a7b16 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeSummaryListComponent } from './grade-summary-list.component'; + +describe('GradeSummaryListComponent', () => { + let component: GradeSummaryListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeSummaryListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeSummaryListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.ts new file mode 100644 index 0000000..dc46ccb --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/list/grade-summary-list/grade-summary-list.component.ts @@ -0,0 +1,46 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges} from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; +@Component({ + selector: 'grade-summary-list', + templateUrl: './grade-summary-list.component.html', + styleUrls: ['./grade-summary-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummaryListComponent extends BaseList implements OnInit , OnChanges { + column = [ + '1', + '2', + 'testing_information_code', + 'testing_information_name', + '5', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + 'created_datetime' + ]; + reload: boolean; + @Input() testingInformationList: any = []; + constructor( + private router: Router, + ) { + super() + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.testingInformationList = this.updateMatTable(this.testingInformationList? this.testingInformationList:[]) + } + + onEdit(id){ + this.router.navigate(['/grade-summary/',id]) + } + + +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.html b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.spec.ts new file mode 100644 index 0000000..1ee83ea --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeSummarySearchComponent } from './grade-summary-search.component'; + +describe('GradeSummarySearchComponent', () => { + let component: GradeSummarySearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeSummarySearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeSummarySearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.ts new file mode 100644 index 0000000..42b035e --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/search/grade-summary-search/grade-summary-search.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; + +@Component({ + selector: 'grade-summary-search', + templateUrl: './grade-summary-search.component.html', + styleUrls: ['./grade-summary-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummarySearchComponent implements OnInit { + @Output() search = new EventEmitter() + academicYearList = []; + query = { + testing_information_name: null, + testing_information_code: null, + academic_semester_code: null, + academic_year_code: null, + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + testing_information_name: null, + testing_information_code: null, + academic_semester_code: null, + academic_year_code: null, + }; + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.html b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.html new file mode 100644 index 0000000..e8fdb25 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.html @@ -0,0 +1,89 @@ +

กำหนดการตัดเกรด ของรอบสอบ {{data?.testing_information_name}}

+
+
+
+ + +
+
+
+
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ + +
+
ลำดับ {{this.getIndex(i)}} รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} ลักษณะการตัดเกรด + + {{x.grading_characteristic == 1? 'กำหนดช่วงคะแนน' : 'กำหนดช่วงเปอร์เซ็นต์'}} + + - + ประเภทเกรด {{x.grading_type == 1? 'ทั่วไป (เช่น A-F)' : '-'}} วันที่ประกาศผลสอบ + + {{x.announcement_type == 2? x.announcement_date : 'ประกาศผลหลังจากส่งข้อสอบ'}} + + - + ชื่อวิชา {{x.subject_name_th}} รหัสเงื่อนไข {{x.grading_code}} กำหนดเกณฑ์ + + + check_circle + + + +
+ +
+
+
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.spec.ts new file mode 100644 index 0000000..3bd6a81 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradeSummarySubjectListComponent } from './grade-summary-subject-list.component'; + +describe('GradeSummarySubjectListComponent', () => { + let component: GradeSummarySubjectListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradeSummarySubjectListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradeSummarySubjectListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.ts new file mode 100644 index 0000000..b9a4f50 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/subject-list/grade-summary-subject-list/grade-summary-subject-list.component.ts @@ -0,0 +1,84 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, AfterViewInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { filter, switchMap, tap } from 'rxjs/operators'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { GradingService } from 'src/app/core/service/testing-information/grading.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-grade-summary-subject-list', + templateUrl: './grade-summary-subject-list.component.html', + styleUrls: ['./grade-summary-subject-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummarySubjectListComponent extends BaseSubList implements OnInit,AfterViewInit{ + column = ['0','1','2','3','4','5','6','7','8','9'] + subjectList; + data; + constructor( + public activeRoute: ActivatedRoute, + private testingInfoSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private router: Router, + private gradingSV: GradingService, + private swSV: SweetalertService + ) { + super(activeRoute) + } + + ngOnInit(): void { + + } + + ngAfterViewInit(){ + this.testingInfoSV.get(this.id).pipe( + tap(x => this.data = x), + tap((x:any) => this.subjectList = x.testing_subjects), + tap(x => this.subjectList = this.updateMatTable(this.subjectList? this.subjectList:[])), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.subjectList.filter = filterValue.trim().toLowerCase(); + } + + onDelete(id){ + let data; + this.gradingSV.search('?subject_uid='+id+'&testing_information_uid='+this.data.testing_information_uid).pipe( + tap(x => data = x[0]), + tap(x => this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.gradingSV.deleteData(data.grading_uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.testingInfoSV.get(this.id).subscribe((x:any) => { + this.subjectList.data = x.testing_subjects + this.cdr.detectChanges() + })), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe()), + ).subscribe() + } + + gradeList(id){ + this.router.navigate(['grade-summary/grade',id,this.id]) + } + + onEdit(id){ + this.router.navigate(['grade-summary/summary',id,this.id]) + } + + onView(id){ + let data; + this.gradingSV.search('?subject_uid='+id+'&testing_information_uid='+this.data.testing_information_uid).pipe( + tap(x => data = x[0]), + tap(x => this.router.navigate(['grade-summary/view',data.grading_uid])) + ).subscribe() + } +} diff --git a/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.html b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.html new file mode 100644 index 0000000..ea1bf64 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.html @@ -0,0 +1,84 @@ +
+ +

กำหนดการตัดเกรด

+
+
+
+ + +
+ +
+ + +
+
+ +

ลักษณะการตัดเกรด

+
+ + กำหนดช่วงเปอร์เซ็นต์ + กำหนดช่วงคะแนน + +
+ +

ประเภทเกรด

+
+ + ทั่วไป (เช่น A-F) + + + ประกาศผลหลังจากส่งข้อสอบ +
+ รอประกาศผลสอบ +
+ + + + + +
+
+
+
+
+

กำหนดคะแนน

+
+ +
+ + +
+
+
+ +
+
+ สูงกว่าหรือเท่ากับ + + + {{form.get('grading_characteristic').value == 1? 'คะแนน' : 'เปอร์เซ็น'}} + +
+
+
+
+
+   +
+
+
+
+
+
+ +
+ + +
+
+ +
{{form.getRawValue() | json}}
diff --git a/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.scss b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.spec.ts b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.spec.ts new file mode 100644 index 0000000..f644b0a --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewComponent } from './view.component'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.ts b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.ts new file mode 100644 index 0000000..c981c60 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/presenter/view/view/view.component.ts @@ -0,0 +1,111 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { throwError } from 'rxjs'; +import { tap, catchError, filter, switchMap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { SubjectsService } from 'src/app/core/service/settings/subjects.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { GradingService } from 'src/app/core/service/testing-information/grading.service'; + +@Component({ + selector: 'app-view', + templateUrl: './view.component.html', + styleUrls: ['./view.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ViewComponent extends BaseForm implements OnInit { + grade; + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + private subjectSV: SubjectsService, + private cdr: ChangeDetectorRef, + private gradingSV: GradingService, + private swSV: SweetalertService, + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.gradingSV.get(this.id).pipe( + tap(x => this.grade = x), + tap(x => this.setupForm(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + setupForm(x){ + this.form.patchValue(x) + this.form.setControl('grading_details',this.fb.array(x?.grading_details.map(z => this.createDetail(z)))) + } + createForm(){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + grading_uid: null, + testing_information_uid: null, + subject_uid: null, + grading_characteristic: null, + grading_type: null, + announcement_type : [null,Validators.required], + announcement_date: null, + grading_details: this.fb.array([]) + }) + } + + createDetail(x){ + return this.fb.group({ + status_id: x.status_id, + created_by: x.created_by, + created_datetime: x.created_datetime, + updated_by: x.updated_by, + updated_datetime: x.updated_datetime, + deleted_by: x.deleted_by, + deleted_datetime: x.deleted_datetime, + grading_detail_uid: x.grading_detail_uid, + grading_uid: x.grading_uid, + grading_name: x.grading_name, + grade_start: x.grade_start, + grade_end: x.grade_end, + }) + } + + save(){ + const form = this.form.getRawValue() + this.gradingSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + + cancel(){ + this.location.back() + } + + onDelete(){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.gradingSV.deleteData(this.id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.location.back()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/exam-setting/grade-summary/router/router.ts b/src/app/feature/exam-setting/grade-summary/router/router.ts new file mode 100644 index 0000000..bf05467 --- /dev/null +++ b/src/app/feature/exam-setting/grade-summary/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-grade-summary-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GradeSummaryRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.html b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.html new file mode 100644 index 0000000..3d4cd25 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.html @@ -0,0 +1,12 @@ + + + + + diff --git a/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.scss b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.spec.ts b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.spec.ts new file mode 100644 index 0000000..7a19ad4 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageExamOfficerContainer } from './manage-exam-officer.container'; + +describe('ManageExamOfficerContainer', () => { + let component: ManageExamOfficerContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageExamOfficerContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageExamOfficerContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.ts b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.ts new file mode 100644 index 0000000..b7c0b46 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/container/manage-exam-officer/manage-exam-officer.container.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {TestingInformationService} from "../../../../../core/service/testing-information/testing-information.service"; +import {Router} from "@angular/router"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import {Observable} from "rxjs"; +import {concatMap, filter, tap} from "rxjs/operators"; + +@Component({ + selector: 'app-manage-exam-officer', + templateUrl: './manage-exam-officer.container.html', + styleUrls: ['./manage-exam-officer.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageExamOfficerContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getAll(); + } + + add(){ + this.router.navigate(['manage-exam-officer/add']); + } + + edit(id){ + + this.router.navigate(['manage-exam-officer/edit', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + + +} diff --git a/src/app/feature/exam-setting/manage-exam-officer/manage-exam-officer.module.ts b/src/app/feature/exam-setting/manage-exam-officer/manage-exam-officer.module.ts new file mode 100644 index 0000000..2bcbe0b --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/manage-exam-officer.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ManageExamOfficerContainer } from './container/manage-exam-officer/manage-exam-officer.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import {ManageExamOfficerRouter} from './router/manage-exam-officer-router'; +import { ManageExamOfficerListComponent } from './presenter/manage-exam-officer-list/manage-exam-officer-list.component'; +import { ManageExamOfficerSearchComponent } from './presenter/manage-exam-officer-search/manage-exam-officer-search.component'; +import { ManageExamOfficerDetailComponent } from './presenter/manage-exam-officer-detail/manage-exam-officer-detail.component'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; + +const routes: Routes = [ + { + path: '', + component: ManageExamOfficerRouter, + children: [ + { + path: '', + component: ManageExamOfficerContainer + }, + { + path: 'edit/:id', + component: ManageExamOfficerDetailComponent + }, + { + path: 'add', + component: ManageExamOfficerDetailComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + ManageExamOfficerRouter, + ManageExamOfficerContainer, + ManageExamOfficerListComponent, + ManageExamOfficerSearchComponent, + ManageExamOfficerDetailComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatProgressSpinnerModule, + ] +}) +export class ManageExamOfficerModule { } diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.html b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.html new file mode 100644 index 0000000..dee6aa3 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.html @@ -0,0 +1,101 @@ + +
+
+
+

กำหนดกรรมการคุมสอบของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} Username +
+ + + + {{x.login_name}} ({{x.display_name}}) + + +
+
ชื่อผู้คุมสอบ {{x.invigilator_name}} + + +
+ +
+
+ +
+
+
+
+

กำหนดกรรมการคุมสอบพิเศษ

+ +
+ + +
+ + +
+
+ + + + + + +
+
+ + + + + {{a.get('invigilator_name').value}} + + + + + + + {{user.login_name}} + + + +
+
+ +
+
+
+
+
+
+ +
+
+
+ +
+
{{form.getRawValue() | json}}
+ + diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.scss b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.spec.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.spec.ts new file mode 100644 index 0000000..de872c2 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageExamOfficerDetailComponent } from './manage-exam-officer-detail.component'; + +describe('ManageExamOfficerDetailComponent', () => { + let component: ManageExamOfficerDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageExamOfficerDetailComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageExamOfficerDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.ts new file mode 100644 index 0000000..adaf83f --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-detail/manage-exam-officer-detail.component.ts @@ -0,0 +1,230 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef, ViewChild} from '@angular/core'; +import {BaseForm} from "../../../../../core/base/base-form"; +import {Form, FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms"; +import {MatDialog} from "@angular/material/dialog"; +import {ActivatedRoute, Router} from "@angular/router"; +import {Location} from "@angular/common"; +import {tap} from "rxjs/operators"; +import {RoomInvigilatorsService} from "../../../../../core/service/testing-information/room-invigilators.service"; +import {SweetalertService} from "../../../../../core/service/sweetalert/sweetalert"; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { isBuffer } from 'util'; + +// @ts-ignore +@Component({ + selector: 'app-manage-exam-officer-detail', + templateUrl: './manage-exam-officer-detail.component.html', + styleUrls: ['./manage-exam-officer-detail.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageExamOfficerDetailComponent extends BaseForm implements OnInit { + @ViewChild(MatSort,{ static: true }) sort: MatSort; + @ViewChild(MatPaginator,{ static: true }) paginator: MatPaginator; + protected updateMatTable(res: any){ + res = new MatTableDataSource(res) + res.paginator = this.paginator + res.sort = this.sort + return res + } + exam_date; + testingInfoData; + list: any = []; + specialList: any = []; + userList: any = []; + constructor( + public fb: FormBuilder, + private swSV: SweetalertService, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private cdr: ChangeDetectorRef, + private roomInvigilatorSV: RoomInvigilatorsService, + private userOpenidSV: UserOpenidService, + private testingInformationSV: TestingInformationService + ) { + super(router,activeRoute,fb,location); + } + + ngOnInit(): void { + this.form.valueChanges.pipe( + tap(x => this.list = this.updateMatTable(x.invigilator_list)), + ).subscribe() + this.userOpenidSV.getAll().pipe(tap(x => this.userList = x)).subscribe() + this.roomInvigilatorSV.search(`?testing_information_uid=${this.id}`).pipe( + tap(x => this.setupForm(x)), + ).subscribe() + this.testingInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + setupForm(data){ + const dataReduce = data.reduce((a,c) => { + if(a[c.examination_date]){ + a[c.examination_date].invigilator_list.push(c) + }else{ + a[c.examination_date] = { + examination_date : c.examination_date, + invigilator_list: [c] + } + } + return a; + },{}) + const newData = Object.values(dataReduce) + const invigilator_form = this.form.get('invigilator_list') as FormArray + const special_list_form = this.form.get('special_list') as FormArray + newData.map((x:any) => { + if(x.examination_date){ + special_list_form.push(this.updateSpecialList(x)) + }else{ + x.invigilator_list.map(a => invigilator_form.push(this.createUpdateInvigilatorForm(a))) + } + }) + this.cdr.detectChanges() + } + + createForm(){ + return this.fb.group({ + invigilator_list: this.fb.array([],Validators.required), + special_list: this.fb.array([]) + }) + } + + addSpecial(){ + const form = this.form.get('special_list') as FormArray + form.push(this.createSpecialList()) + } + + createSpecialList(){ + return this.fb.group({ + examination_date: [null,Validators.required], + invigilator_list: this.fb.array([],Validators.required) + }) + } + + updateSpecialList(data){ + return this.fb.group({ + examination_date: data.examination_date, + invigilator_list: this.fb.array(data.invigilator_list.map(x => this.createUpdateInvigilatorForm(x))) + }) + } + + addSpecialInvi(user,form){ + const invigilatorList = this.form.get('invigilator_list') as FormArray + const array = form.get('invigilator_list') as FormArray + const date = form.get('examination_date').value + if(!array.getRawValue().some(x => x.invigilator_uid == user.user_uid) && !invigilatorList.getRawValue().some(x => x.invigilator_uid == user.user_uid)){ + array.push(this.createInvigilatorForm(user,date)) + }else{ + this.swSV.errText('มีผู้คุมสอบซ้ำ') + } + } + + + createUpdateInvigilatorForm(x){ + return this.fb.group({ + status_id: x.status_id, + created_by: x.created_by, + created_datetime: x.created_datetime, + updated_by: x.updated_by, + updated_datetime: x.updated_datetime, + deleted_by: x.deleted_by, + deleted_datetime: x.deleted_datetime, + testing_invigilator_uid: x.testing_invigilator_uid, + testing_information_uid: [x.testing_information_uid], + invigilator_uid: [x?.invigilator_uid,Validators.required], + invigilator_code: [x?.invigilator_code,Validators.required], + invigilator_name: [x?.invigilator_name,Validators.required], + examination_date: x.examination_date, + }) + } + createInvigilatorForm(special?,date?): FormGroup { + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_invigilator_uid: null, + testing_information_uid: this.id, + invigilator_uid: [special?.user_uid,Validators.required], + invigilator_code: [special?.login_name,Validators.required], + invigilator_name: [special?.display_name,Validators.required], + examination_date: date, + }) + } + + addInvigilator(){ + const form = this.form.get('invigilator_list') as FormArray + form.push(this.createInvigilatorForm()) + } + + setDisplayName(x,index){ + const form = this.form.get('invigilator_list') as FormArray + const list = this.form.getRawValue() + const array = [] + list.special_list.map(x => {x.invigilator_list.map(b => array.push(b))}) + const allList = [...list.invigilator_list,...array] + if(!allList.some(data => data.invigilator_uid == x.user_uid)){ + form.at(index).get('invigilator_name').setValue(x.display_name) + form.at(index).get('invigilator_uid').setValue(x.user_uid) + form.at(index).get('invigilator_code').setValue(x.login_name) + }else{ + this.swSV.errText('มีผู้คุมสอบซ้ำ') + form.at(index).get('invigilator_name').setValue(null) + form.at(index).get('invigilator_uid').setValue(null) + form.at(index).get('invigilator_code').setValue(null) + } + // const specialList = (this.form.get('special_list') as FormArray).value + // const invigilatorList = (this.form.get('invigilator_list') as FormArray).value + // if(specialList.find(data => x)) + // console.log(specialList.find(data => data.invigilator_name == x.display_name)) + // form.at(index).get('invigilator_name').setValue(x.display_name) + // form.at(index).get('invigilator_uid').setValue(x.user_uid) + // form.at(index).get('invigilator_code').setValue(x.login_name) + } + + + removeInvigilator(index){ + const form = this.form.get('invigilator_list') as FormArray + form.removeAt(index) + } + + removeChip(form,index){ + const arrayForm = form.get('invigilator_list') as FormArray + arrayForm.removeAt(index) + } + + addDate(event,form){ + const arrayForm = form.get('invigilator_list') as FormArray + arrayForm.controls.map(x => x.get('examination_date').setValue(event.value)) + } + + removeSpecial(index){ + const form = this.form.get('special_list') as FormArray + form.removeAt(index) + } + + save(){ + const form = this.form.getRawValue() + const array = [] + form.special_list.map(x => { + x.invigilator_list.map(b => array.push(b)) + }) + const save = [...form.invigilator_list,...array] + this.roomInvigilatorSV.putMany(save).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()) + ).subscribe() + } + + +} diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.html b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.html new file mode 100644 index 0000000..5830a01 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.html @@ -0,0 +1,86 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ +
+ + +
+
+
diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.scss b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.spec.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.spec.ts new file mode 100644 index 0000000..c0e9ceb --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageExamOfficerListComponent } from './manage-exam-officer-list.component'; + +describe('ManageExamOfficerListComponent', () => { + let component: ManageExamOfficerListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageExamOfficerListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageExamOfficerListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.ts new file mode 100644 index 0000000..27585b2 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-list/manage-exam-officer-list.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; + +@Component({ + selector: 'app-manage-exam-officer-list', + templateUrl: './manage-exam-officer-list.component.html', + styleUrls: ['./manage-exam-officer-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageExamOfficerListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + @Output() edit = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + '9', + 'created_by', + '10', + 'created_datetime', + '7' + ]; + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.subjectList); + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + console.log() + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.html b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.html new file mode 100644 index 0000000..d25afb7 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.scss b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.spec.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.spec.ts new file mode 100644 index 0000000..0a95109 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageExamOfficerSearchComponent } from './manage-exam-officer-search.component'; + +describe('ManageExamOfficerSearchComponent', () => { + let component: ManageExamOfficerSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageExamOfficerSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageExamOfficerSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.ts b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.ts new file mode 100644 index 0000000..99174cf --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/presenter/manage-exam-officer-search/manage-exam-officer-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from "../../../../../shared/util/func"; +import {AcademicYearService} from "../../../../../core/service/settings/academic-year.service"; + +@Component({ + selector: 'app-manage-exam-officer-search', + templateUrl: './manage-exam-officer-search.component.html', + styleUrls: ['./manage-exam-officer-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageExamOfficerSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList = []; + + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + console.log(result); + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/exam-setting/manage-exam-officer/router/manage-exam-officer-router.ts b/src/app/feature/exam-setting/manage-exam-officer/router/manage-exam-officer-router.ts new file mode 100644 index 0000000..1b3f262 --- /dev/null +++ b/src/app/feature/exam-setting/manage-exam-officer/router/manage-exam-officer-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-manage-exam-officer-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageExamOfficerRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.html b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.html new file mode 100644 index 0000000..8b2290b --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.html @@ -0,0 +1,6 @@ + + diff --git a/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.scss b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.spec.ts b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.spec.ts new file mode 100644 index 0000000..0bcdcb2 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomQuestionsContainer } from './random-questions.container'; + +describe('RandomQuestionsContainer', () => { + let component: RandomQuestionsContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomQuestionsContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomQuestionsContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.ts b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.ts new file mode 100644 index 0000000..9563a07 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/container/random-questions/random-questions.container.ts @@ -0,0 +1,26 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-random-questions', + templateUrl: './random-questions.container.html', + styleUrls: ['./random-questions.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsContainer implements OnInit { + testingInformation$ = new Observable() + constructor( + private testingInfoSV: TestingInformationService + ) { } + + ngOnInit(): void { + this.testingInformation$ = this.testingInfoSV.getAll() + } + + search(query){ + if(query) return this.testingInformation$ = this.testingInfoSV.search(`?${query}`) + if(!query) return this.testingInformation$ = this.testingInfoSV.getAll() + } + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.html b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.html new file mode 100644 index 0000000..b05d682 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.html @@ -0,0 +1,107 @@ +
+ +

กำหนดการสุ่มคำถาม

+
+
+
+ + +
+ +
+ + +
+ +
+ +
+
+ +

ลักษณะการสุ่ม

+
+ + ไม่มีการสลับข้อใด ๆ เลย + สลับข้อคำถาม แต่ตัวเลือกไม่สลับ + สลับตัวเลือก แต่ข้อคำถามไม่สลับ + สลับทุกอย่าง ทั้งข้อคำถามและตัวเลือก + +
+ +

วิธีการสุ่มข้อสอบ

+
+ + สุ่มแบบชุด + สุ่มแยกบท + สุ่มโดยอาจารย์ + +
+
+
+

วิธีการสุ่มข้อสอบ

+ + + + + + + + + + +
+ + +
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.scss b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.spec.ts new file mode 100644 index 0000000..8d07815 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomQuestionsFormContainer } from './random-questions-form.container'; + +describe('RandomQuestionsFormContainer', () => { + let component: RandomQuestionsFormContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomQuestionsFormContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomQuestionsFormContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.ts b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.ts new file mode 100644 index 0000000..254eb0b --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/container/random-questions-form/random-questions-form.container.ts @@ -0,0 +1,340 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormArray, FormBuilder, RequiredValidator, Validators } from '@angular/forms'; +import { MatGridTileHeaderCssMatStyler } from '@angular/material/grid-list'; +import { ActivatedRoute, Router } from '@angular/router'; +import { of, throwError } from 'rxjs'; +import { catchError, concatMap, filter, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { QuestionCategoryService } from 'src/app/core/service/question/question-category.service'; +import { SubjectsService } from 'src/app/core/service/settings/subjects.service'; +import { SubjectInformationService } from 'src/app/core/service/store-api/subject-information.service'; +import { SyncStoreService } from 'src/app/core/service/store-api/sync.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { RandomQuestionsService } from 'src/app/core/service/testing-information/random-questions.service'; + +@Component({ + selector: 'app-random-questions-form', + templateUrl: './random-questions-form.container.html', + styleUrls: ['./random-questions-form.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsFormContainer extends BaseFormUid implements OnInit { + questionCategory; + questionCategoryAll; + questionCategoryInstructor; + questionCategoryType; + data; + subject; + subjectInformation; + oldData; + buttonDisabled: boolean = false + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private questionCategoryDetailSV: QuestionCategoryService, + private cdr: ChangeDetectorRef, + private subjectSV: SubjectsService, + private randomQuestionSV: RandomQuestionsService, + private swSV: SweetalertService, + private subjectInformationSV : SubjectInformationService, + private syncSV: SyncStoreService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + if(this.state == 'edit'){ + this.activeRoute.paramMap.pipe( + concatMap((x:any) => this.randomQuestionSV.search('?subject_uid='+x.params.id+'&testing_information_uid='+x.params.uid+'&is_use=true')), + concatMap((x:any) => { + if(x.length > 0) { + return this.randomQuestionSV.get(x[0].random_question_uid) + } else { + return of() + } + }), + tap((x:any) => this.oldData = x), + ).subscribe() + this.questionCategoryDetailSV.getSubject(this.id).pipe( + tap(x => this.questionCategory = x), + concatMap((x:any) => this.subjectInformationSV.get(x[0].subject_information_uid)), + tap(x => this.subjectInformation = x), + ).subscribe() + this.questionCategoryDetailSV.search('?subject_uid='+this.id+'&level=0').pipe( + tap((x:any) => this.questionCategoryType = x.filter((v,i,a) => a.findIndex(b => b.question_category_master_uid == v.question_category_master_uid) === i)) + ).subscribe() + this.questionCategoryDetailSV.getAllSubject(this.id).pipe( + tap(x => this.questionCategoryAll = x), + ).subscribe() + this.questionCategoryDetailSV.getSubjectWithInstructor(this.id).pipe( + tap(x => this.questionCategoryInstructor = x) + ).subscribe() + this.subjectSV.get(this.id).pipe( + tap(x => this.subject = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.form.get('subject_uid').setValue(this.id) + this.activeRoute.params.pipe( + tap(x => this.form.get('testing_information_uid').setValue(x.uid)) + ).subscribe() + } + } + + createForm(){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + random_question_uid: null, + testing_information_uid: null, + subject_uid: null, + random_type: [null,Validators.required], + random_question_type: [null,Validators.required], + time_to_complete_exam: [null,Validators.required], + random_question_details: this.fb.array([]), + array: this.fb.array([ + this.createArray() + ]) + }) + } + + questionTypeChange(event){ + this.buttonDisabled = false + const form = this.form.get('array') as FormArray + const random = this.form.get('random_question_details') as FormArray + if(event.value == 3){ + form.clear() + random.clear() + random.push(this.createInstructorForm()) + this.form.get('time_to_complete_exam').setValidators(Validators.required) + this.form.get('time_to_complete_exam').updateValueAndValidity() + } else if (event.value == 1){ + form.clear() + random.clear() + random.push(this.createGroupForm()) + this.form.get('time_to_complete_exam').clearValidators() + this.form.get('time_to_complete_exam').updateValueAndValidity() + } else{ + form.clear() + random.clear() + this.form.get('time_to_complete_exam').setValidators(Validators.required) + this.form.get('time_to_complete_exam').updateValueAndValidity + form.push(this.createArray()) + } + } + + randomTypeChange(event){ + const form = this.form.get('array') as FormArray + const random = this.form.get('random_question_details') as FormArray + form.clear() + random.clear() + this.form.get('random_question_type').setValue(null) + } + + createArray(){ + return this.fb.group({ + arr: this.fb.array([],Validators.required) + }) + } + + addTeacher(){ + const form = this.form.get('random_question_details') as FormArray + form.push(this.createInstructorForm()) + } + + removeTeacher(index){ + const form = this.form.get('random_question_details') as FormArray + form.removeAt(index) + } + + createGroupForm(){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + random_question_detail_uid: null, + random_question_uid: [null], + question_set_uid: [null,Validators.required], + total_question: [0,Validators.required], + question_sub_set_uid: null, + total_question_easy: [null], + total_question_medium: [null], + total_question_hard: [null], + instructor_uid: [null], + instructor_name: null, + num_question: null, + exam_time: [null,Validators.required], + row_order: null, + total_question_porranai: null, + total_question_auttanai: null + }) + } + + createInstructorForm(){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + random_question_detail_uid: null, + random_question_uid: null, + question_set_uid: null, + total_question: [null,Validators.required], + question_sub_set_uid: null, + total_question_easy: [null], + total_question_medium: [null], + total_question_hard: [null], + instructor_uid: [null,Validators.required], + instructor_name: null, + num_question: null, + row_order: null, + multiple_choice_easy: [0,Validators.required], + subjective_easy: [0,Validators.required], + multiple_choice_medium: [0,Validators.required], + subjective_medium: [0,Validators.required], + multiple_choice_hard: [0,Validators.required], + subjective_hard: [0,Validators.required], + total_question_auttanai_easy: null, + total_question_porranai_easy: null, + total_question_auttanai_medium: null, + total_question_porranai_medium: null, + total_question_auttanai_hard: null, + total_question_porranai_hard: null, + total_question_porranai: null, + total_question_auttanai: null, + }) + } + + + addCategory(){ + const form = this.form.get('array') as FormArray + form.push(this.createArray()) + } + + addGroup(){ + const form = this.form.get('random_question_details') as FormArray + form.push(this.createGroupForm()) + } + + save(){ + const teacherForm = this.form.getRawValue() + teacherForm.random_question_details.map((data,index) => { + data.row_order = index+1 + }) + if(this.oldData){ + teacherForm.random_question_uid = this.oldData.random_question_uid + } + + this.swSV.confirmWithSubtext('ผู้เข้าสอบที่ยังไม่ได้สอบจะถูกลบข้อมูลการสุ่มเดิมและแทนที่ด้วยลักษณะการสุ่มนี้','กรุณากดสร้างข้อสอบใหม่ทุกครั้งหลังจากเปลี่ยนเงื่อนไข').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + if(teacherForm.random_question_type == 3){ + if(this.oldData){ + return this.randomQuestionSV.update2(teacherForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + }else{ + return this.randomQuestionSV.add(teacherForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + } + }else if (teacherForm.random_question_type == 1){ + if(this.oldData){ + return this.randomQuestionSV.update2(teacherForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + } else { + return this.randomQuestionSV.add(teacherForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + } + }else{ + let newdata = [] + const saveForm = this.form.getRawValue() + const arr = this.form.get('array') as FormArray + const form = arr.getRawValue() + form.map(x => { + x.arr.map(a => newdata.push(a)) + }) + newdata.map((data,index) => { + data.row_order = index+1 + }) + saveForm.random_question_details = newdata; + if(this.oldData){ + saveForm.random_question_uid = this.oldData.random_question_uid + return this.randomQuestionSV.update2(saveForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + }else{ + return this.randomQuestionSV.add(saveForm).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + } + } + }), + concatMap(x => { + return this.syncSV.deleteTest(teacherForm.testing_information_uid,teacherForm.subject_uid) + }) + ).subscribe() + } + + cancel(){ + this.location.back() + } + + removeCategory(index){ + const form = this.form.get('array') as FormArray + form.removeAt(index) + } + + removeGroup(index){ + const form = this.form.get('random_question_details') as FormArray + form.removeAt(index) + } + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.html b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.html new file mode 100644 index 0000000..748f0d6 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.html @@ -0,0 +1,121 @@ +
+
+
+
+
+
+ +
+ เวลาในการทำข้อสอบ + + นาที +
+
+ เลือกโครง +
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อบท {{x.question_category_name_th}} จำนวนข้อในบท {{x.total}} ระดับง่าย +
+
+ ปรนัย + +  / {{x.porranai_easy}} +
+
+ อัตนัย + +  / {{x.auttanai_easy}} +
+ +
+
ระดับปานกลาง + +
+
+ ปรนัย + +  / {{x.porranai_medium}} +
+
+ อัตนัย + +  / {{x.auttanai_medium}} +
+ +
+
ระดับยาก + +
+
+ ปรนัย + +  / {{x.porranai_hard}} +
+
+ อัตนัย + +  / {{x.auttanai_hard}} +
+ +
+
จำนวนที่สุ่มไป {{x.total_random}}
+
+
+
+
+ diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.scss b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.spec.ts new file mode 100644 index 0000000..542810f --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CategoryListComponent } from './category-list.component'; + +describe('CategoryListComponent', () => { + let component: CategoryListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CategoryListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CategoryListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.ts new file mode 100644 index 0000000..d47f27f --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/category/category-list/category-list.component.ts @@ -0,0 +1,210 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { distinctUntilChanged, tap } from 'rxjs/operators'; +import { QuestionCategoryService } from 'src/app/core/service/question/question-category.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { SweetAlertArrayOptions } from 'sweetalert2'; + +@Component({ + selector: 'category-list', + templateUrl: './category-list.component.html', + styleUrls: ['./category-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CategoryListComponent implements OnInit { + getArr(){ return this.form.get('arr') as FormArray } + @ViewChild('input') input: ElementRef; + @ViewChild('porranaiEasy') multiple_choice_easy: ElementRef; + @ViewChild('auttanaiEasy') subjective_easy: ElementRef; + @ViewChild('porranaiMedium') multiple_choice_medium: ElementRef; + @ViewChild('auttanaiMedium') subjective_medium: ElementRef; + @ViewChild('porranaiHard') multiple_choice_hard: ElementRef; + @ViewChild('auttanaiHard') subjective_hard: ElementRef; + @Input() form: FormGroup; + @Input() oldForm: FormGroup; + @Input() index; + @Input() category; + @Input() first; + @Input() reset; + @Input() categoryType: any = []; + @Output() addCategory = new EventEmitter() + @Output() removeCategory = new EventEmitter() + @Output() isButtonDisabled = new EventEmitter() + data; + test; + isMore; + totalQuestion; + questionFrameData; + column = ['1','2','3','4','5','6','7'] + constructor( + public fb: FormBuilder, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private questionCategorySV: QuestionCategoryService + ) { } + + ngOnInit(): void { + + } + + add(){ + this.addCategory.emit() + } + + isMoreThan360(event){ + if(event.target.valueAsNumber > 360) return this.oldForm.get('time_to_complete_exam').setValue(360) + } + + remove(){ + this.removeCategory.emit(this.index) + } + + pushQuestion(data){ + const question = data + this.form.setControl('arr',this.fb.array(question.question_category_list_child.map((x,index) => this.createRandomQuestionDetail(x,question.question_category_master_uid,index)))) + const form = this.getArr().value + if(form.length > 1){ + this.totalQuestion = form.reduce((acc,cur)=> {return acc + cur.total},0) + } else { + this.totalQuestion = form[0].total + } + this.isButtonDisabled.emit(this.checkCondition()) + this.test = this.getArr().value + this.cdr.detectChanges() + } + + onChange(event){ + this.questionCategorySV.getCategoryType(event.subject_uid,event.question_category_master_uid).pipe( + tap(x => this.pushQuestion(x[0])), + tap(x => this.questionFrameData = x[0]), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + createRandomQuestionDetail(x,data,index){ + return this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + random_question_detail_uid: null, + random_question_uid: null, + question_set_uid: data, + question_sub_set_uid: x.question_category_master_uid, + total_question_easy: [0,Validators.required], + total_question_medium: [0,Validators.required], + total_question_hard: [0,Validators.required], + question_category_name_th: x.question_category_name_th, + total: x.total_question, + total_question: null, + total_random: null, + auttanai_easy: x.total_question_auttanai_easy, + porranai_easy: x.total_question_porranai_easy, + auttanai_medium: x.total_question_auttanai_medium, + porranai_medium: x.total_question_porranai_medium, + auttanai_hard: x.total_question_auttanai_hard, + porranai_hard: x.total_question_porranai_hard, + multiple_choice_easy: [0,Validators.required], + subjective_easy: [0,Validators.required], + multiple_choice_medium: [0,Validators.required], + subjective_medium: [0,Validators.required], + multiple_choice_hard: [0,Validators.required], + subjective_hard: [0,Validators.required], + row_order: index+1, + is_ok_easy: x.is_ok_easy, + is_ok_easy_auttanai: x.is_ok_easy_auttanai, + is_ok_easy_porranai: x.is_ok_easy_porranai, + is_ok_medium: x.is_ok_medium, + is_ok_medium_auttanai: x.is_ok_medium_auttanai, + is_ok_medium_porranai: x.is_ok_medium_porranai, + is_ok_hard: x.is_ok_hard, + is_ok_hard_auttanai: x.is_ok_hard_auttanai, + is_ok_hard_porranai: x.is_ok_hard_porranai, + }) + } + + total(input){ + if(input <= this.totalQuestion){ + this.getArr().controls.map(x => { + x.get('total_question_easy').setValue(null) + x.get('total_question_medium').setValue(null) + x.get('total_question_hard').setValue(null) + }) + } else { + this.swSV.errText('จำนวนคำถามมากเกินกำหนด') + this.input.nativeElement.value = 0 + this.getArr().controls.map(x => { + x.get('total_question_easy').setValue(null) + x.get('total_question_medium').setValue(null) + x.get('total_question_hard').setValue(null) + }) + } + } + + sumTotal(index,type?){ + return this.getArr().at(index).get('subjective_easy').value + + this.getArr().at(index).get('multiple_choice_easy').value + + this.getArr().at(index).get('subjective_medium').value + + this.getArr().at(index).get('multiple_choice_medium').value + + this.getArr().at(index).get('subjective_hard').value + + this.getArr().at(index).get('multiple_choice_hard').value + } + + checkValidation(index,data,type,input){ + const level = type.split('_')[type.split('_').length-1] + const isSubjective = type.split('_').includes("subjective") + this.getArr().at(index).get('total_question').setValue(this.sumTotal(index)) + // this.test = this.getArr().value + data.total_random = this.sumTotal(index) + if(this.sumTotal(index) > data.total){ + this.swSV.errText('จำนวนสุ่มเกินกำหนด') + this[type].nativeElement.value = 0 + // this.multiple_choice_hard + this.getArr().at(index).get(type).setValue(0) + this.getArr().at(index).get('total_question').setValue(this.sumTotal(index)) + this.getArr().at(index).get('total_random').setValue(this.sumTotal(index)) + this.test = this.getArr().value + }else if (input > data[(isSubjective? 'auttanai_' : 'porranai_')+level]){ + this.swSV.errText('จำนวนสุ่มเกินกำหนด') + this[type].nativeElement.value = 0 + this.getArr().at(index).get(type).setValue(0) + this.getArr().at(index).get('total_question').setValue(this.sumTotal(index)) + this.getArr().at(index).get('total_random').setValue(this.sumTotal(index)) + this.test = this.getArr().value + } + } + + inputCheck(input,index,data,type){ + this.getArr().at(index).get(type).setValue(+input) + this.getArr().at(index).get('total_random').setValue(this.sumTotal(index)) + this.checkValidation(index,data,type,input) + this.isButtonDisabled.emit(this.checkCondition()) + } + + isNull(form){ + // const form = this.getArr().at(this.index).value + // const form = this.getArr().value + const isEnabledButton = form.total_random > 0 + // const multipleEasy = form.porranai_easy == 0? false : form.multiple_choice_easy == 0 + // const multipleMedium = form.porranai_medium == 0? false : form.multiple_choice_medium == 0 + // const multipleHard = form.porranai_hard == 0? false : form.multiple_choice_hard == 0 + // const subjectiveEasy = form.auttanai_easy == 0? false : form.subjective_easy == 0 + // const subjectiveMedium = form.auttanai_medium == 0? false : form.subjective_medium == 0 + // const subjectiveHard = form.auttanai_hard == 0? false : form.subjective_hard == 0 + // const conditionArray = [multipleEasy,multipleHard,multipleMedium,subjectiveEasy,subjectiveHard,subjectiveMedium] + // const isEnabledButton = conditionArray.some(condition => condition == true) + return isEnabledButton + } + + checkCondition(){ + const form = this.getArr().value + const conditionArray = form.map(data => this.isNull(data)) + const isEnabledButton = conditionArray.some(condition => condition == true) + return !isEnabledButton + } + + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.html b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.html new file mode 100644 index 0000000..ba4d0d9 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.html @@ -0,0 +1,63 @@ +
+
+
+ + {{index+1}}. +
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+ + +
+ +
+ + +
+
+ +
+
+
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.scss b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.spec.ts new file mode 100644 index 0000000..cf6b3a4 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GroupListComponent } from './group-list.component'; + +describe('GroupListComponent', () => { + let component: GroupListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GroupListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GroupListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.ts new file mode 100644 index 0000000..e968a12 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/group/group-list/group-list.component.ts @@ -0,0 +1,72 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, EventEmitter, Output, ElementRef, ViewChild } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { environment } from 'src/environments/environment'; + +@Component({ + selector: 'group-list', + templateUrl: './group-list.component.html', + styleUrls: ['./group-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GroupListComponent implements OnInit { + getArr(){return this.form.get('arr') as FormArray} + @ViewChild('input') input: ElementRef; + @Output() addGroup = new EventEmitter() + @Output() removeGroup = new EventEmitter() + @Input() form: FormGroup; + @Input() index; + @Input() category; + @Input() first; + @Input() wholeForm; + data; + totalQuestion; + table; + column = ['3','4','5','6'] + constructor( + public fb: FormBuilder, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + if(!environment.hideForm) console.log('ข้อมูลแบบชุด : ',this.category) + } + + add(){ + this.addGroup.emit() + } + + remove(){ + this.removeGroup.emit(this.index) + } + + isMoreThan360(event){ + if(event.target.valueAsNumber > 360) return this.form.get('exam_time').setValue(360) + } + + onChange(x){ + const form = this.wholeForm.getRawValue() + const duplicateData = form.random_question_details.find(a => a.question_set_uid == x.question_category_uid) + if(duplicateData){ + this.swSV.errText('มีข้อมูลซ้ำ') + this.remove() + } else { + const auttanai = x.question_category_list_child.reduce((acc,cur) => {return acc+cur.total_question_auttanai},0) + const porranai = x.question_category_list_child.reduce((acc,cur) => {return acc+cur.total_question_porranai},0) + const easy = x.question_category_list_child.reduce((acc,cur) => {return acc + cur.total_question_easy},0) + const medium = x.question_category_list_child.reduce((acc,cur) => {return acc + cur.total_question_medium},0) + const hard = x.question_category_list_child.reduce((acc,cur) => {return acc + cur.total_question_hard},0) + const total_question = x.question_category_list_child.reduce((acc,cur) => {return acc + cur.total_question},0) + this.form.get('total_question_easy').setValue(easy) + this.form.get('total_question_medium').setValue(medium) + this.form.get('total_question_hard').setValue(hard) + this.form.get('total_question_porranai').setValue(porranai) + this.form.get('total_question_auttanai').setValue(auttanai) + this.form.get('total_question').setValue(total_question) + this.form.get('question_set_uid').setValue(x.question_category_uid) + } + } + +} + + diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.html b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.html new file mode 100644 index 0000000..a907b9f --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.html @@ -0,0 +1,85 @@ +
+
+
+ เวลาในการทำข้อสอบ + + นาที +
+
+
+
+
+
+ + {{index+1}}. +
+ +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ +
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.scss b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.spec.ts new file mode 100644 index 0000000..9ddefd9 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeacherComponent } from './teacher.component'; + +describe('TeacherComponent', () => { + let component: TeacherComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TeacherComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TeacherComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.ts b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.ts new file mode 100644 index 0000000..8f9539e --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/form/type/teacher/teacher.component.ts @@ -0,0 +1,141 @@ +import { formatNumber } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +import { FormArray, FormGroup, FormBuilder } from '@angular/forms'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { environment } from 'src/environments/environment'; + +@Component({ + selector: 'teacher', + templateUrl: './teacher.component.html', + styleUrls: ['./teacher.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherComponent implements OnInit { + getArr(){return this.form.get('arr') as FormArray} + @ViewChild('input') input: ElementRef; + @Output() addTeacher = new EventEmitter() + @Output() removeTeacher = new EventEmitter() + @Input() form: FormGroup; + @Input() index; + @Input() category; + @Input() first; + @Input() check; + @Input() subject; + @Output() isButtonDisabled = new EventEmitter() + @ViewChild('porranaiEasy') multiple_choice_easy: ElementRef; + @ViewChild('auttanaiEasy') subjective_easy: ElementRef; + @ViewChild('porranaiMedium') multiple_choice_medium: ElementRef; + @ViewChild('auttanaiMedium') subjective_medium: ElementRef; + @ViewChild('porranaiHard') multiple_choice_hard: ElementRef; + @ViewChild('auttanaiHard') subjective_hard: ElementRef; + instructor; + data; + constructor( + public fb: FormBuilder, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.instructor = this.category[0].instructor_detail + if(!environment.hideForm)console.log('ข้อมูลสุ่มโดยอาจารย์ : ',this.instructor) + } + + add(){ + this.addTeacher.emit() + } + + isMoreThan360(event){ + if(event.target.valueAsNumber > 360) return this.check.get('time_to_complete_exam').setValue(360) + } + + remove(){ + this.removeTeacher.emit(this.index) + } + + // totalQuestion(x){ + // const total_question = this.form.get('num_question').value + // if(x > total_question){ + // this.form.get('total_question').setValue(null) + // this.input.nativeElement.value = null + // this.swSV.errText('ใส่จำนวนคำถามเกินกำหนด') + // } + // if(x <= total_question) return this.form.get('total_question').setValue(+x) + // } + + sumTotal(){ + return this.form.get('subjective_easy').value + + this.form.get('multiple_choice_easy').value + + this.form.get('subjective_medium').value + + this.form.get('multiple_choice_medium').value + + this.form.get('subjective_hard').value + + this.form.get('multiple_choice_hard').value + } + + checkValidation(type,input){ + const data = this.form.getRawValue() + const level = type.split('_')[type.split('_').length-1] + const isSubjective = type.split('_').includes('subjective') + this.form.get('total_question').setValue(this.sumTotal()) + if(this.sumTotal() > data.num_question){ + this.swSV.errText('จำนวนสุ่มเกินกำหนด') + this[type].nativeElement.value = 0 + this.form.get(type).setValue(0) + this.form.get('total_question').setValue(this.sumTotal()) + this.form.get('total_random').setValue(this.sumTotal() == null? 0 : this.sumTotal()) + }else if (input > data[(isSubjective? 'total_question_auttanai_' : 'total_question_porranai_')+level]){ + this.swSV.errText('จำนวนสุ่มเกินกำหนด') + this[type].nativeElement.value = 0 + this.form.get(type).setValue(0) + this.form.get('total_question').setValue(this.sumTotal()) + this.form.get('total_random').setValue(this.sumTotal()) + } + } + + inputCheck(input,type){ + this.form.get(type).setValue(+input) + this.checkValidation(type,input) + this.isButtonDisabled.emit(this.checkCondition()) + } + + selectInsturctor(x){ + const form = this.check.getRawValue() + const dub = form.random_question_details.find(a => a.instructor_uid == x.instructor_uid) + if(dub){ + this.swSV.errText('มีข้อมูลซ้ำ') + this.remove() + } else { + this.form.patchValue(x) + this.form.get('instructor_uid').setValue(x.instructor_uid) + this.form.get('num_question').setValue(x.total_question) + this.form.get('instructor_name').setValue(x.instructor_name_th) + this.form.get('total_question').setValue(0) + this.isButtonDisabled.emit(this.checkCondition()) + } + } + + isNull(form){ + // const form = this.getArr().at(this.index).value + // const form = this.getArr().value + const isEnabledButton = form.total_question > 0 + // const multipleEasy = form.porranai_easy == 0? false : form.multiple_choice_easy == 0 + // const multipleMedium = form.porranai_medium == 0? false : form.multiple_choice_medium == 0 + // const multipleHard = form.porranai_hard == 0? false : form.multiple_choice_hard == 0 + // const subjectiveEasy = form.auttanai_easy == 0? false : form.subjective_easy == 0 + // const subjectiveMedium = form.auttanai_medium == 0? false : form.subjective_medium == 0 + // const subjectiveHard = form.auttanai_hard == 0? false : form.subjective_hard == 0 + // const conditionArray = [multipleEasy,multipleHard,multipleMedium,subjectiveEasy,subjectiveHard,subjectiveMedium] + // const isEnabledButton = conditionArray.some(condition => condition == true) + return isEnabledButton + } + + checkCondition(){ + const form = this.check.get('random_question_details').value + const conditionArray = form.map(data => this.isNull(data)) + const isEnabledButton = conditionArray.some(condition => condition == true) + return !isEnabledButton + } + + +} + + diff --git a/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.html b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.html new file mode 100644 index 0000000..44b0bd4 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.html @@ -0,0 +1,64 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ +
+
ลำดับ {{this.getIndex(i)}} รหัสรอบการสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} จำนวนวิชาที่สร้าง {{x.count_random}}/{{x.count_subject}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}}
+ + + ไม่มีข้อมูล / รอข้อมูลโหลด +
+ +
+
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.scss b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.spec.ts new file mode 100644 index 0000000..53d0b09 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomQuestionsListComponent } from './random-questions-list.component'; + +describe('RandomQuestionsListComponent', () => { + let component: RandomQuestionsListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomQuestionsListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomQuestionsListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.ts b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.ts new file mode 100644 index 0000000..12d72e7 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/list/random-questions-list/random-questions-list.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; +import { Router } from '@angular/router'; +import { Subject } from 'rxjs'; +import { BaseList } from 'src/app/core/base/base-list'; +import { RandomQuestionsService } from 'src/app/core/service/testing-information/random-questions.service'; + +@Component({ + selector: 'random-questions-list', + templateUrl: './random-questions-list.component.html', + styleUrls: ['./random-questions-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsListComponent extends BaseList implements OnInit,OnChanges { + column = [ + '1', + '2', + 'testing_information_code', + 'testing_information_name', + '5', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + 'created_datetime' + ]; + @Input() testingInformationList: any = []; + private reload: boolean; + constructor( + private router: Router, + ) { + super() + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.testingInformationList = this.updateMatTable(this.testingInformationList? this.testingInformationList:[]) + } + + onEdit(id){ + this.router.navigate(['/random-questions/',id]) + } + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.html b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.html new file mode 100644 index 0000000..899077b --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.html @@ -0,0 +1,75 @@ +

กำหนดการสุ่มคำถาม ของวิชา {{data?.subject_name_th}}

+ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ +
+
ลำดับ {{this.getIndex(i)}} รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} ลักษณะการสุ่ม + {{randomType(x.random_type)}} + วิธีการสุ่มข้อสอบ + {{randomQuestionType(x.random_question_type)}} + จำนวน {{x.total_set}} บท / {{x.total_question? x.total_question : 0}} ข้อ รหัสเงื่อนไข {{x.random_question_code? x.random_question_code : '-'}} สถานะ + + + check_circle + + +
+ +
+
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.scss b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.spec.ts new file mode 100644 index 0000000..d1226e3 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomListComponent } from './random-list.component'; + +describe('RandomListComponent', () => { + let component: RandomListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.ts b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.ts new file mode 100644 index 0000000..427b585 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/random-list/random-list/random-list.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { concatMap, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { RandomQuestionsService } from 'src/app/core/service/testing-information/random-questions.service'; + +@Component({ + selector: 'app-random-list', + templateUrl: './random-list.component.html', + styleUrls: ['./random-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomListComponent extends BaseList implements OnInit { + randomList: any = []; + data; + constructor( + public activeRoute: ActivatedRoute, + private cdr: ChangeDetectorRef, + private router: Router, + private randomQuestionSV: RandomQuestionsService, + private swSV: SweetalertService + ) { + super() + } + + ngOnInit(): void { + this.activeRoute.paramMap.pipe( + concatMap((x:any) => this.randomQuestionSV.search('?subject_uid='+x.params.id+'&testing_information_uid='+x.params.testing_uid)), + tap(x => this.data = x[0]), + tap(x => this.randomList = this.updateMatTable(x)) + ).subscribe() + } + + randomType(type){ + if(type == 1) return 'ไม่มีการสลับข้อใด ๆ เลย' + if(type == 2) return 'สลับข้อคำถาม แต่ตัวเลือกไม่สลับ' + if(type == 3) return 'สลับตัวเลือก แต่ข้อคำถามไม่สลับ' + if(type == 4) return 'สลับทุกอย่าง ทั้งข้อคำถามและตัวเลือก' + return '-' + } + + randomQuestionType(type){ + if(type == 1) return 'สุ่มแบบชุด' + if(type == 2) return 'สุ่มแยกบท' + if(type == 3) return 'สุ่มโดยอาจารย์' + return '-' + } + + onView(id){ + this.router.navigate(['random-questions/view',id]) + } +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.html b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.html new file mode 100644 index 0000000..7feded3 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ + +
+ + +
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.scss b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.spec.ts new file mode 100644 index 0000000..4ae4b96 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomQuestionsSearchComponent } from './random-questions-search.component'; + +describe('RandomQuestionsSearchComponent', () => { + let component: RandomQuestionsSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomQuestionsSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomQuestionsSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.ts b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.ts new file mode 100644 index 0000000..b117b87 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/search/random-questions-search/random-questions-search.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; + +@Component({ + selector: 'random-questions-search', + templateUrl: './random-questions-search.component.html', + styleUrls: ['./random-questions-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsSearchComponent implements OnInit { + academicYearList = []; + @Output() search = new EventEmitter() + query={ + testing_information_name:null, + testing_information_code:null, + academic_semester_code:null, + academic_year_code:null + } + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + testing_information_name:null, + testing_information_code:null, + academic_semester_code:null, + academic_year_code:null + } + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.html b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.html new file mode 100644 index 0000000..132f672 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.html @@ -0,0 +1,77 @@ +

กำหนดการสุ่มคำถาม ของรอบสอบ {{data?.testing_information_name}}

+
+
+
+ + +
+
+
+
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ + +
+
ลำดับ {{this.getIndex(i)}} รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} ลักษณะการสุ่ม + {{randomType(x.random_type)}} + วิธีการสุ่มข้อสอบ + {{randomQuestionType(x.random_question_type)}} + จำนวน {{x.total_set}} บท / {{x.total_question? x.total_question : 0}} ข้อ รหัสเงื่อนไข {{x.random_question_code? x.random_question_code : '-'}} สถานะการสุ่มคำถาม + + check_circle + + - +
+ +
+
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.scss b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.spec.ts new file mode 100644 index 0000000..1416ab9 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { RandomQuestionsSubjectListComponent } from './random-questions-subject-list.component'; + +describe('RandomQuestionsSubjectListComponent', () => { + let component: RandomQuestionsSubjectListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ RandomQuestionsSubjectListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(RandomQuestionsSubjectListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.ts b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.ts new file mode 100644 index 0000000..c40061e --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component.ts @@ -0,0 +1,99 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, OnChanges, AfterViewInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { concatMap, filter, switchMap, tap } from 'rxjs/operators'; +import { BaseSubList } from 'src/app/core/base/base-sub-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { RandomQuestionsService } from 'src/app/core/service/testing-information/random-questions.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-random-questions-subject-list', + templateUrl: './random-questions-subject-list.component.html', + styleUrls: ['./random-questions-subject-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsSubjectListComponent extends BaseSubList implements OnInit,AfterViewInit { + column = ['1','2','3','4','5','6','7','8','9'] + subjectList; + data; + constructor( + public activeRoute: ActivatedRoute, + private testingInfoSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private router: Router, + private randomQuestionSV: RandomQuestionsService, + private swSV: SweetalertService + ) { + super(activeRoute) + } + + ngOnInit(): void { + + } + + ngAfterViewInit(){ + this.testingInfoSV.get(this.id).pipe( + tap(x => this.data = x), + tap((x:any) => this.subjectList = x.testing_subjects), + tap(x => this.subjectList = this.updateMatTable(this.subjectList? this.subjectList:[])), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.subjectList.filter = filterValue.trim().toLowerCase(); + } + + onEdit(id){ + this.router.navigate(['random-questions/setting',id,this.id]) + } + + onView(id){ + let data; + this.randomQuestionSV.search('?subject_uid='+id+'&testing_information_uid='+this.data.testing_information_uid).pipe( + tap(x => data = x[0]), + tap(x => this.router.navigate(['random-questions/view',data.random_question_uid])) + ).subscribe() + } + + randomList(id){ + this.router.navigate(['random-questions/random',id,this.id]) + } + + onDelete(id){ + let data; + this.randomQuestionSV.search('?subject_uid='+id+'&testing_information_uid='+this.data.testing_information_uid).pipe( + tap(x => data = x[0]), + tap(x => this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.randomQuestionSV.deleteData(data.random_question_uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.testingInfoSV.get(this.id).subscribe((x:any) => { + this.subjectList.data = x.testing_subjects + this.cdr.detectChanges() + })), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe()), + ).subscribe() + } + + randomType(type){ + if(type == 1) return 'ไม่มีการสลับข้อใด ๆ เลย' + if(type == 2) return 'สลับข้อคำถาม แต่ตัวเลือกไม่สลับ' + if(type == 3) return 'สลับตัวเลือก แต่ข้อคำถามไม่สลับ' + if(type == 4) return 'สลับทุกอย่าง ทั้งข้อคำถามและตัวเลือก' + return '-' + } + + randomQuestionType(type){ + if(type == 1) return 'สุ่มแบบชุด' + if(type == 2) return 'สุ่มแยกบท' + if(type == 3) return 'สุ่มโดยอาจารย์' + return '-' + } + +} diff --git a/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.html b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.html new file mode 100644 index 0000000..09859dd --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.html @@ -0,0 +1,235 @@ + +

กำหนดการสุ่มคำถาม

+
+
+
+ + +
+ +
+ + +
+ +
+ + + + +
+
+ +

ลักษณะการสุ่ม

+
+ + ไม่มีการสลับข้อใด ๆ เลย + สลับข้อคำถาม แต่ตัวเลือกไม่สลับ + สลับตัวเลือก แต่ข้อคำถามไม่สลับ + สลับทุกอย่าง ทั้งข้อคำถามและตัวเลือก + +
+ +

วิธีการสุ่มข้อสอบ

+
+ + สุ่มแบบชุด + สุ่มแยกบท + สุ่มโดยอาจารย์ + +
+
+
+
+
+ เวลาในการทำข้อสอบ + + นาที +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อบท {{x.question_set_name}} จำนวนข้อ {{x.total_question}} ปรนัย + {{x.total_question_porranai}} + อัตนัย + {{x.total_question_auttanai}} + เวลาในการทำข้อสอบ + {{x.exam_time}} +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อบท {{x.question_sub_set_name}} จำนวนข้อ {{x.total_question? x.total_question : '0'}} ระดับง่าย +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
ระดับปานกลาง +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
ระดับยาก +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่ออาจารย์ {{x.instructor_name}} จำนวนข้อ {{x.total_question}} ระดับง่าย +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
ระดับปานกลาง +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
ระดับยาก +
+
+ ปรนัย + +   +
+
+ อัตนัย + +   +
+
+
+
+ +
+
+
+ + +
+
diff --git a/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.scss b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.spec.ts b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.spec.ts new file mode 100644 index 0000000..f644b0a --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewComponent } from './view.component'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.ts b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.ts new file mode 100644 index 0000000..e052c6c --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/presenter/view/view/view.component.ts @@ -0,0 +1,58 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { filter, switchMap, tap } from 'rxjs/operators'; +import { sortByProperty } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { RandomQuestionsService } from 'src/app/core/service/testing-information/random-questions.service'; + +@Component({ + selector: 'app-view', + templateUrl: './view.component.html', + styleUrls: ['./view.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ViewComponent extends BaseFormUid implements OnInit { + data; + dataTable; + column = ['1','2','3','4','5','6'] + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private randomQuestionSV: RandomQuestionsService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.randomQuestionSV.get(this.id).pipe( + tap((x:any) => this.data = x), + tap((x:any) => this.dataTable = x.random_question_details.sort(sortByProperty('row_order'))), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + cancel(){ + this.location.back() + } + + onDelete(){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.randomQuestionSV.deleteData(this.id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.location.back()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/exam-setting/random-questions/random-questions.module.ts b/src/app/feature/exam-setting/random-questions/random-questions.module.ts new file mode 100644 index 0000000..a3cde3b --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/random-questions.module.ts @@ -0,0 +1,69 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {RouterModule, Routes} from '@angular/router'; +import {MatTabsModule} from '@angular/material/tabs'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RandomQuestionsRouter } from './router/router'; +import { RandomQuestionsContainer } from './container/random-questions/random-questions.container'; +import { RandomQuestionsSearchComponent } from './presenter/search/random-questions-search/random-questions-search.component'; +import { RandomQuestionsListComponent } from './presenter/list/random-questions-list/random-questions-list.component'; +import { RandomQuestionsSubjectListComponent } from './presenter/subject-list/random-questions-subject-list/random-questions-subject-list.component'; +import { RandomQuestionsFormContainer } from './presenter/form/container/random-questions-form/random-questions-form.container'; +import { GroupListComponent } from './presenter/form/type/group/group-list/group-list.component'; +import { CategoryListComponent } from './presenter/form/type/category/category-list/category-list.component'; +import { ViewComponent } from './presenter/view/view/view.component'; +import { TeacherComponent } from './presenter/form/type/teacher/teacher.component'; +import { RandomListComponent } from './presenter/random-list/random-list/random-list.component'; + + +const routes: Routes = [ + { + path: '', + component: RandomQuestionsRouter, + children: [ + { + path: '', + component: RandomQuestionsContainer + }, + { + path: ':id', + component: RandomQuestionsSubjectListComponent + }, + { + path: 'setting/:id/:uid', + component: RandomQuestionsFormContainer + }, + { + path: 'view/:id', + component: ViewComponent + }, + { + path: 'random/:id/:testing_uid', + component: RandomListComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + RandomQuestionsRouter, + RandomQuestionsContainer, + RandomQuestionsSearchComponent, + RandomQuestionsListComponent, + RandomQuestionsSubjectListComponent, + RandomQuestionsFormContainer, + GroupListComponent, + CategoryListComponent, + ViewComponent, + TeacherComponent, + RandomListComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatTabsModule + ] +}) +export class RandomQuestionsModule { } diff --git a/src/app/feature/exam-setting/random-questions/router/router.ts b/src/app/feature/exam-setting/random-questions/router/router.ts new file mode 100644 index 0000000..715ba39 --- /dev/null +++ b/src/app/feature/exam-setting/random-questions/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-random-questions-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class RandomQuestionsRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.html b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.html new file mode 100644 index 0000000..138fc28 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.html @@ -0,0 +1,10 @@ + + + + + diff --git a/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.scss b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.spec.ts b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.spec.ts new file mode 100644 index 0000000..f91ac09 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationDateContainer } from './extend-information-date.container'; + +describe('ExtendInformationDateContainer', () => { + let component: ExtendInformationDateContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationDateContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationDateContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.ts b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.ts new file mode 100644 index 0000000..da999c8 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/container/extend-information-date/extend-information-date.container.ts @@ -0,0 +1,66 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {MatDialog} from '@angular/material/dialog'; +import { + DialogChangeSeatComponent +} from '../../../../candidate-list/candidate-list/presenter/dialog/dialog-change-seat/dialog-change-seat.component'; +import {tap} from 'rxjs/operators'; +import { + DialogExtendInformationDateFormComponent +} from '../../presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component'; + +@Component({ + selector: 'app-extend-information-date', + templateUrl: './extend-information-date.container.html', + styleUrls: ['./extend-information-date.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationDateContainer implements OnInit { + + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private dialog: MatDialog, + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getAll(); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } + + edit(id){ + this.router.navigate(['extend-information-date/edit', id]); + } + + openDialog(id){ + const dialogRef = this.dialog.open(DialogExtendInformationDateFormComponent, { + width: '500px', + height: '300px', + data: { + id, + state : 'edit', + } + }); + dialogRef.afterClosed().pipe( + tap(x => { + console.log(x) + }) + ).subscribe(); + } + + // edit(id){ + // this.router.navigate(['extend-information-date/edit', id]); + // } + +} diff --git a/src/app/feature/extend-information/extend-information-date/extend-information-date.module.ts b/src/app/feature/extend-information/extend-information-date/extend-information-date.module.ts new file mode 100644 index 0000000..e54511d --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/extend-information-date.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ExtendInformationDateRouter } from './router/extend-information-date-router'; +import { ExtendInformationDateContainer } from './container/extend-information-date/extend-information-date.container'; +import { ExtendInformationDateFormComponent } from './presenter/form/extend-information-date-form/extend-information-date-form.component'; +import { ExtendInformationDateListComponent } from './presenter/list/extend-information-date-list/extend-information-date-list.component'; +import { ExtendInformationDateSearchComponent } from './presenter/search/extend-information-date-search/extend-information-date-search.component'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { DialogExtendInformationDateFormComponent } from './presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component'; + +const routes: Routes = [ + { + path: '', + component: ExtendInformationDateRouter, + children: [ + { + path: '', + component: ExtendInformationDateContainer + }, + { + path: 'add', + component: ExtendInformationDateFormComponent + }, + { + path: 'edit/:id', + component: ExtendInformationDateFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + ExtendInformationDateRouter, + ExtendInformationDateContainer, + ExtendInformationDateFormComponent, + ExtendInformationDateListComponent, + ExtendInformationDateSearchComponent, + DialogExtendInformationDateFormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ExtendInformationDateModule { } diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.html b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.html new file mode 100644 index 0000000..27ac7b1 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.html @@ -0,0 +1,43 @@ +
+
+
+ + +
+ +
+
+
+ + + + + + +
+
+ + + + + + +
+
+
+ +
+ + +
+
+
+ + + + diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.scss b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.spec.ts b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.spec.ts new file mode 100644 index 0000000..0c335ed --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogExtendInformationDateFormComponent } from './dialog-extend-information-date-form.component'; + +describe('DialogExtendInformationDateFormComponent', () => { + let component: DialogExtendInformationDateFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogExtendInformationDateFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogExtendInformationDateFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.ts b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.ts new file mode 100644 index 0000000..256dc79 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/dialog-extend-information-date-form/dialog-extend-information-date-form.component.ts @@ -0,0 +1,472 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Inject} from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {MatTableDataSource} from '@angular/material/table'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import { + TestingInformationService +} from '../../../../../../core/service/testing-information/testing-information.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {catchError, tap} from 'rxjs/operators'; +import {Subject, throwError} from 'rxjs'; +import { + SetExamInformationDialogComponent +} from '../../../../../set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component'; + +@Component({ + selector: 'app-dialog-extend-information-date-form', + templateUrl: './dialog-extend-information-date-form.component.html', + styleUrls: ['./dialog-extend-information-date-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogExtendInformationDateFormComponent extends BaseForm implements OnInit { + + setroomcenterForm: FormGroup; + subjectList: any = []; + subjectList2: any = []; + subjectList3: any = []; + dataSource3 = new MatTableDataSource(); + displayedColumns3: string[] = ['1', '2', '3', '5', '6', '7']; + testingInfoData; + private curSub: any; + private curSub2: any; + private curSub3: any; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + testing_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + + constructor( + private academicSemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.setroomcenterForm = this.formBuilder.group({ + branch_name_th: null, + branch_uid: null, + testing_center_uid: null, + testing_field_name_th: null, + testing_field_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + is_random_seat: null, + }); + } + + block_days(blockdays?) { + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?) { + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?) { + return this.formBuilder.group({ + status_id: null, + is_open: data?.is_open, + print_start_time: data?.print_start_time, + print_end_time: data?.print_end_time, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?) { + return this.formBuilder.group({ + is_new: data?.is_new, + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?) { + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?) { + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + // MainForm + setexamform: FormGroup; + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + switch (this.data.state) { + case 'edit': + this.TestInformationSV.get(this.data.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + const res: any = x; + console.log(res) + this.getBranchList(res) + }), + tap(x => { + form5.clear(); + form3.clear(); + form4.clear(); + form2.clear(); + form.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + }), + tap(x => this.add3Edit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + } + } + + checkAcaSemandAcaYear(data) { + const returndata = { + academic_year_uid: null, + academic_semester_uid: null + }; + const result = new Subject(); + this.academicSemSV.query(`?academic_semester_code=${data.academic_semester_code}`).subscribe( + res => { + returndata.academic_semester_uid = res[0].academic_semester_uid + this.academicYearSV.query(`?academic_year_code=${data.academic_year_code}`).subscribe( + res2 => { + returndata.academic_year_uid = res2[0].academic_year_uid + result.next(returndata); + } + ); + } + ); + return result.asObservable(); + } + + async getBranchList(data) { + await this.checkAcaSemandAcaYear(data).subscribe( + res => { + if (res.academic_year_uid != null && res.academic_semester_uid != null) { + this.testcenterSV.query(`?academic_year_uid=${res.academic_year_uid}&academic_semester_uid=${res.academic_semester_uid}`).pipe( + // tap(x => this.subjectList = x), + tap(x => this.subjectList = this.clearBranchlist(x)), + ).subscribe(); + } + } + ); + } + + clearBranchlist(arr) { + const resArr = []; + arr.filter(function (item: any): any { + const i = resArr.findIndex(x => (x.branch_name_th === item.branch_name_th)); + if (i <= -1) { + resArr.push(item); + } + return null; + }); + return resArr + } + + add3Edit(data) { + console.log(data) + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + addCalendaEdit(x) { + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x) { + console.log(x.testing_periods); + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + this.sectionsFakeFalse[foundIndex].print_start_time = x.testing_periods[i].print_start_time; + this.sectionsFakeFalse[foundIndex].print_end_time = x.testing_periods[i].print_end_time; + this.sectionsFakeFalse[foundIndex].testing_period_uid = x.testing_periods[i].testing_period_uid; + this.sectionsFakeFalse[foundIndex].testing_information_uid = x.testing_periods[i].testing_information_uid; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x) { + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + } + } + + addSubject(x) { + const form = this.setexamform.get('testing_subjects') as FormArray; + if (x.testing_subjects != null) { + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + } + + save() { + switch (this.data.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back() { + this.location.back() + } + + cancel() { + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.html b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.html new file mode 100644 index 0000000..3168060 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.html @@ -0,0 +1 @@ +

extend-information-date-form works!

diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.scss b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.spec.ts b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.spec.ts new file mode 100644 index 0000000..97c97ed --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationDateFormComponent } from './extend-information-date-form.component'; + +describe('ExtendInformationDateFormComponent', () => { + let component: ExtendInformationDateFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationDateFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationDateFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.ts b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.ts new file mode 100644 index 0000000..1d12bd1 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/form/extend-information-date-form/extend-information-date-form.component.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-extend-information-date-form', + templateUrl: './extend-information-date-form.component.html', + styleUrls: ['./extend-information-date-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationDateFormComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.html b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.html new file mode 100644 index 0000000..4f68c0c --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.html @@ -0,0 +1,88 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.scss b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.spec.ts b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.spec.ts new file mode 100644 index 0000000..c20fd0e --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationDateListComponent } from './extend-information-date-list.component'; + +describe('ExtendInformationDateListComponent', () => { + let component: ExtendInformationDateListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationDateListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationDateListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.ts b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.ts new file mode 100644 index 0000000..dd51d5a --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/list/extend-information-date-list/extend-information-date-list.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-extend-information-date-list', + templateUrl: './extend-information-date-list.component.html', + styleUrls: ['./extend-information-date-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationDateListComponent extends BaseList implements OnInit, OnChanges { + + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + 'is_open', + 'created_datetime', + '7' + ]; + reload: boolean; + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + this.subjectList.data = this.subjectList.data + .filter((x) => { + return x.is_open === true; + }); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.html b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.scss b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.spec.ts b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.spec.ts new file mode 100644 index 0000000..3f3f1b4 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationDateSearchComponent } from './extend-information-date-search.component'; + +describe('ExtendInformationDateSearchComponent', () => { + let component: ExtendInformationDateSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationDateSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationDateSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.ts b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.ts new file mode 100644 index 0000000..50d7fb7 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/presenter/search/extend-information-date-search/extend-information-date-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-extend-information-date-search', + templateUrl: './extend-information-date-search.component.html', + styleUrls: ['./extend-information-date-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationDateSearchComponent implements OnInit { + + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/extend-information/extend-information-date/router/extend-information-date-router.ts b/src/app/feature/extend-information/extend-information-date/router/extend-information-date-router.ts new file mode 100644 index 0000000..ececf48 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-date/router/extend-information-date-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationDateRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.html b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.html new file mode 100644 index 0000000..c4244d8 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.html @@ -0,0 +1,11 @@ + + + + + + diff --git a/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.scss b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.spec.ts b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.spec.ts new file mode 100644 index 0000000..c0a592b --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationRoomContainer } from './extend-information-room.container'; + +describe('ExtendInformationRoomContainer', () => { + let component: ExtendInformationRoomContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationRoomContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationRoomContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.ts b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.ts new file mode 100644 index 0000000..3e6da7b --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/container/extend-information-room/extend-information-room.container.ts @@ -0,0 +1,38 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {MatDialog} from '@angular/material/dialog'; +import {Observable} from 'rxjs'; + +@Component({ + selector: 'app-extend-information-room', + templateUrl: './extend-information-room.container.html', + styleUrls: ['./extend-information-room.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationRoomContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private dialog: MatDialog, + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getAll(); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } + + edit(id){ + this.router.navigate(['extend-information-room/edit', id]); + } + +} diff --git a/src/app/feature/extend-information/extend-information-room/extend-information-room.module.ts b/src/app/feature/extend-information/extend-information-room/extend-information-room.module.ts new file mode 100644 index 0000000..cb61d03 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/extend-information-room.module.ts @@ -0,0 +1,42 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ExtendInformationRoomRouter } from './router/extend-information-room-router'; +import { ExtendInformationRoomContainer } from './container/extend-information-room/extend-information-room.container'; +import { ExtendInformationRoomFormComponent } from './presenter/form/extend-information-room-form/extend-information-room-form.component'; +import { ExtendInformationRoomListComponent } from './presenter/list/extend-information-room-list/extend-information-room-list.component'; +import { ExtendInformationRoomSearchComponent } from './presenter/search/extend-information-room-search/extend-information-room-search.component'; +import {RouterModule, Routes} from '@angular/router'; +import {SharedModule} from '../../../shared/shared.module'; + +const routes: Routes = [ + { + path: '', + component: ExtendInformationRoomRouter, + children: [ + { + path: '', + component: ExtendInformationRoomContainer + }, + { + path: 'edit/:id', + component: ExtendInformationRoomFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + ExtendInformationRoomRouter, + ExtendInformationRoomContainer, + ExtendInformationRoomFormComponent, + ExtendInformationRoomListComponent, + ExtendInformationRoomSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ExtendInformationRoomModule { } diff --git a/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.html b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.html new file mode 100644 index 0000000..4d2f44b --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.html @@ -0,0 +1,129 @@ +
+
+

กำหนดห้องสอบของรอบสอบ {{testingInfoData?.testing_information_name}}

+
+
+ + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject2.testing_field_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{subject3.testing_room_name_th}} + + +
+ +
+ +
+
+
+ + +
+
+
+
+ +

แสดงรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{element.branch_name_th}} สนามสอบ {{element.testing_field_name_th}} ห้องสอบ {{element.testing_room_name_th}} สุ่มที่นั่งสอบ + + + จัดการที่นั่งสอบ* + + + +
+ +
+
ไม่มีข้อมูล
+
+
+
+
+ + +
+
+
+  {{setexamform.getRawValue() | json}}
+
diff --git a/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.scss b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.spec.ts b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.spec.ts new file mode 100644 index 0000000..9e4dc56 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationRoomFormComponent } from './extend-information-room-form.component'; + +describe('ExtendInformationRoomFormComponent', () => { + let component: ExtendInformationRoomFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationRoomFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationRoomFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.ts b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.ts new file mode 100644 index 0000000..561da0a --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/form/extend-information-room-form/extend-information-room-form.component.ts @@ -0,0 +1,651 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {MatTableDataSource} from '@angular/material/table'; +import {AcademicSemesterService} from '../../../../../../core/service/settings/academic-semester.service'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../../core/service/testing-information/testing-information.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {catchError, tap} from 'rxjs/operators'; +import {Subject, throwError} from 'rxjs'; +import { + SetExamInformationDialogComponent +} from '../../../../../set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component'; + +@Component({ + selector: 'app-extend-information-room-form', + templateUrl: './extend-information-room-form.component.html', + styleUrls: ['./extend-information-room-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationRoomFormComponent extends BaseForm implements OnInit{ + + setroomcenterForm: FormGroup; + subjectList: any = []; + subjectList2: any = []; + subjectList3: any = []; + dataSource3 = new MatTableDataSource(); + displayedColumns3: string[] = ['1', '2', '3', '5', '6', '7']; + testingInfoData; + private curSub: any; + private curSub2: any; + private curSub3: any; + sectionsFakeFalse = [ + { + status_id: 1, + testing_center_period_uid: null, + period_id: 1, + is_check: false, + start_time: '09:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 2, + is_check: false, + start_time: '12:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 3, + is_check: false, + start_time: '15:00' + }, + { + status_id: 1, + testing_center_period_uid: null, + period_id: 4, + is_check: false, + start_time: '18:00' + } + ]; + constructor( + private academicSemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + start_datetime: null, + end_datetime: null, + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_open: null, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.setroomcenterForm = this.formBuilder.group({ + branch_name_th: null, + branch_uid: null, + testing_center_uid: null, + testing_field_name_th: null, + testing_field_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + is_random_seat: null, + }); + } + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + is_new: data?.is_new, + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + // MainForm + setexamform: FormGroup; + + ngOnInit(): void { + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList = this.clearBranchList(x)), + // ).subscribe(); + // await this.testingFieldSV.getAll().pipe( + // tap(x => this.subjectList2 = x), + // ).subscribe(); + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList3 = x), + // ).subscribe(); + // this.testcenterSV.getAll().pipe( + // tap(x => this.subjectList3 = x), + // ).subscribe(); + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => this.testingInfoData = x), + tap(x => { + const res: any = x; + console.log(res) + this.getBranchList(res) + }), + tap(x => { + form5.clear(); + form3.clear(); + form2.clear(); + form.clear(); + }), + tap(x => { + const data: any = x; + this.setexamform.patchValue(data); + }), + tap(x => this.add3Edit(x)), + tap(x => this.addPeriodEdit(x)), + tap(x => this.addCalendaEdit(x)), + tap(x => this.addSubject(x)), + tap(x => this.addEditBlockadd(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + } + } + + checkAcaSemandAcaYear(data){ + const returndata = { + academic_year_uid: null, + academic_semester_uid: null + }; + const result = new Subject(); + this.academicSemSV.query(`?academic_semester_code=${data.academic_semester_code}`).subscribe( + res => { + returndata.academic_semester_uid = res[0].academic_semester_uid + this.academicYearSV.query(`?academic_year_code=${data.academic_year_code}`).subscribe( + res2 => { + returndata.academic_year_uid = res2[0].academic_year_uid + result.next(returndata); + } + ); + } + ); + return result.asObservable(); + } + + async getBranchList(data){ + await this.checkAcaSemandAcaYear(data).subscribe( + res => { + if (res.academic_year_uid != null && res.academic_semester_uid != null){ + this.testcenterSV.query(`?academic_year_uid=${res.academic_year_uid}&academic_semester_uid=${res.academic_semester_uid}`).pipe( + // tap(x => this.subjectList = x), + tap(x => this.subjectList = this.clearBranchlist(x)), + ).subscribe(); + } + } + ); + } + + clearBranchlist(arr){ + const resArr = []; + arr.filter(function(item: any): any{ + const i = resArr.findIndex(x => (x.branch_name_th === item.branch_name_th)); + if (i <= -1){ + resArr.push(item); + } + return null; + }); + return resArr + } + + add3Edit(data){ + console.log(data) + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + add3EditReserve(data){ + console.log(data) + const form = this.setexamform.get('testing_rooms') as FormArray; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = formatDate(x.testing_calendars[i].end_datetime, 'yyyy-MM-dd', 'en-US'); + x.testing_calendars[i].start_datetime = formatDate(x.testing_calendars[i].start_datetime, 'yyyy-MM-dd', 'en-US'); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + } + + addPeriodEdit(x){ + const form = this.setexamform.get('testing_periods') as FormArray; + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + } + } + + addSubject(x){ + const form = this.setexamform.get('testing_subjects') as FormArray; + if (x.testing_subjects != null){ + for (let i = 0; i < x.testing_subjects.length; i++) { + form.push(this.testing_subjects(x.testing_subjects[i])); + } + } + } + + add3(){ + const form = this.setroomcenterForm.getRawValue(); + const form3 = this.setexamform.get('testing_rooms') as FormArray; + console.log(form) + console.log(form3.getRawValue()) + const everyResult = form3.getRawValue().some((member) => { + return member.testing_center_uid === form.testing_center_uid + }) + console.log(everyResult) + if (everyResult){ + return this.swSV.errText('มีห้องสอบซ้ำ') + } + // this.setupdata.testing_auth_name = form.testing_auth_name; + form.is_new = true; + form3.push(this.testing_rooms(form)); + const table = form3.getRawValue(); + this.dataSource3.data = table; + const index = table.findIndex( + member => member.testing_center_uid === form.testing_center_uid && + member.branch_uid === form.branch_uid && + member.testing_field_uid === form.testing_field_uid + ); + if (index !== -1){ + this.setroomcenterForm.reset(); + this.openDialogexam(form.testing_center_uid , index) + }else { + this.swSV.errText('ไม่พบห้องสอบกรุณาลบสร้างห้องสอบใหม่') + } + } + + setFieldname(uid){ + const branch = this.subjectList.filter((x) => { + return x.branch_uid === uid; + }); + this.setroomcenterForm.get('branch_name_th').setValue(branch[0].branch_name_th); + this.testingFieldSV.getByBrandID(uid).pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe(); + } + + setRoomname(uid){ + const branch = this.subjectList2.filter((x) => { + return x.testing_field_uid === uid; + }); + this.setroomcenterForm.get('testing_field_name_th').setValue(branch[0].testing_field_name_th); + this.testcenterSV.getByFiledID(uid).pipe( + tap(x => console.log(x)), + tap(x => this.subjectList3 = x), + ).subscribe(); + } + + setRoomnameth(uid){ + const branch = this.subjectList3.filter((x) => { + return x.testing_center_uid === uid; + }); + this.setroomcenterForm.get('testing_room_name_th').setValue(branch[0].testing_room_name_th); + } + + displayBranchname(uid){ + if (uid && this.subjectList) return this.subjectList.find(x => x.branch_uid === uid)?.branch_name_th + if (uid && !this.subjectList) return this.curSub?.branch_name_th + } + + displayFieldname(uid){ + if (uid && this.subjectList2) return this.subjectList2.find(x => x.testing_field_uid === uid)?.testing_field_name_th + if (uid && !this.subjectList2) return this.curSub2?.testing_field_name_th + } + + displayRoomname(uid){ + if (uid && this.subjectList3) return this.subjectList3.find(x => x.testing_center_uid === uid)?.testing_room_name_th + if (uid && !this.subjectList3) return this.curSub3?.testing_room_name_th + } + + selectionValue(data, i){ + switch (this.state) { + case 'edit': + let israndom = true; + if (data.is_random_seat === true){ + israndom = false; + }else if (data.is_random_seat === false){ + israndom = true; + } + const form = this.setexamform.get('testing_rooms') as FormArray; + form.at(i).get('is_random_seat').setValue(israndom); + const table = form.getRawValue(); + this.dataSource3.data = table; + break; + } + } + + openDialogexam(id:any,index:any){ + const form = this.setexamform.get('testing_rooms') as FormArray; + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + const centerList = form.getRawValue(); + switch (this.state) { + case 'edit': + console.log(centerList[index]) + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1200px', + height: '700px', + data: { + id, + centerList : centerList[index], + subjectlist : subjectForm.getRawValue(), + state : this.state, + } + }); + dialogRefedit.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const testseat = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(testseat); + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + this.cdRef.detectChanges(); + } + ); + break; + case 'add': + const dialogRefadd = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + subjectlist : subjectForm.getRawValue(), + state : this.state, + } + }); + dialogRefadd.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let i = 0; i < testseat.testing_seat.length; i++) { + formArray.push(testseatdata.get('testing_seat').controls[i]); + } + this.cdRef.detectChanges(); + } + ); + break; + } + } + + removeArray3(i){ + const form = this.setexamform.get('testing_rooms') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + save(){ + switch (this.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + back(){ + this.location.back() + } + + onView(id,index){ + const form = this.setexamform.get('testing_rooms') as FormArray; + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + const centerList = form.getRawValue(); + switch (this.state) { + case 'edit': + console.log(centerList[index]) + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1200px', + height: '700px', + data: { + id, + centerList : centerList[index], + subjectlist : subjectForm.getRawValue(), + state : 'view', + } + }); + break; + } + } + +} diff --git a/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.html b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.html new file mode 100644 index 0000000..ae3786a --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.html @@ -0,0 +1,88 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + + + +
+
วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.scss b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.spec.ts b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.spec.ts new file mode 100644 index 0000000..94197e0 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationRoomListComponent } from './extend-information-room-list.component'; + +describe('ExtendInformationRoomListComponent', () => { + let component: ExtendInformationRoomListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationRoomListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationRoomListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.ts b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.ts new file mode 100644 index 0000000..da34299 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/list/extend-information-room-list/extend-information-room-list.component.ts @@ -0,0 +1,70 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {OBJECT} from '../../../../../../core/enum/role'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-extend-information-room-list', + templateUrl: './extend-information-room-list.component.html', + styleUrls: ['./extend-information-room-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationRoomListComponent extends BaseList implements OnInit, OnChanges { + + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'created_by', + 'is_open', + 'created_datetime', + '7' + ]; + reload: boolean; + + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + this.subjectList.data = this.subjectList.data + .filter((x) => { + return x.is_open === true; + }); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.html b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.scss b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.spec.ts b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.spec.ts new file mode 100644 index 0000000..d0f32f8 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExtendInformationRoomSearchComponent } from './extend-information-room-search.component'; + +describe('ExtendInformationRoomSearchComponent', () => { + let component: ExtendInformationRoomSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExtendInformationRoomSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExtendInformationRoomSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.ts b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.ts new file mode 100644 index 0000000..57cbff9 --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/presenter/search/extend-information-room-search/extend-information-room-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-extend-information-room-search', + templateUrl: './extend-information-room-search.component.html', + styleUrls: ['./extend-information-room-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationRoomSearchComponent implements OnInit { + + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/extend-information/extend-information-room/router/extend-information-room-router.ts b/src/app/feature/extend-information/extend-information-room/router/extend-information-room-router.ts new file mode 100644 index 0000000..856753f --- /dev/null +++ b/src/app/feature/extend-information/extend-information-room/router/extend-information-room-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExtendInformationRoomRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/manage-payment/confirm/confirm.module.ts b/src/app/feature/manage-payment/confirm/confirm.module.ts new file mode 100644 index 0000000..44aeb8b --- /dev/null +++ b/src/app/feature/manage-payment/confirm/confirm.module.ts @@ -0,0 +1,34 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ConfirmRouter } from './router/router'; +import { ConfirmContainer } from './container/confirm/confirm.container'; +import { ListComponent } from './presenter/list/list.component'; + +const routes: Routes = [ + { + path: '', + component: ConfirmRouter, + children: [ + { + path: '', + component: ConfirmContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ConfirmRouter, + ConfirmContainer, + ListComponent, + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ConfirmModule { } diff --git a/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.html b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.html new file mode 100644 index 0000000..61c55fc --- /dev/null +++ b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.html @@ -0,0 +1,6 @@ + + diff --git a/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.scss b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.spec.ts b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.spec.ts new file mode 100644 index 0000000..2a1e6e6 --- /dev/null +++ b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfirmContainer } from './confirm.container'; + +describe('ConfirmContainer', () => { + let component: ConfirmContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfirmContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfirmContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.ts b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.ts new file mode 100644 index 0000000..5c0ce6a --- /dev/null +++ b/src/app/feature/manage-payment/confirm/container/confirm/confirm.container.ts @@ -0,0 +1,72 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Observable, throwError } from 'rxjs'; +import { tap, catchError, filter, map, switchMap } from 'rxjs/operators'; +import { StudentPaymentService } from 'src/app/core/service/student-payment/student-payment.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-confirm', + templateUrl: './confirm.container.html', + styleUrls: ['./confirm.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ConfirmContainer implements OnInit { + confirmList$ = new Observable() + constructor( + private studentPaymentSV: StudentPaymentService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.getData() + } + + getData(){ + return this.confirmList$ = this.studentPaymentSV.getAll().pipe( + map((x:any) => x.filter(a => a.is_approve == null)) + ) + } + + confirm(data){ + if(data.length == 0){ + this.swSV.errText('กรุณาเลือกข้อมูล') + } else { + this.studentPaymentSV.confirmPayment(data).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.getData()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + } + + deletePayment(data){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.studentPaymentSV.deletePayment(data).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.getData()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + + search(date){ + const newDate = formatDate(date, 'yyyy-MM-dd', 'en-US') + if(date) return this.confirmList$ = this.studentPaymentSV.getByDate(newDate).pipe( + map((x:any) => x.filter(a => a.is_approve == null)) + ) + } + +} diff --git a/src/app/feature/manage-payment/confirm/presenter/list/list.component.html b/src/app/feature/manage-payment/confirm/presenter/list/list.component.html new file mode 100644 index 0000000..b3f880d --- /dev/null +++ b/src/app/feature/manage-payment/confirm/presenter/list/list.component.html @@ -0,0 +1,75 @@ +

ยืนยันรายการชำระเงิน

+
+
+
+ + + + + + +
+
+
+
+
+
+

รายการนำเข้า

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อ-นามสกุล {{x.payer_name}} ref1 {{x.ref1}} ref2 {{x.ref2}} จำนวนเงิน {{x.transaction_amount}} วันที่ชำระเงิน {{x.transaction_date | thaidate}} + + + + + +
+ +
+
+ + +
+
+ + + diff --git a/src/app/feature/manage-payment/confirm/presenter/list/list.component.scss b/src/app/feature/manage-payment/confirm/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-payment/confirm/presenter/list/list.component.spec.ts b/src/app/feature/manage-payment/confirm/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/manage-payment/confirm/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-payment/confirm/presenter/list/list.component.ts b/src/app/feature/manage-payment/confirm/presenter/list/list.component.ts new file mode 100644 index 0000000..2c6d142 --- /dev/null +++ b/src/app/feature/manage-payment/confirm/presenter/list/list.component.ts @@ -0,0 +1,76 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter } from '@angular/core'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { StudentPaymentService } from 'src/app/core/service/student-payment/student-payment.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { PeriodicElement } from 'src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() confirmList: any = []; + @Output() delete = new EventEmitter() + @Output() confirm = new EventEmitter() + @Output() search = new EventEmitter() + column = ['1','2','3','4','5','6','7'] + selection = new SelectionModel(true, []); + query = { + date: null + } + constructor( + private studentPaymentSV: StudentPaymentService, + private swSV: SweetalertService + ) { + super() + } + + ngOnInit(): void { + + } + + ngOnChanges(){ + this.confirmList = this.updateMatTable(this.confirmList? this.confirmList: []) + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.confirmList?.data.length; + return numSelected === numRows; + } + + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.confirmList?.data.forEach((row:any) => this.selection.select(row)); + } + + checkboxLabel(row?: PeriodicElement): string { + if (!row) { + return `${this.isAllSelected() ? 'select' : 'deselect'} all`; + } + return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`; + } + + save(){ + this.confirm.emit(this.selection.selected) + } + + clear(){ + this.selection.clear() + } + + onSearch(event){ + this.search.emit(event) + } + + deletePayment(){ + this.delete.emit(this.selection.selected) + } + +} diff --git a/src/app/feature/manage-payment/confirm/router/router.ts b/src/app/feature/manage-payment/confirm/router/router.ts new file mode 100644 index 0000000..4ad2cce --- /dev/null +++ b/src/app/feature/manage-payment/confirm/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-confirm-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ConfirmRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/manage-payment/import/container/import/import.container.html b/src/app/feature/manage-payment/import/container/import/import.container.html new file mode 100644 index 0000000..f2d54fe --- /dev/null +++ b/src/app/feature/manage-payment/import/container/import/import.container.html @@ -0,0 +1 @@ + diff --git a/src/app/feature/manage-payment/import/container/import/import.container.scss b/src/app/feature/manage-payment/import/container/import/import.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-payment/import/container/import/import.container.spec.ts b/src/app/feature/manage-payment/import/container/import/import.container.spec.ts new file mode 100644 index 0000000..63187cc --- /dev/null +++ b/src/app/feature/manage-payment/import/container/import/import.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImportContainer } from './import.container'; + +describe('ImportContainer', () => { + let component: ImportContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ImportContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ImportContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-payment/import/container/import/import.container.ts b/src/app/feature/manage-payment/import/container/import/import.container.ts new file mode 100644 index 0000000..9c30588 --- /dev/null +++ b/src/app/feature/manage-payment/import/container/import/import.container.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-import', + templateUrl: './import.container.html', + styleUrls: ['./import.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ImportContainer implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/manage-payment/import/import.module.ts b/src/app/feature/manage-payment/import/import.module.ts new file mode 100644 index 0000000..11e1e4a --- /dev/null +++ b/src/app/feature/manage-payment/import/import.module.ts @@ -0,0 +1,34 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { ImportRouter } from './router/router'; +import { ImportContainer } from './container/import/import.container'; +import { ListComponent } from './presenter/list/list.component'; + +const routes: Routes = [ + { + path: '', + component: ImportRouter, + children: [ + { + path: '', + component: ImportContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ImportRouter, + ImportContainer, + ListComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ImportModule { } diff --git a/src/app/feature/manage-payment/import/presenter/list/list.component.html b/src/app/feature/manage-payment/import/presenter/list/list.component.html new file mode 100644 index 0000000..c7fa30a --- /dev/null +++ b/src/app/feature/manage-payment/import/presenter/list/list.component.html @@ -0,0 +1,46 @@ +

นำเข้ารายการชำระเงิน

+
+
+ + +
+
+
+
+

รายการนำเข้า

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อ-นามสกุล {{x.payer_name}} ref1 {{x.ref1}} ref2 {{x.ref2}} จำนวนเงิน {{x.transaction_amount}} วันที่ชำระเงิน {{x.transaction_date | thaidate}}
+ +
+
+ + +
+
diff --git a/src/app/feature/manage-payment/import/presenter/list/list.component.scss b/src/app/feature/manage-payment/import/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-payment/import/presenter/list/list.component.spec.ts b/src/app/feature/manage-payment/import/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/manage-payment/import/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-payment/import/presenter/list/list.component.ts b/src/app/feature/manage-payment/import/presenter/list/list.component.ts new file mode 100644 index 0000000..e4a1bd2 --- /dev/null +++ b/src/app/feature/manage-payment/import/presenter/list/list.component.ts @@ -0,0 +1,75 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core'; +import { throwError } from 'rxjs'; +import { catchError, filter, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { StudentPaymentService } from 'src/app/core/service/student-payment/student-payment.service'; +import { StudentPaymentUploadService } from 'src/app/core/service/student-payment/student-upload.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit { + @Input() importList: any = []; + column = ['1','2','3','4','5','6'] + selectfile; + data; + confirmData; + constructor( + private studentUploadSV: StudentPaymentUploadService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private studentPaymentSV: StudentPaymentService + ) { + super() + } + + ngOnInit(): void { + } + + save(){ + this.studentUploadSV.confirm(this.confirmData).pipe( + tap(x => console.log(x)), + tap(x => this.swSV.saveSuccess()), + tap(x => this.clear()), + catchError(err => { + this.swSV.errText('บันทึกไม่สำเร็จ') + return throwError(err) + }) + ).subscribe() + } + + clear(){ + this.data = [] + this.confirmData = null + this.cdr.detectChanges() + console.log(this.confirmData) + } + + onSelectFile(event) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.upload() + } + } + + upload(){ + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.studentUploadSV.uploadDocument(formData).pipe( + filter((x:any) => x.status == 'success'), + tap(x => this.confirmData = x.message), + tap(x => this.data = x.message.bill_receivable_items), + tap(x => this.data = this.updateMatTable(this.data)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText('มีข้อผิดพลาดในการนำเข้า') + return throwError(err) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/manage-payment/import/router/router.ts b/src/app/feature/manage-payment/import/router/router.ts new file mode 100644 index 0000000..6e7653f --- /dev/null +++ b/src/app/feature/manage-payment/import/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-import-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ImportRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/manage-test-center/manage-test-center-router/manage-test-center-router.component.ts b/src/app/feature/manage-test-center/manage-test-center-router/manage-test-center-router.component.ts new file mode 100644 index 0000000..ebab5a9 --- /dev/null +++ b/src/app/feature/manage-test-center/manage-test-center-router/manage-test-center-router.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-manage-test-center-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageTestCenterRouterComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/manage-test-center/manage-test-center.module.ts b/src/app/feature/manage-test-center/manage-test-center.module.ts new file mode 100644 index 0000000..1f931a4 --- /dev/null +++ b/src/app/feature/manage-test-center/manage-test-center.module.ts @@ -0,0 +1,56 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { ManageTestCenterRouterComponent } from './manage-test-center-router/manage-test-center-router.component'; +import { ManageTestCenterListComponent } from './presenter/manage-test-center-list/manage-test-center-list.component'; +import { ManageTestCenterSearchComponent } from './presenter/manage-test-center-search/manage-test-center-search.component'; +import { ManageTestCenterFormComponent } from './presenter/manage-test-center-form/manage-test-center-form.component'; +import { ManageTestCenterTableComponent } from './presenter/manage-test-center-table/manage-test-center-table.component'; +import { CopyComponent } from './presenter/dialog/copy/copy.component'; +import { PreviewComponent } from './presenter/dialog/preview/preview.component'; +import { ViewSeatComponent } from './presenter/dialog/view-seat/view-seat.component'; + +const routes: Routes = [ + { + path: '', + component: ManageTestCenterRouterComponent, + children: [ + { + path: '', + component: ManageTestCenterListComponent, + }, + { + path: 'search', + component: ManageTestCenterTableComponent, + }, + { + path: 'add', + component: ManageTestCenterFormComponent, + }, + { + path: 'edit/:id', + component: ManageTestCenterFormComponent, + }, + ], + }, +]; + +@NgModule({ + declarations: [ + ManageTestCenterRouterComponent, + ManageTestCenterListComponent, + ManageTestCenterSearchComponent, + ManageTestCenterFormComponent, + ManageTestCenterTableComponent, + CopyComponent, + PreviewComponent, + ViewSeatComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class ManageTestCenterModule { } diff --git a/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.html b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.html new file mode 100644 index 0000000..95740ac --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.html @@ -0,0 +1,25 @@ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
diff --git a/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.scss b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.spec.ts b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.spec.ts new file mode 100644 index 0000000..8ed1e7f --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CopyComponent } from './copy.component'; + +describe('CopyComponent', () => { + let component: CopyComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CopyComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CopyComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.ts b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.ts new file mode 100644 index 0000000..1436388 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/copy/copy.component.ts @@ -0,0 +1,143 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../core/service/settings/academic-semester.service'; + +@Component({ + selector: 'app-copy', + templateUrl: './copy.component.html', + styleUrls: ['./copy.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CopyComponent implements OnInit { + Olddata; + copycat; + AcademicYear = []; + AcademicsemesterMock = []; + query = { + academic_year_uid: null, + academic_semester_uid: null, + testing_center_uid: null, + testing_center_name_th: null, + testing_room_name_th: null + }; + constructor( + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + private cdr: ChangeDetectorRef, + private testingCenter: TestingCenterService, + private academicYearSV: AcademicYearService, + private academicSemSV: AcademicSemesterService, + @Inject(MAT_DIALOG_DATA) public data + ) { } + + ngOnInit(): void { + this.academicYearSV.getAll().subscribe( + result => { + this.AcademicYear = result; + this.cdr.detectChanges(); + } + ); + this.academicSemSV.getAll().subscribe( + result => { + this.AcademicsemesterMock = result; + this.cdr.detectChanges(); + } + ); + } + + cancel(){ + this.dialogRef.close(); + } + + save(){ + for (var index in this.data){ + console.log(this.data[index].testing_center_uid); + this.checkdata(this.data[index].testing_center_uid); + } + this.swSV.saveSuccess(); + this.cancel() + } + + checkdata(id: number){ + this.testingCenter.get(id).pipe( + // tap(x => console.log(x)), + ). + subscribe( + res => { + const copy = JSON.parse(JSON.stringify(res)); + copy.testing_center_uid = null; + copy.academic_year_uid = this.query.academic_year_uid; + copy.academic_semester_uid = this.query.academic_semester_uid; + console.log(copy); + const picked = (({ + status_id, + branch_uid, + testing_room_name_th, + testing_room_name_en, + testing_center_uid, + testing_field_uid, + academic_year_uid, + academic_semester_uid, + testing_center_periods, + testing_center_rows, + }) => ({ + status_id, + branch_uid, + testing_room_name_th, + testing_room_name_en, + testing_center_uid, + testing_field_uid, + academic_year_uid, + academic_semester_uid, + testing_center_periods, + testing_center_rows, + }))(copy); + // console.log(picked.testing_center_periods); + // const copyperiods = picked.testing_center_periods; + for (var index in picked.testing_center_periods){ + console.log(picked.testing_center_periods[index]); + picked.testing_center_periods[index] = (({ + status_id, + testing_center_period_uid, + period_id, + start_time, + }) => ({ + status_id, + testing_center_period_uid, + period_id, + start_time, + }))( picked.testing_center_periods[index]); + } + for (var index in picked.testing_center_rows){ + console.log(picked.testing_center_rows[index]); + picked.testing_center_rows[index] = (({ + status_id, + testing_center_row_uid, + row_name, + no_of_seats, + }) => ({ + status_id, + testing_center_row_uid, + row_name, + no_of_seats, + }))( picked.testing_center_rows[index]); + } + console.log(picked); + this.testingCenter.add(picked).pipe( + // tap(x => this.swSV.saveSuccess()), + // tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + } + ); + } + +} diff --git a/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.html b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.html new file mode 100644 index 0000000..74167b0 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.html @@ -0,0 +1,26 @@ +
+
+ ศูนย์สอบ : {{data.testing_center.branch_uid | getDataId : branchList:'branch_uid' : 'branch_name_th':''}} + สนามสอบ : {{data.testing_center.testing_field_uid | getDataId : testingFieldList:'testing_field_uid' : 'testing_field_name_th':''}} + ห้องสอบ : {{data.testing_center.testing_room_name_th}} +
+
+
+
+
+ +
+ +
+ chair + {{x.row_name + (seat_index+1)}} +
+
+
+
+
+
+
+
+ +
diff --git a/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.scss b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.scss new file mode 100644 index 0000000..6baa146 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.scss @@ -0,0 +1,11 @@ +@media print { + #section-to-print { + background-color: white; + height: 100%; + width: 100%; + position: fixed; + top: 0; + left: 0; + } +} + diff --git a/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.spec.ts b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.spec.ts new file mode 100644 index 0000000..5d99da7 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PreviewComponent } from './preview.component'; + +describe('PreviewComponent', () => { + let component: PreviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PreviewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PreviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.ts b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.ts new file mode 100644 index 0000000..83109cc --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/preview/preview.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { tap } from 'rxjs/operators'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { TestingFieldService } from 'src/app/core/service/settings/testing-field.service'; + +@Component({ + selector: 'app-preview', + templateUrl: './preview.component.html', + styleUrls: ['./preview.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PreviewComponent implements OnInit { + testingFieldList: any = []; + branchList: any = []; + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.testingFieldSV.getAll().pipe( + tap(x => this.testingFieldList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.branchSV.getAll().pipe( + tap(x => this.branchList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + print(){ + window.print() + } + +} diff --git a/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.html b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.html new file mode 100644 index 0000000..1b16c2a --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.html @@ -0,0 +1,55 @@ +
+

การใช้ห้อง

+
+
+
+
+
+ + + + + + +
+ +
+ + + + + + +
+ +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
วันที่ {{x.date | thaidate}} ที่นั่งทั้งหมด {{x.total_seat}} ใช้แล้ว {{x.total_seat_use}} คงเหลือ {{x.total_seat_left}}
+ +
diff --git a/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.scss b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.spec.ts b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.spec.ts new file mode 100644 index 0000000..374f365 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewSeatComponent } from './view-seat.component'; + +describe('ViewSeatComponent', () => { + let component: ViewSeatComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ViewSeatComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewSeatComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.ts b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.ts new file mode 100644 index 0000000..eb5efd8 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/dialog/view-seat/view-seat.component.ts @@ -0,0 +1,53 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingCenterService } from 'src/app/core/service/TestingCenter/testing-center.service'; + +@Component({ + selector: 'app-view-seat', + templateUrl: './view-seat.component.html', + styleUrls: ['./view-seat.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ViewSeatComponent extends BaseList implements OnInit { + availableSeatList: any = []; + query = { + from_date: null, + to_date: null, + testing_center_uid: null + } + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private testingCenterSV: TestingCenterService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super() + } + + ngOnInit(): void { + this.query.testing_center_uid = this.data + } + + search(){ + this.query.from_date = formatDate(this.query.from_date,'yyyy-MM-dd','en-US') + this.query.to_date = formatDate(this.query.to_date,'yyyy-MM-dd','en-US') + this.testingCenterSV.getAvailableSeat(this.query).pipe( + tap((x:any) => { + if(x.length == 0) return this.swSV.errText('ไม่มีข้อมูล') + }), + tap(x => this.availableSeatList = this.updateMatTable(x)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.html b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.html new file mode 100644 index 0000000..fca0544 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.html @@ -0,0 +1,196 @@ + +

เพิ่มรายการ

+
+
+
+
+ + +
+ +
+ + +
+
+ + +
+
+
+
+ + +
+ + + + +
+ + +
+ +
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
ชื่อแถว {{element.row_name}} จำนวนที่นั่งต่อแถว {{element.no_of_seats}} +
+ +
+
ไม่มีข้อมูล
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+
{{testcenterForm.getRawValue() | json}}
+ + + diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.scss b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.spec.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.spec.ts new file mode 100644 index 0000000..acc3623 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageTestCenterFormComponent } from './manage-test-center-form.component'; + +describe('ManageTestCenterFormComponent', () => { + let component: ManageTestCenterFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageTestCenterFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageTestCenterFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.ts new file mode 100644 index 0000000..455068b --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-form/manage-test-center-form.component.ts @@ -0,0 +1,376 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {FormBuilder, FormGroup, FormArray, Validators} from '@angular/forms'; +import {TestingCenterService} from '../../../../core/service/TestingCenter/testing-center.service'; +import {catchError, switchMap, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {ActivatedRoute, Router} from '@angular/router'; +import {formatDate, Location} from '@angular/common'; +import { BaseForm } from 'src/app/core/base/base-form'; +import {BranchService} from '../../../../core/service/settings/branch.service'; +import {TestingFieldService} from '../../../../core/service/settings/testing-field.service'; +import {AcademicYearService} from '../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../core/service/settings/academic-semester.service'; +import { MatDialog } from '@angular/material/dialog'; +import { PreviewComponent } from '../dialog/preview/preview.component'; + +@Component({ + selector: 'app-manage-test-center-form', + templateUrl: './manage-test-center-form.component.html', + styleUrls: ['./manage-test-center-form.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageTestCenterFormComponent extends BaseForm implements OnInit { + testcenterForm: FormGroup; + PeriodData: any; + // testingCenterPeriods: FormArray; + // testingCenterRows: FormArray; + UnivesityMock: any = []; + TestfiledList:any = []; + AcademicsemesterMock = []; + AcademicYear = []; + DataPriod: any = { + period_id: null, + start_time: '', + }; + + rowData: any = { + row_name: '', + no_of_seats: null, + }; + + jsonSection = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": "1", + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": "2", + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": "3", + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": "4", + "start_time": "18:00" + } + ]; + + + // public get getForm(): FormArray { + // return this.testcenterForm.get('testing_center_rows') as FormArray; + // } + + displayedColumns: string[] = ['row_name', 'no_of_seats', 'actions']; + displayedColumns2: string[] = ['period_id', 'start_time', 'actions']; + dataSource = new MatTableDataSource(); + dataSource2 = new MatTableDataSource(); + constructor( + private formBuilder: FormBuilder, + private testingCenter: TestingCenterService, + private branchSV: BranchService, + private testfieldSV: TestingFieldService, + private academicYearSV: AcademicYearService, + private academicSemSV: AcademicSemesterService, + private swSV: SweetalertService, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private cdr: ChangeDetectorRef, + private dialog: MatDialog + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + + this.testcenterForm = this.formBuilder.group({ + status_id: 1, + created_by: null, + created_date: null, + updated_by: null, + updated_date: null, + deleted_by: null, + deleted_date: null, + testing_field_uid: [null, Validators.required], + testing_field_name_th: null, + branch_uid: [null, Validators.required], + branch_name_th: null, + testing_room_name_th: [null, Validators.required], + testing_room_name_en: [null], + academic_year_uid: [null, Validators.required], + academic_semester_uid: [null, Validators.required], + testing_center_uid: null, + testing_center_rows: this.formBuilder.array([ + this.rowForm() + ]), + testing_center_periods: this.formBuilder.array([ + this.periodsForm(), + ]), + }); + } + + periodsForm(a?){ + return this.formBuilder.group({ + status_id: 1, + // created_by: null, + // created_date: new Date(), + // updated_by: null, + // updated_date: Date, + // deleted_by: null, + // deleted_date: Date, + testing_center_period_uid: null, + // testing_center_id: null, + period_id: [a?.period_id, Validators.required], + start_time: [a?.start_time, Validators.required], + }); + } + periodsFormEdit(a){ + return this.formBuilder.group({ + status_id: a.status_id, + created_by: a.created_by, + created_date: a.created_date, + updated_by: a.updated_by, + updated_date: a.updated_date, + deleted_by: a.deleted_by, + deleted_date: a.deleted_date, + testing_center_period_uid: a.testing_center_period_uid, + testing_center_uid: a.testing_center_uid, + period_id: a.period_id, + start_time: a.start_time, + }); + } + rowForm(a?){ + return this.formBuilder.group({ + status_id: 1, + // created_by: null, + // created_date: new Date(), + // updated_by: null, + // updated_date: null, + // deleted_by: null, + // deleted_date: null, + testing_center_row_uid: null, + // testing_center_id: null, + row_name: [a?.row_name, Validators.required], + no_of_seats: [a?.no_of_seats, + [Validators.pattern(/^-?(0|[1-9]\d*)?$/) , Validators.required], + ], + }); + } + rowFormEdit(a){ + return this.formBuilder.group({ + status_id: a.status_id, + created_by: a.created_by, + created_date: a.created_date, + updated_by: a.updated_by, + updated_date: a.updated_date, + deleted_by: a.deleted_by, + deleted_date: a.deleted_date, + testing_center_row_uid: a.testing_center_row_uid, + testing_center_uid: a.testing_center_uid, + row_name: a.row_name, + no_of_seats: a.no_of_seats, + }); + } + + ngOnInit(): void { + + this.branchSV.getAllStatus1().pipe( + tap(x => this.UnivesityMock = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + + this.testfieldSV.getAll().pipe( + tap(x => this.TestfiledList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + + this.academicYearSV.getAll().pipe( + tap(x => this.AcademicYear = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + + this.academicSemSV.getAll().pipe( + tap(x => this.AcademicsemesterMock = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + + switch (this.state) { + case 'edit': + const formRow = this.testcenterForm.get('testing_center_rows') as FormArray; + const formPeriod = this.testcenterForm.get('testing_center_periods') as FormArray; + this.testingCenter.get(this.id).pipe( + tap(x => console.log(x)), + tap(x => this.testcenterForm.patchValue(x)), + tap(x => { + formRow.clear(); + // @ts-ignore + x.testing_center_rows.forEach(a => { + console.log(a); + formRow.push(this.rowFormEdit(a)); + // formPeriod.push(this.formBuilder.group(a)); + }); + const table = formRow.getRawValue(); + this.dataSource.data = table; + }), + tap(x => { + formPeriod.clear(); + // @ts-ignore + x.testing_center_periods.forEach(a => { + console.log(a); + formPeriod.push(this.periodsFormEdit(a)); + // formPeriod.push(this.formBuilder.group(a)); + }); + const table = formPeriod.getRawValue(); + this.dataSource2.data = table; + }), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + break; + case 'add': + console.log(this.jsonSection); + const formPeriodAdd = this.testcenterForm.get('testing_center_periods') as FormArray; + formPeriodAdd.clear(); + this.jsonSection.forEach(a => { + formPeriodAdd.push(this.periodsForm(a)); + }); + // this.rowForm(this.jsonSection); + break; + } + // const form1 = this.testcenterForm.get('testing_center_rows') as FormArray; + // form1.reset(); + // const form2 = this.testcenterForm.get('testing_center_periods') as FormArray; + // form2.reset(); + // this.dataSource.data = []; + // this.dataSource2.data = []; + } + + save(){ + const form = this.testcenterForm.getRawValue(); + const formRow = this.testcenterForm.get('testing_center_rows') as FormArray; + const formPeriod = this.testcenterForm.get('testing_center_periods') as FormArray; + switch (this.state) { + case 'edit': + form.created_datetime = formatDate(new Date(), 'yyyy-MM-dd', 'en-US'); + this.testingCenter.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error.description); + return throwError(err); + }) + ).subscribe(); + break; + case 'add': + this.testingCenter.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error.description); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + clearTable() { + this.dataSource.data = []; + } + + // addItem(){ + // this.getForm.push(this.rowForm()); + // } + // remove(index: number){ + // this.getForm.removeAt(index); + // } + addData() { + this.dataSource.data = []; + } + + clearTable2() { + this.dataSource2.data = []; + } + addData2() { + this.dataSource2.data = []; + } + + putArray(){ + const form = this.testcenterForm.get('testing_center_rows') as FormArray; + const table = form.getRawValue(); + this.dataSource.data = table; + } + add(){ + const form = this.testcenterForm.get('testing_center_rows') as FormArray; + form.push(this.rowForm()); + } + + removeArray(i){ + const form = this.testcenterForm.get('testing_center_rows') as FormArray; + form.removeAt(i); + } + + removeArrayTable(i){ + const form = this.testcenterForm.get('testing_center_rows') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource.data = table; + } + + add2(){ + const form = this.testcenterForm.get('testing_center_periods') as FormArray; + form.push(this.periodsForm()); + } + + putArray2(){ + const form = this.testcenterForm.get('testing_center_periods') as FormArray; + const table = form.getRawValue(); + this.dataSource2.data = table; + } + + removeArray2(i){ + const form = this.testcenterForm.get('testing_center_periods') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource2.data = table; + } + + + cancel(){ + window.history.back() + } + + setTestField(id){ + this.testfieldSV.getByBrandID(id).pipe( + tap(x => console.log(x)), + tap(x => this.TestfiledList = x), + ).subscribe(); + } + + preview(){ + const form = (this.testcenterForm.get('testing_center_rows') as FormArray).getRawValue(); + const obj = { + data : form, + testing_center: this.testcenterForm.getRawValue() + } + + const dialogRef = this.dialog.open(PreviewComponent, { + width: '600px', + maxHeight: '80vh', + data: obj + }); + } +} diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.html b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.html new file mode 100644 index 0000000..aa8a41d --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.html @@ -0,0 +1,15 @@ + +
+
+ +
+
+ +
+
+ + + diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.scss b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.spec.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.spec.ts new file mode 100644 index 0000000..8852b90 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageTestCenterListComponent } from './manage-test-center-list.component'; + +describe('ManageTestCenterListComponent', () => { + let component: ManageTestCenterListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageTestCenterListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageTestCenterListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.ts new file mode 100644 index 0000000..cef1527 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-list/manage-test-center-list.component.ts @@ -0,0 +1,59 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges, ChangeDetectorRef} from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import {TestingCenterService} from '../../../../core/service/TestingCenter/testing-center.service'; +import {BaseList} from '../../../../core/base/base-list'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import { ViewSeatComponent } from '../dialog/view-seat/view-seat.component'; + +@Component({ + selector: 'app-manage-test-center-list', + templateUrl: './manage-test-center-list.component.html', + styleUrls: ['./manage-test-center-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageTestCenterListComponent extends BaseList implements OnInit { + testingcenterList$ = new Observable(); + constructor( + private testingCenter: TestingCenterService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService + ) { + super(); + } + + ngOnInit(): void { + this.testingcenterList$ = this.testingCenter.getAll(); + } + search(query){ + if (query) { return this.testingcenterList$ = this.testingCenter.search(`?${query}`); } + if (!query) { return this.testingcenterList$ = this.testingCenter.getAll(); } + } + + viewAvailableSeat(testing_center_uid){ + const dialog = this.dialog.open(ViewSeatComponent, { + width: '50%', + data: testing_center_uid + }); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.testingCenter.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.testingcenterList$ = this.testingCenter.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ); + }) + ).subscribe(); + } +} diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.html b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.html new file mode 100644 index 0000000..a5fda1d --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.html @@ -0,0 +1,49 @@ + +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
+ + + diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.scss b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.scss new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.spec.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.spec.ts new file mode 100644 index 0000000..4f13a31 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageTestCenterSearchComponent } from './manage-test-center-search.component'; + +describe('ManageTestCenterSearchComponent', () => { + let component: ManageTestCenterSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageTestCenterSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageTestCenterSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.ts new file mode 100644 index 0000000..c8c4986 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-search/manage-test-center-search.component.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, ChangeDetectionStrategy , Output, EventEmitter } from '@angular/core'; +import {createQueryStringFromObject} from '../../../../shared/util/func'; +import {AcademicYearService} from "../../../../core/service/settings/academic-year.service"; +import {AcademicSemesterService} from "../../../../core/service/settings/academic-semester.service"; + + +@Component({ + selector: 'app-manage-test-center-search', + templateUrl: './manage-test-center-search.component.html', + styleUrls: ['./manage-test-center-search.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageTestCenterSearchComponent implements OnInit { + academicYearList; + academicSemList; + @Output() search = new EventEmitter(); + query = { + academic_year_name_th: null, + academic_semester_name_th: null, + branch_name_th: null, + testing_field_name_th: null, + testing_room_name_th: null + }; + + constructor( + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + clear() { + this.query = { + academic_year_name_th: null, + academic_semester_name_th: null, + branch_name_th: null, + testing_field_name_th: null, + testing_room_name_th: null + }; + } + +} diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.html b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.html new file mode 100644 index 0000000..bdb26b3 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.html @@ -0,0 +1,121 @@ +
+ + +
+
+ แสดงผลการค้นหา +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + ปีการศึกษา {{element.academic_year_name_th}} ภาคการศึกษา {{element.academic_semester_name_th}} ชื่อศูนย์สอบ {{element.branch_name_th}} สนามสอบ {{element.testing_field_name_th}} ห้องสอบ {{element.testing_room_name_th}} จำนวนแถว {{element.total_row}} จำนวนที่นั่งรวม {{element.total_seat}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล +
+ {{x.created_datetime | thaidate}} +
+
+
+ + + +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
+
+ + diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.scss b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.scss new file mode 100644 index 0000000..af588a0 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.scss @@ -0,0 +1,6 @@ +table { + width: 100%; +} +.mat-column-select { + overflow: initial; +} diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.spec.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.spec.ts new file mode 100644 index 0000000..17aa789 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ManageTestCenterTableComponent } from './manage-test-center-table.component'; + +describe('ManageTestCenterTableComponent', () => { + let component: ManageTestCenterTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ManageTestCenterTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ManageTestCenterTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.ts b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.ts new file mode 100644 index 0000000..c6b6e71 --- /dev/null +++ b/src/app/feature/manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component.ts @@ -0,0 +1,124 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef, Output, EventEmitter} from '@angular/core'; +import {MatTableDataSource} from '@angular/material/table'; +import {SelectionModel} from '@angular/cdk/collections'; +import {CalendarDialogComponent} from '../../../settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component'; +import {MatDialog} from '@angular/material/dialog'; +import {CopyComponent} from '../dialog/copy/copy.component'; +import { BaseList } from 'src/app/core/base/base-list'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {TestingCenterService} from '../../../../core/service/TestingCenter/testing-center.service'; +// import {mkdir} from 'fs'; + +export interface PeriodicElement { + position: number; + testing_center_id: number; + year: number; + term: number; + centername: string; + testcentername: string; + roomname: string; + row: number; + total: number; +} + +@Component({ + selector: 'app-manage-test-center-table', + templateUrl: './manage-test-center-table.component.html', + styleUrls: ['./manage-test-center-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ManageTestCenterTableComponent extends BaseList implements OnInit, OnChanges { + @Input() testingcenterList: any = []; + @Output() delete = new EventEmitter(); + @Output() onViewAvailableSeat = new EventEmitter() + column = [ + 'select', + 'academic_year_name_th', + 'academic_semester_name_th', + 'branch_name_th', + 'testing_field_name_th', + 'testing_room_name_th', + 'total_row', + 'total_seat', + 'created_by', + 'created_datetime', + 'actions' + ]; + dataSource = new MatTableDataSource(); + selection = new SelectionModel(true, []); + + /** Whether the number of selected elements matches the total number of rows. */ + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.testingcenterList?.data?.length; + return numSelected === numRows; + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.testingcenterList.data.forEach(row => this.selection.select(row)); + } + + /** The label for the checkbox on the passed row */ + checkboxLabel(row?: PeriodicElement): string { + if (!row) { + return `${this.isAllSelected() ? 'select' : 'deselect'} all`; + } + return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${ + row.position + 1 + }`; + } + + + reload: boolean; + constructor( + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingCenterSV: TestingCenterService, + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.testingcenterList = this.updateMatTable(this.testingcenterList ? this.testingcenterList : []); + } + + + openCopydialog(){ + const dialogRef = this.dialog.open(CopyComponent, { + width: '500px', + height: '200px', + data: this.selection.selected + }); + dialogRef.afterClosed().pipe( + tap(x => { + this.testingCenterSV.getAll().subscribe( + res => + { + this.testingcenterList = this.updateMatTable(res) + } + ); + }), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + onDelete(id){ + this.delete.emit(id); + } + + + + +} diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.html b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.html new file mode 100644 index 0000000..fc7bf99 --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.scss b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.spec.ts b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.spec.ts new file mode 100644 index 0000000..73938e3 --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamListContainer } from './notification-check-exam-list.container'; + +describe('NotificationCheckExamListContainer', () => { + let component: NotificationCheckExamListContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamListContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamListContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.ts b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.ts new file mode 100644 index 0000000..d86d89c --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam-list/notification-check-exam-list.container.ts @@ -0,0 +1,36 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from 'rxjs'; +import {Router} from '@angular/router'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-notification-check-exam-list', + templateUrl: './notification-check-exam-list.container.html', + styleUrls: ['./notification-check-exam-list.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamListContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.search(`?is_open=true`); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.search(`?is_open=true`); + } + + view(id){ + this.router.navigate(['notification-check-exam/detail', id]); + } + +} diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.html b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.html new file mode 100644 index 0000000..d666998 --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.scss b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.spec.ts b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.spec.ts new file mode 100644 index 0000000..11ceeeb --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamContainer } from './notification-check-exam.container'; + +describe('NotificationCheckExamContainer', () => { + let component: NotificationCheckExamContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.ts b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.ts new file mode 100644 index 0000000..0702b81 --- /dev/null +++ b/src/app/feature/notification-check-exam/container/notification-check-exam/notification-check-exam.container.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {concatMap, tap} from 'rxjs/operators'; +import {ExamNotificationService} from '../../../../core/service/testing-information/exam-notification.service'; +import {Observable} from 'rxjs'; +import {SubjectsService} from '../../../../core/service/settings/subjects.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-notification-check-exam', + templateUrl: './notification-check-exam.container.html', + styleUrls: ['./notification-check-exam.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamContainer implements OnInit { + subjectList$ = new Observable(); + subjectListSend$ = []; + testinForUid; + testingInfoData + constructor( + private subjectSV: SubjectsService, + private router: Router, + private activeRouter: ActivatedRoute, + private examNotiSV: ExamNotificationService, + private testingInfoSV: TestingInformationService + ) { } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => { + this.subjectList$ = this.examNotiSV.getByUid(x.id); + }), + concatMap(x => this.testingInfoSV.get(x.id)), + tap(x => this.testingInfoData = x) + ).subscribe(); + this.subjectSV.getAll().pipe( + tap(x => { + this.subjectListSend$ = x; + }), + ).subscribe(); + } + + search(query){ + if(query) return this.subjectList$ = this.examNotiSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.examNotiSV.getAll(); + } + +} diff --git a/src/app/feature/notification-check-exam/notification-check-exam.module.ts b/src/app/feature/notification-check-exam/notification-check-exam.module.ts new file mode 100644 index 0000000..434db6c --- /dev/null +++ b/src/app/feature/notification-check-exam/notification-check-exam.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NotificationCheckExamRouter } from './router/notification-check-exam-router'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { NotificationCheckExamContainer } from './container/notification-check-exam/notification-check-exam.container'; +import { NotificationCheckExamListContainer } from './container/notification-check-exam-list/notification-check-exam-list.container'; +import { NotificationCheckExamAllComponent } from './presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component'; +import { NotificationCheckExamSearchComponent } from './presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component'; +import { NotificationCheckExamListComponent } from './presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component'; +import { NotificationCheckExamListSearchComponent } from './presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component'; +import { + NotificationCheckExamDialogComponent +} from './presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: NotificationCheckExamRouter, + children: [ + { + path: '', + component: NotificationCheckExamListContainer + }, + { + path: 'detail/:id', + component: NotificationCheckExamContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + NotificationCheckExamRouter, + NotificationCheckExamContainer, + NotificationCheckExamListContainer, + NotificationCheckExamAllComponent, + NotificationCheckExamSearchComponent, + NotificationCheckExamListComponent, + NotificationCheckExamListSearchComponent, + NotificationCheckExamDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class NotificationCheckExamModule { } diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.html b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.html new file mode 100644 index 0000000..ad62bea --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.html @@ -0,0 +1,79 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.scss b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.spec.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.spec.ts new file mode 100644 index 0000000..9a1e72a --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamListComponent } from './notification-check-exam-list.component'; + +describe('NotificationCheckExamListComponent', () => { + let component: NotificationCheckExamListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.ts new file mode 100644 index 0000000..94531d5 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/list/notification-check-exam-list/notification-check-exam-list.component.ts @@ -0,0 +1,48 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'notification-check-exam-list', + templateUrl: './notification-check-exam-list.component.html', + styleUrls: ['./notification-check-exam-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '8', + 'count_subject', + 'is_open', + 'created_by', + 'created_datetime', + '7' + ]; + reload: boolean; + + @Output() view = new EventEmitter(); + constructor( + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onView(id){ + this.view.emit(id); + } + +} diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.html b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.html new file mode 100644 index 0000000..4a3636a --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.html @@ -0,0 +1,27 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.scss b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.spec.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.spec.ts new file mode 100644 index 0000000..b568b6b --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamListSearchComponent } from './notification-check-exam-list-search.component'; + +describe('NotificationCheckExamListSearchComponent', () => { + let component: NotificationCheckExamListSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamListSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamListSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.ts new file mode 100644 index 0000000..1429e29 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam-list/search/notification-check-exam-list-search/notification-check-exam-list-search.component.ts @@ -0,0 +1,50 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../../../core/service/settings/academic-year.service'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-notification-check-exam-list-search', + templateUrl: './notification-check-exam-list-search.component.html', + styleUrls: ['./notification-check-exam-list-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamListSearchComponent implements OnInit { + + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + is_open: true + }; + } + +} diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.html b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.html new file mode 100644 index 0000000..ec44004 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.html @@ -0,0 +1,62 @@ +
+
+
+
แจ้งเตือนการตรวจข้อสอบ
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+

Topic

+
+
+ +
+
+
+
+ +
+
+
+
+

Email

+
+ +
+ + +
+
+
+
+
+
+ + +
+
+ + + + + diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.scss b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.scss new file mode 100644 index 0000000..a22b7ee --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.scss @@ -0,0 +1,11 @@ +.bgPopup{ // สีพื้นหลังหน้า list ลอง + background-color: #576071; +} + +.lock_open{ + @apply focus:outline-none text-green-700 text-sm py-1 px-2 rounded-md hover:bg-green-100 hover:bg-opacity-50 +} + +.lock_outline{ + @apply focus:outline-none text-gray-400 text-sm py-1 px-2 rounded-md hover:bg-gray-100 bg-opacity-50 +} diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.spec.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.spec.ts new file mode 100644 index 0000000..356a55c --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamDialogComponent } from './notification-check-exam-dialog.component'; + +describe('NotificationCheckExamDialogComponent', () => { + let component: NotificationCheckExamDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.ts new file mode 100644 index 0000000..03503a7 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/dialog/notification-check-exam-dialog/notification-check-exam-dialog.component.ts @@ -0,0 +1,114 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Inject} from '@angular/core'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormBuilder, Validators} from '@angular/forms'; +import {SubjectTypesService} from '../../../../../../core/service/settings/subject-types.service'; +import {SubjectsService} from '../../../../../../core/service/settings/subjects.service'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {FacultysService} from '../../../../../../core/service/settings/facultys.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {UploadService} from '../../../../../../core/service/upload/upload.service'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {ExamResultSubjectService} from '../../../../../../core/service/report/exam-result-subject/exam-result-subject.service'; +import {ExamNotificationService} from '../../../../../../core/service/testing-information/exam-notification.service'; +import {catchError, concatMap, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; + +@Component({ + selector: 'app-notification-check-exam-dialog', + templateUrl: './notification-check-exam-dialog.component.html', + styleUrls: ['./notification-check-exam-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamDialogComponent extends BaseForm implements OnInit { + text = '' + emailList: any = []; + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + private swSV: SweetalertService, + public location: Location, + private examResultSV: ExamNotificationService, + private dialogRef: MatDialogRef, + private examNotiSV: ExamNotificationService, + @Inject(MAT_DIALOG_DATA) public data, + private cdr: ChangeDetectorRef + ) { + super( + router, + activeRoute, + fb, + location + ); + this.form = this.fb.group({ + topic: 'ตรวจข้อสอบ e-Testing', + body: null, + email: null, + }); + } + + ngOnInit(): void { + this.examNotiSV.getInstructorEmail(this.data.subject_uid).pipe( + tap(x => this.emailList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + let date = new Date(this.data.testing_datetime).toLocaleDateString('th-TH',{ + year: 'numeric', + month: 'short', + day: 'numeric', + }) + this.text = `วิชา : ${this.data.subject_name}
วันที่สอบ: ${date}
รอการตรวจข้อสอบ : ${this.data.count_waiting}` + this.form.get('body').setValue(this.text) + } + + save(){ + const form = this.form.getRawValue(); + this.swSV.loadingStart() + this.examResultSV.getSendUpdateNotiDate(this.data).pipe( + catchError(err => { + this.swSV.close() + this.swSV.err() + return throwError(err) + }), + concatMap(x => { + return this.examResultSV.sendMail(form).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess('ส่งอีเมล์สำเร็จ')), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.close() + this.swSV.err() + return throwError(err) + }) + ) + }) + ).subscribe() + // this.examResultSV.getSendUpdateNotiDate( + // this.data.testing_information_uid, + // this.data.subject_uid, + // this.data.testing_datetime, + // this.data.period_id).pipe( + // catchError(err => { + // this.swSV.err(); + // return throwError(err); + // }) + // ).subscribe( + // result => { + // this.examResultSV.sendMail(form).pipe( + // tap(x => this.swSV.saveSuccess('ส่งอีเมล์สำเร็จ')), + // catchError(err => { + // this.swSV.err(); + // return throwError(err); + // }) + // ).subscribe(); + // } + // ); + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.html b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.html new file mode 100644 index 0000000..d1e3476 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.html @@ -0,0 +1,51 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} วิชาสอบ {{x.subject_name}} วันที่สอบ {{x.testing_datetime | thaidate}} จำนวนนักศึกษา {{x.count_waiting}} แจ้งเตือนล่าสุด {{x.last_noti_date | thaidate}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.scss b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.spec.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.spec.ts new file mode 100644 index 0000000..5f5a960 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamAllComponent } from './notification-check-exam-all.component'; + +describe('NotificationCheckExamAllComponent', () => { + let component: NotificationCheckExamAllComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamAllComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamAllComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.ts new file mode 100644 index 0000000..5b78231 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/list/notification-check-exam-all/notification-check-exam-all.component.ts @@ -0,0 +1,43 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {MatDialog} from '@angular/material/dialog'; +import {CalendarDialogComponent} from '../../../../../settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component'; +import {tap} from 'rxjs/operators'; +import {NotificationCheckExamDialogComponent} from '../../dialog/notification-check-exam-dialog/notification-check-exam-dialog.component'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-notification-check-exam-all', + templateUrl: './notification-check-exam-all.component.html', + styleUrls: ['./notification-check-exam-all.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamAllComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + column = ['1', '0', '2', '3', '4', '5']; + constructor( + private dialog: MatDialog, + private swSV: SweetalertService + ) { + super(); + } + + ngOnInit(): void { + this.swSV.loadingStart() + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + if(this.subjectList.data) this.swSV.close() + } + + opendialog(data){ + const dialogRef = this.dialog.open(NotificationCheckExamDialogComponent, { + width: '700px', + height: '570px', + data, + panelClass: 'custom-modalbox' + }); + } + +} diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.html b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.html new file mode 100644 index 0000000..83bd3d5 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.html @@ -0,0 +1,43 @@ +

ค้นหาวิชาสอบเพื่อแจ้งเตือนของรอบ {{testingInfoData.testing_information_name}}

+
+
+
+ + + + + {{x.subject_name_th}} + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + +
+ +
+ +
+ + + diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.scss b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.spec.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.spec.ts new file mode 100644 index 0000000..69b6174 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationCheckExamSearchComponent } from './notification-check-exam-search.component'; + +describe('NotificationCheckExamSearchComponent', () => { + let component: NotificationCheckExamSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ NotificationCheckExamSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NotificationCheckExamSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.ts b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.ts new file mode 100644 index 0000000..e7976a8 --- /dev/null +++ b/src/app/feature/notification-check-exam/presenter/notification-check-exam/search/notification-check-exam-search/notification-check-exam-search.component.ts @@ -0,0 +1,58 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {formatDate} from '@angular/common'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {ActivatedRoute, Router} from '@angular/router'; +import {tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-notification-check-exam-search', + templateUrl: './notification-check-exam-search.component.html', + styleUrls: ['./notification-check-exam-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamSearchComponent implements OnInit { + @Output() search = new EventEmitter(); + @Input() testingInfoData: any = []; + @Input() subjectListSend: any = []; + query = { + testing_information_uid: null, + subject_uid: null, + start_date: null, + end_date: null, + }; + private curSub: any; + constructor( + private router: Router, + private activeRouter: ActivatedRoute, + ) { } + + ngOnInit(): void { + this.activeRouter.params.pipe( + tap(x => { + this.query.testing_information_uid = x.id; + }), + ).subscribe(); + } + + onSearch(){ + if(this.query.start_date) this.query.start_date = formatDate(this.query.start_date, 'yyyy-MM-dd', 'en-US'); + if(this.query.end_date) this.query.end_date = formatDate(this.query.end_date, 'yyyy-MM-dd', 'en-US'); + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + displayTestInfor(uid){ + if (uid && this.subjectListSend) return this.subjectListSend.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.subjectListSend) return this.curSub?.subject_name_th + } + + clear(){ + this.query = { + testing_information_uid: this.query.testing_information_uid, + subject_uid: null, + start_date: null, + end_date: null, + }; + } + +} diff --git a/src/app/feature/notification-check-exam/router/notification-check-exam-router.ts b/src/app/feature/notification-check-exam/router/notification-check-exam-router.ts new file mode 100644 index 0000000..36825a9 --- /dev/null +++ b/src/app/feature/notification-check-exam/router/notification-check-exam-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotificationCheckExamRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/online-summary/container/online-summary/online-summary.container.html b/src/app/feature/online-summary/container/online-summary/online-summary.container.html new file mode 100644 index 0000000..8b46dcf --- /dev/null +++ b/src/app/feature/online-summary/container/online-summary/online-summary.container.html @@ -0,0 +1,4 @@ + + diff --git a/src/app/feature/online-summary/container/online-summary/online-summary.container.scss b/src/app/feature/online-summary/container/online-summary/online-summary.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/online-summary/container/online-summary/online-summary.container.spec.ts b/src/app/feature/online-summary/container/online-summary/online-summary.container.spec.ts new file mode 100644 index 0000000..ab9ba61 --- /dev/null +++ b/src/app/feature/online-summary/container/online-summary/online-summary.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OnlineSummaryContainer } from './online-summary.container'; + +describe('OnlineSummaryContainer', () => { + let component: OnlineSummaryContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ OnlineSummaryContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OnlineSummaryContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/online-summary/container/online-summary/online-summary.container.ts b/src/app/feature/online-summary/container/online-summary/online-summary.container.ts new file mode 100644 index 0000000..a821518 --- /dev/null +++ b/src/app/feature/online-summary/container/online-summary/online-summary.container.ts @@ -0,0 +1,40 @@ +import {formatDate} from '@angular/common'; +import {Component, OnInit, ChangeDetectionStrategy} from '@angular/core'; +import {Observable} from 'rxjs'; +import {map} from 'rxjs/operators'; +import {StudentPaymentConfirmService} from 'src/app/core/service/student-payment/student-payment-confirm.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-online-summary', + templateUrl: './online-summary.container.html', + styleUrls: ['./online-summary.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class OnlineSummaryContainer implements OnInit { + paymentList$ = new Observable(); + + constructor( + private studentPaymentConfirmSV: StudentPaymentConfirmService + ) { + } + + ngOnInit(): void { + + } + + search(data) { + if(data.date != null){ + data.date = formatDate(data.date, 'yyyy-MM-dd', 'en-US'); + } + console.log(data); + const query = createQueryStringFromObject(data) + if(query){ + return this.paymentList$ = this.studentPaymentConfirmSV.search(`?${query}`) + }else{ + return this.paymentList$ = this.studentPaymentConfirmSV.getAll() + } + } + + +} diff --git a/src/app/feature/online-summary/online-summary.module.ts b/src/app/feature/online-summary/online-summary.module.ts new file mode 100644 index 0000000..489be93 --- /dev/null +++ b/src/app/feature/online-summary/online-summary.module.ts @@ -0,0 +1,36 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import { OnlineSummaryRouter } from './router/router'; +import { OnlineSummaryContainer } from './container/online-summary/online-summary.container'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { ListComponent } from './presenter/list/list.component'; +import { DialogComponent } from './presenter/dialog/dialog.component'; + +const routes: Routes = [ + { + path: '', + component: OnlineSummaryRouter, + children: [ + { + path: '', + component: OnlineSummaryContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + OnlineSummaryRouter, + OnlineSummaryContainer, + ListComponent, + DialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class OnlineSummaryModule { } diff --git a/src/app/feature/online-summary/presenter/dialog/dialog.component.html b/src/app/feature/online-summary/presenter/dialog/dialog.component.html new file mode 100644 index 0000000..65e69a1 --- /dev/null +++ b/src/app/feature/online-summary/presenter/dialog/dialog.component.html @@ -0,0 +1,59 @@ +
+ + +
+ +
+ + + + + กรุณาเลือก + + + {{x.testing_information_name}} + + +
+ + +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + CASH + PAYIN + QRCODE + CREDIT-CARD + + +
+ +
+
+ +
+ + diff --git a/src/app/feature/online-summary/presenter/dialog/dialog.component.scss b/src/app/feature/online-summary/presenter/dialog/dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/online-summary/presenter/dialog/dialog.component.spec.ts b/src/app/feature/online-summary/presenter/dialog/dialog.component.spec.ts new file mode 100644 index 0000000..a32e0ea --- /dev/null +++ b/src/app/feature/online-summary/presenter/dialog/dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DialogComponent } from './dialog.component'; + +describe('DialogComponent', () => { + let component: DialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/online-summary/presenter/dialog/dialog.component.ts b/src/app/feature/online-summary/presenter/dialog/dialog.component.ts new file mode 100644 index 0000000..091840e --- /dev/null +++ b/src/app/feature/online-summary/presenter/dialog/dialog.component.ts @@ -0,0 +1,94 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { tap } from 'rxjs/operators'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-dialog', + templateUrl: './dialog.component.html', + styleUrls: ['./dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DialogComponent implements OnInit { + paymentselect: [] = []; + obj = { + date: null, + start_date: null, + end_date: null, + is_testing_information_report: null, + testing_information_uid: null, + type: null, + is_cash: false, + is_payin: false, + is_qrcode: false, + is_credit_card: false, + } + testingInformationList: any = []; + etest101:boolean = false + etest102:boolean = false + etest103:boolean = false + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.testingInformationSV.getAll().pipe( + tap(x => this.testingInformationList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + + if(this.data){ + if(this.data.type == '101') this.etest101 = true + if(this.data.type == '102') this.etest102 = true + if(this.data.type == '103') this.etest103 = true + } + } + + confirm(){ + if (this.paymentselect.length != 0) { + this.obj.is_cash = false; + this.obj.is_payin = false; + this.obj.is_qrcode = false; + this.obj.is_credit_card = false; + this.paymentselect.forEach(option => { + switch (option) { + case 'CASH': + this.obj.is_cash = true; + break; + case 'PAYIN': + this.obj.is_payin = true; + break; + case 'QRCODE': + this.obj.is_qrcode = true; + break; + case 'CREDIT-CARD': + this.obj.is_credit_card = true; + break; + } + }); + } + console.log(this.obj); + if(this.etest101){ + this.obj.date = this.data.date + this.dialogRef.close({obj:this.obj}) + } + if(this.etest102){ + this.obj.date = this.data.date + this.dialogRef.close({obj:this.obj}) + } + if(this.etest103){ + this.obj.start_date = formatDate(this.obj.start_date, 'yyyy-MM-dd', 'en-US') + this.obj.end_date = formatDate(this.obj.end_date, 'yyyy-MM-dd', 'en-US') + this.dialogRef.close({obj:this.obj}) + } + } + + display(uid){ + if (uid && this.testingInformationList) return this.testingInformationList.find(x => x.testing_information_uid === uid)?.testing_information_name + } + +} diff --git a/src/app/feature/online-summary/presenter/list/list.component.html b/src/app/feature/online-summary/presenter/list/list.component.html new file mode 100644 index 0000000..67433a1 --- /dev/null +++ b/src/app/feature/online-summary/presenter/list/list.component.html @@ -0,0 +1,88 @@ +

รายงานรับเงินออนไลน์

+
+
+
+ + + + + + +
+
+ + + + CASH + PAYIN + QRCODE + CREDIT-CARD + + +
+
+ +
+
+
+
+
+
+

รายการนำเข้า

+

ยอดรวม {{total()}} บาท

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} รหัสผู้เข้าสอบ {{x.student_code}} ชื่อ-นามสกุล {{x.full_name}} ref1 {{x.ref1}} เลขที่ใบเสร็จ {{x.payment_code}} จำนวนเงิน {{x.testing_fee}} ช่องทางชำระเงิน {{x.payment_method}} วันที่ชำระเงิน {{x.payment_datetime | thaidate}} วันที่ลงทะเบียน {{x.created_datetime | thaidate}}
+ +
+
+ +   + +   + +
+ +
+ + + diff --git a/src/app/feature/online-summary/presenter/list/list.component.scss b/src/app/feature/online-summary/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/online-summary/presenter/list/list.component.spec.ts b/src/app/feature/online-summary/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/online-summary/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/online-summary/presenter/list/list.component.ts b/src/app/feature/online-summary/presenter/list/list.component.ts new file mode 100644 index 0000000..73cd62e --- /dev/null +++ b/src/app/feature/online-summary/presenter/list/list.component.ts @@ -0,0 +1,138 @@ +import {formatDate} from '@angular/common'; +import {Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, Output, ViewChild} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {filter, switchMap, tap} from 'rxjs/operators'; +import {BaseList} from 'src/app/core/base/base-list'; +import { + DailyRegisterPaymentTotalService +} from 'src/app/core/service/report/daily-register/daily-register-payment-total.service'; +import {DailyRegisterPaymentService} from 'src/app/core/service/report/daily-register/daily-register-payment.service'; +import { + PeriodRegisterPaymentOnlineService +} from 'src/app/core/service/report/period-register/period-register-payment-online.service'; +import {StudentPaymentService} from 'src/app/core/service/student-payment/student-payment.service'; +import {SweetalertService} from 'src/app/core/service/sweetalert/sweetalert'; +import {DialogComponent} from '../dialog/dialog.component'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit { + paymentselect: [] = []; + @Input() paymentList: any = []; + @Output() confirm = new EventEmitter() + @Output() search = new EventEmitter() + query = { + date: null, + is_cash: false, + is_payin: false, + is_qrcode: false, + is_credit_card: false, + }; + + constructor( + private studentPaymentSV: StudentPaymentService, + private swSV: SweetalertService, + private dailyRegisterSV: DailyRegisterPaymentService, + private dailyRegisterTotalSV: DailyRegisterPaymentTotalService, + private dialog: MatDialog, + private periodRegisterSV: PeriodRegisterPaymentOnlineService, + ) { + super() + } + + ngOnInit(): void { + + } + + ngOnChanges() { + this.paymentList = this.updateMatTable(this.paymentList ? this.paymentList : []) + } + + total() { + const total = this.paymentList.data.reduce((prev, cur) => { + return prev + +cur.testing_fee + }, 0) + return total + } + + onSearch() { + if (this.paymentselect.length != 0) { + this.query.is_cash = false; + this.query.is_payin = false; + this.query.is_qrcode = false; + this.query.is_credit_card = false; + this.paymentselect.forEach(option => { + switch (option) { + case 'CASH': + this.query.is_cash = true; + break; + case 'PAYIN': + this.query.is_payin = true; + break; + case 'QRCODE': + this.query.is_qrcode = true; + break; + case 'CREDIT-CARD': + this.query.is_credit_card = true; + break; + } + }); + } + this.search.emit(this.query) + } + + reportEtest(type: string) { + const obj = { + type: type, + date: formatDate(this.paymentList.data[0].payment_datetime, 'yyyy-MM-dd', 'en-US') + } + const dialogRef = this.dialog.open(DialogComponent, { + width: '500px', + data: obj, + }); + + dialogRef.afterClosed().pipe( + filter(x => x.obj), + switchMap(x => { + if (type == '101') { + console.log(x.obj) + if (x.obj.is_testing_information_report) { + return window.open(this.dailyRegisterSV.etest101InformationOnline(x.obj)) + } else { + return window.open(this.dailyRegisterSV.etest101Online(x.obj)) + } + } + if (type == '102') { + if (x.obj.is_testing_information_report) { + return window.open(this.dailyRegisterTotalSV.etest102InformationOnline(x.obj)) + } else { + return window.open(this.dailyRegisterTotalSV.etest102Online(x.obj)) + } + } + if (type == '103') { + if (x.obj.is_testing_information_report) { + return window.open(this.periodRegisterSV.etest103InformationOnline(x.obj)) + } else { + return window.open(this.periodRegisterSV.etest103Online(x.obj)) + } + } + }) + ).subscribe() + + // const data = {...this.paymentList.data[0]} + // const date = formatDate(data.payment_datetime,'yyyy-MM-dd','en-US') + // const query = { + // date : date + // } + // if(type == '101'){ + // window.open(this.dailyRegisterSV.etest101InformationOnline(query)) + // }else{ + // window.open(this.dailyRegisterTotalSV.etest102InformationOnline(query)) + // } + } + +} diff --git a/src/app/feature/online-summary/router/router.ts b/src/app/feature/online-summary/router/router.ts new file mode 100644 index 0000000..98c41e8 --- /dev/null +++ b/src/app/feature/online-summary/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-confirm-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class OnlineSummaryRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.html b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.html new file mode 100644 index 0000000..9587e68 --- /dev/null +++ b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.html @@ -0,0 +1,4 @@ + + diff --git a/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.scss b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.spec.ts b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.spec.ts new file mode 100644 index 0000000..ad75430 --- /dev/null +++ b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PrintExamCardContainer } from './print-exam-card.container'; + +describe('PrintExamCardContainer', () => { + let component: PrintExamCardContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PrintExamCardContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PrintExamCardContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.ts b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.ts new file mode 100644 index 0000000..dcf38bd --- /dev/null +++ b/src/app/feature/print-exam-card/container/print-exam-card/print-exam-card.container.ts @@ -0,0 +1,25 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-print-exam-card', + templateUrl: './print-exam-card.container.html', + styleUrls: ['./print-exam-card.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PrintExamCardContainer implements OnInit { + testingInfo$ = new Observable() + branch$ = new Observable() + constructor( + private testingInfoSV: TestingInformationService, + private branchSV: BranchService + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfoSV.getAll() + this.branch$ = this.branchSV.getAll() + } + +} diff --git a/src/app/feature/print-exam-card/presenter/info/info.component.html b/src/app/feature/print-exam-card/presenter/info/info.component.html new file mode 100644 index 0000000..c7e94dd --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/info/info.component.html @@ -0,0 +1,78 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ +
+
+
+
+

ข้อมูลการสมัคร

+
+
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+
+ + +
+ +
+ + +
+
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+
diff --git a/src/app/feature/print-exam-card/presenter/info/info.component.scss b/src/app/feature/print-exam-card/presenter/info/info.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/print-exam-card/presenter/info/info.component.spec.ts b/src/app/feature/print-exam-card/presenter/info/info.component.spec.ts new file mode 100644 index 0000000..fead35b --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/info/info.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoComponent } from './info.component'; + +describe('InfoComponent', () => { + let component: InfoComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InfoComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/print-exam-card/presenter/info/info.component.ts b/src/app/feature/print-exam-card/presenter/info/info.component.ts new file mode 100644 index 0000000..35663f8 --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/info/info.component.ts @@ -0,0 +1,45 @@ +import { ThrowStmt } from '@angular/compiler'; +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { tap } from 'rxjs/operators'; +import { CardPrintingService } from 'src/app/core/service/card-print/card-printing.service'; +import { TestingCardService } from 'src/app/core/service/report/exam-card-print/testing-card.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-info', + templateUrl: './info.component.html', + styleUrls: ['./info.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InfoComponent implements OnInit { + query = { + code: null, + test1: null + } + data; + list:any = [] + constructor( + private cardSV: CardPrintingService, + private printSV: TestingCardService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.list = this.cardSV.studentList + } + + onSearch(){ + this.data = this.list.find(x => x.student_code == this.query.code) + if(!this.data) this.swSV.errText('ไม่พบรหัสนักศึกษา') + } + + print(){ + if(!this.data){ + this.swSV.errText('กรุณากรอกรหัสนักศึกษา') + } else{ + const fileURL = this.printSV.print(this.data.tests_uid) + window.open(fileURL) + } + } + +} diff --git a/src/app/feature/print-exam-card/presenter/search/search.component.html b/src/app/feature/print-exam-card/presenter/search/search.component.html new file mode 100644 index 0000000..1b77910 --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/search/search.component.html @@ -0,0 +1,44 @@ + +
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+ +
+ + + + + + +
+
+
+ +
+
diff --git a/src/app/feature/print-exam-card/presenter/search/search.component.scss b/src/app/feature/print-exam-card/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/print-exam-card/presenter/search/search.component.spec.ts b/src/app/feature/print-exam-card/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/print-exam-card/presenter/search/search.component.ts b/src/app/feature/print-exam-card/presenter/search/search.component.ts new file mode 100644 index 0000000..8331fea --- /dev/null +++ b/src/app/feature/print-exam-card/presenter/search/search.component.ts @@ -0,0 +1,57 @@ +import { formatDate } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; +import { Router } from '@angular/router'; +import { tap } from 'rxjs/operators'; +import { CardPrintingService } from 'src/app/core/service/card-print/card-printing.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Input() testingInfo: any = []; + @Input() branch: any = []; + query = { + testing_information_uid: null, + branch_uid: null, + testing_date: null + } + constructor( + private router: Router, + private cardSV: CardPrintingService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + // console.log(this.branch) + // console.log(this.testingInfo) + } + + onSearch(){ + this.query.testing_date = formatDate(this.query.testing_date, 'yyyy-MM-dd', 'en-US') + const query = createQueryStringFromObject(this.query) + // this.router.navigate(["print-exam-card/info"]) + this.cardSV.search('?'+query).pipe( + tap((x:any) => { + if(x.length == 0) this.swSV.errText('ไม่พบข้อมูล') + if(x.length != 0){ + this.router.navigate(["print-exam-card/info"]) + this.cardSV.studentList = x + } + }) + ).subscribe() + } + + display(item:string){ + if (item) return this.testingInfo.find(x => x.testing_information_uid == item)?.testing_information_name + } + + displayBranch(item:string){ + if (item) return this.branch.find(x => x.branch_uid == item)?.branch_name_th + } + +} diff --git a/src/app/feature/print-exam-card/print-exam-card.module.ts b/src/app/feature/print-exam-card/print-exam-card.module.ts new file mode 100644 index 0000000..63e2b7e --- /dev/null +++ b/src/app/feature/print-exam-card/print-exam-card.module.ts @@ -0,0 +1,40 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { PrintExamCardRouter } from './router/router'; +import { PrintExamCardContainer } from './container/print-exam-card/print-exam-card.container'; +import { SearchComponent } from './presenter/search/search.component'; +import { InfoComponent } from './presenter/info/info.component'; + +const routes: Routes = [ + { + path: '', + component: PrintExamCardRouter, + children: [ + { + path: '', + component: PrintExamCardContainer + }, + { + path: 'info', + component: InfoComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + PrintExamCardRouter, + PrintExamCardContainer, + SearchComponent, + InfoComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class PrintExamCardModule { } diff --git a/src/app/feature/print-exam-card/router/router.ts b/src/app/feature/print-exam-card/router/router.ts new file mode 100644 index 0000000..d7587f3 --- /dev/null +++ b/src/app/feature/print-exam-card/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-print-exam-card-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PrintExamCardRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.html b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.html new file mode 100644 index 0000000..9a8f5db --- /dev/null +++ b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.html @@ -0,0 +1,4 @@ + + diff --git a/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.scss b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.spec.ts b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.spec.ts new file mode 100644 index 0000000..69285ba --- /dev/null +++ b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PrintExamResultContainer } from './print-exam-result.container'; + +describe('PrintExamResultContainer', () => { + let component: PrintExamResultContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PrintExamResultContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PrintExamResultContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.ts b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.ts new file mode 100644 index 0000000..6b8fce1 --- /dev/null +++ b/src/app/feature/print-exam-result/container/print-exam-result/print-exam-result.container.ts @@ -0,0 +1,25 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Observable } from 'rxjs'; +import { AcademicSemesterService } from 'src/app/core/service/settings/academic-semester.service'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; + +@Component({ + selector: 'app-print-exam-result', + templateUrl: './print-exam-result.container.html', + styleUrls: ['./print-exam-result.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PrintExamResultContainer implements OnInit { + academicYearList$ = new Observable() + academicSemList$ = new Observable() + constructor( + private acdmYearSV : AcademicYearService, + private acdmSemSV : AcademicSemesterService + ) { } + + ngOnInit(): void { + this.academicYearList$ = this.acdmYearSV.getAll() + this.academicSemList$ = this.acdmSemSV.getAll() + } + +} diff --git a/src/app/feature/print-exam-result/presenter/search/search.component.html b/src/app/feature/print-exam-result/presenter/search/search.component.html new file mode 100644 index 0000000..20cc614 --- /dev/null +++ b/src/app/feature/print-exam-result/presenter/search/search.component.html @@ -0,0 +1,134 @@ + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + + + + + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
+
+
+
+

ตรวจสอบผลการสอบทั้งหมด

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อผู้เข้าสอบ {{x.student_name}} รหัสวิชา {{x.subject_code}} ชื่อวิชา (TH) {{x.subject_name_th}} วันที่สอบ {{x.testing_date | thaidate}} คาบสอบ {{x.period_id}} ผลการสอบ {{x.grade}} ปีการศึกษา {{x.academic_year_name}} ภาคการศึกษา {{x.academic_semester_name}} +
+ +
+
+ +
+
+
+ diff --git a/src/app/feature/print-exam-result/presenter/search/search.component.scss b/src/app/feature/print-exam-result/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/print-exam-result/presenter/search/search.component.spec.ts b/src/app/feature/print-exam-result/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/print-exam-result/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/print-exam-result/presenter/search/search.component.ts b/src/app/feature/print-exam-result/presenter/search/search.component.ts new file mode 100644 index 0000000..8011c90 --- /dev/null +++ b/src/app/feature/print-exam-result/presenter/search/search.component.ts @@ -0,0 +1,65 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef} from '@angular/core'; +import {tap} from 'rxjs/operators'; +import {BaseList} from 'src/app/core/base/base-list'; +import {TestingScoreService} from 'src/app/core/service/card-print/testing-score.service'; +import {ExamResultPrintService} from 'src/app/core/service/report/exam-result-print/exam-result-print.service'; +import {createQueryStringFromObject} from 'src/app/shared/util/func'; +import {formatDate} from "@angular/common"; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent extends BaseList implements OnInit { + query = { + academic_year_code: null, + academic_semester_code: null, + student_code: null, + test_date: null, + period: null, + } + result: any = []; + @Input() academicYearList: any = []; + @Input() academicSemList: any = []; + + constructor( + private testingScoreSV: TestingScoreService, + private cdr: ChangeDetectorRef, + private resultSV: ExamResultPrintService + ) { + super() + } + + ngOnInit(): void { + } + + print(x) { + const fileURL = this.resultSV.print(x.tests_uid) + window.open(fileURL) + } + + onSearch() { + if (this.query.test_date !== null) { + this.query.test_date = formatDate(this.query.test_date, 'yyyy-MM-dd', 'en-US') + } + const query = createQueryStringFromObject(this.query); + this.testingScoreSV.search('?' + query).pipe( + tap(x => this.result = this.updateMatTable(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + clear() { + this.query = { + academic_year_code: null, + academic_semester_code: null, + student_code: null, + test_date: null, + period: null, + } + this.result = this.updateMatTable([]) + } + +} diff --git a/src/app/feature/print-exam-result/print-exam-result.module.ts b/src/app/feature/print-exam-result/print-exam-result.module.ts new file mode 100644 index 0000000..7144db5 --- /dev/null +++ b/src/app/feature/print-exam-result/print-exam-result.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { PrintExamResultRouter } from './router/router'; +import { PrintExamResultContainer } from './container/print-exam-result/print-exam-result.container'; +import { SearchComponent } from './presenter/search/search.component'; + +const routes: Routes = [ + { + path: '', + component: PrintExamResultRouter, + children: [ + { + path: '', + component: PrintExamResultContainer + }, + + ] + } +]; + +@NgModule({ + declarations: [ + PrintExamResultRouter, + PrintExamResultContainer, + SearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class PrintExamResultModule { } diff --git a/src/app/feature/print-exam-result/router/router.ts b/src/app/feature/print-exam-result/router/router.ts new file mode 100644 index 0000000..dbc2287 --- /dev/null +++ b/src/app/feature/print-exam-result/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-print-exam-result-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PrintExamResultRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/report/container/report/report.container.html b/src/app/feature/report/container/report/report.container.html new file mode 100644 index 0000000..cae9747 --- /dev/null +++ b/src/app/feature/report/container/report/report.container.html @@ -0,0 +1,8 @@ + + diff --git a/src/app/feature/report/container/report/report.container.scss b/src/app/feature/report/container/report/report.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/container/report/report.container.spec.ts b/src/app/feature/report/container/report/report.container.spec.ts new file mode 100644 index 0000000..410ed0a --- /dev/null +++ b/src/app/feature/report/container/report/report.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportContainer } from './report.container'; + +describe('ReportContainer', () => { + let component: ReportContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/container/report/report.container.ts b/src/app/feature/report/container/report/report.container.ts new file mode 100644 index 0000000..dc0e05e --- /dev/null +++ b/src/app/feature/report/container/report/report.container.ts @@ -0,0 +1,760 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {CandidateService} from '../../../../core/service/report/candidate/candidate.service'; +import {CandidateRegisteredByCenterService} from '../../../../core/service/report/candidate-registered-by-center/candidate-registered-by-center.service'; +import {CandidateRegisteredBySubjectService} from '../../../../core/service/report/candidate-registered-by-subject/candidate-registered-by-subject.service'; +import {CandidateSubjectService} from '../../../../core/service/report/candidate-subject/candidate-subject.service'; +import {PaymentAndApplicationByCenterService} from '../../../../core/service/report/payment-and-application-by-center/payment-and-application-by-center.service'; +import {PaymentAndApplicationBySubjectService} from '../../../../core/service/report/payment-and-application-by-subject/payment-and-application-by-subject.service'; +import {SettingTestingCenterService} from '../../../../core/service/report/setting-testing-center/setting-testing-center.service'; +import {SettingTestingRoomService} from '../../../../core/service/report/setting-testing-room/setting-testing-room.service'; +import {SummaryCandidateService} from '../../../../core/service/report/summary-candidate/summary-candidate.service'; +import {TestingCenterInformationService} from '../../../../core/service/report/testing-center-information/testing-center-information.service'; +import {TestingRegistrationService} from '../../../../core/service/report/testing-registration/testing-registration.service'; +import {TestingSeatAndRoomService} from '../../../../core/service/report/testing-seat-and-room/testing-seat-and-room.service'; +import {SignatureExaminationService} from '../../../../core/service/report/signature-examination/signature-examination.service'; +import {RegisterByPaymentService} from '../../../../core/service/report/register-by-payment/register-by-payment.service'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {SeparatedByExamCenterService} from '../../../../core/service/report/separated-by-exam-center/separated-by-exam-center.service'; +import {ExamTotalService} from '../../../../core/service/report/exam_total/exam-total.service'; +import {TesingSubjectService} from '../../../../core/service/report/testing-subject/tesing-subject.service'; +import {TestingRoomService} from '../../../../core/service/report/testing-room/testing-room.service'; + +@Component({ + selector: 'app-report', + templateUrl: './report.container.html', + styleUrls: ['./report.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportContainer implements OnInit { + fileURL: any = null; + constructor( + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private candidateReportSV: CandidateService, + private candidateRegisBySubReportSV: CandidateRegisteredBySubjectService, + private candidateRegisByCenReportSV: CandidateRegisteredByCenterService, + private candidateSubjectSV: CandidateSubjectService, + private paymentANDappByCenReportSV: PaymentAndApplicationByCenterService, + private paymentANDappBySubReportSV: PaymentAndApplicationBySubjectService, + private settingTestingCenterSV: SettingTestingCenterService, + private settingTestingRoomSV: SettingTestingRoomService, + private registerByPaymentReportSV: RegisterByPaymentService, + private summaryCandidateSV: SummaryCandidateService, + private signatureExamReportSV: SignatureExaminationService, + private testingCenterInformationSV: TestingCenterInformationService, + private testingRegisterReportSV: TestingRegistrationService, + private testingSeatRoomReportSV: TestingSeatAndRoomService, + private separatedByExamCenterSV: SeparatedByExamCenterService, + private examTotalSV: ExamTotalService, + private testingSubjectSV: TesingSubjectService, + private testingRoomSV: TestingRoomService, + ) { } + + ngOnInit(): void { + } + + excel(choose){ + const reportId = choose.reportId; + const query = choose.query; + switch (reportId) { + case 1: { + console.log(query); + this.candidateReportSV.getExcelReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date)).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 2: { + console.log(query); + this.summaryCandidateSV.getExcelReport( + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 3: { + console.log(query); + this.testingRegisterReportSV.getExcelReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 4: { + console.log(query); + this.candidateRegisBySubReportSV.getExcelReport( + query.subject_uid, + query.academic_year_uid, + query.academic_semester_uid, + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 5: { + console.log(query); + this.candidateRegisByCenReportSV.getExcelReport( + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.subject_uid).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 6: { + console.log(query); + this.paymentANDappBySubReportSV.getExcelReport( + query.academic_year_uid, + query.academic_semester_uid, + query.subject_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 7: { + console.log(query); + this.paymentANDappByCenReportSV.getExcelReport( + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.subject_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 8: { + console.log(query); + this.registerByPaymentReportSV.getExcelReport( + query.testing_information_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 9: { + console.log(query); + this.testingCenterInformationSV.getExcelReport( + query.testing_information_uid, + query.subject_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 10: { + console.log(query); + this.testingSeatRoomReportSV.getExcelReport( + query.testing_information_uid, + query.branch_uid, + query.period_id, + this.convert(query.test_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 12: { + console.log(query); + this.signatureExamReportSV.getExcelReport( + query.testing_information_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.period_id, + this.convert(query.test_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 13: { + this.candidateSubjectSV.getExcelReport( + query.academic_year_uid, + query.academic_semester_uid, + query.subject_uid + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 14: { + console.log(query); + this.settingTestingCenterSV.getExcelReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 15: { + console.log(query); + this.settingTestingRoomSV.getExcelReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 16: { + console.log(query); + this.settingTestingRoomSV.getExcelReport16( + query.subject_uid, + query.testing_information_uid, + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 17: { + this.settingTestingRoomSV.getExcelReport17( + query.testing_information_uid, + query.academic_year_code, + query.academic_semester_code, + query.branch_uid, + query.testing_center_uid, + query.room_name_th, + ).subscribe( + res => { + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 18: { + this.separatedByExamCenterSV.getExcelReport( + query.testing_information_uid, + query.subject_uid, + query.branch_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 19: { + this.examTotalSV.getExcelReport( + query.testing_information_uid, + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 20: { + this.testingRoomSV.getExcelReport( + query.testing_information_uid, + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 21: { + this.testingSubjectSV.getExcelReport( + query.testing_information_uid, + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + } + } + + search(choose){ + console.log(choose); + const reportId = choose.reportId; + const query = choose.query; + switch (reportId) { + case 1: { + console.log(query); + this.candidateReportSV.getPdfReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date)).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 2: { + console.log(query); + this.summaryCandidateSV.getPdfReport( + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 3: { + console.log(query); + this.testingRegisterReportSV.getPdfReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 4: { + console.log(query); + this.candidateRegisBySubReportSV.getPdfReport( + query.subject_uid, + query.academic_year_uid, + query.academic_semester_uid, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 5: { + console.log(query); + this.candidateRegisByCenReportSV.getPdfReport( + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.subject_uid).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 6: { + console.log(query); + this.paymentANDappBySubReportSV.getPdfReport( + query.academic_year_uid, + query.academic_semester_uid, + query.subject_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 7: { + console.log(query); + this.paymentANDappByCenReportSV.getPdfReport( + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.subject_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 8: { + console.log(query); + this.registerByPaymentReportSV.getPdfReport( + query.testing_information_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 9: { + console.log(query); + this.testingCenterInformationSV.getPdfReport( + query.testing_information_uid, + query.subject_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 10: { + console.log(query); + this.testingSeatRoomReportSV.getPdfReport( + query.testing_information_uid, + query.branch_uid, + query.period_id, + this.convert(query.test_date) + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 12: { + console.log(query); + this.signatureExamReportSV.getPdfReport( + query.testing_information_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + query.period_id, + this.convert(query.test_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 13: { + this.candidateSubjectSV.getPdfReport( + query.academic_year_uid, + query.academic_semester_uid, + query.subject_uid + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 14: { + console.log(query); + this.settingTestingCenterSV.getPdfReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล'); + }); + break; + } + case 15: { + console.log(query); + this.settingTestingRoomSV.getPdfReport( + query.testing_information_uid, + query.academic_year_uid, + query.academic_semester_uid, + query.branch_uid, + query.testing_field_uid, + query.testing_center_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 16: { + console.log(query); + this.settingTestingRoomSV.getPdfReport16( + query.subject_uid, + query.testing_information_uid, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 17: { + this.settingTestingRoomSV.getPdfReport17( + query.testing_information_uid, + query.academic_year_code, + query.academic_semester_code, + query.branch_uid, + query.testing_center_uid, + query.room_name_th, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 18: { + this.separatedByExamCenterSV.getPdfReport( + query.testing_information_uid, + query.subject_uid, + query.branch_uid, + this.convert(query.from_date), + this.convert(query.to_date), + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 19: { + this.examTotalSV.getPdfReport( + query.testing_information_uid, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 20: { + this.testingRoomSV.getPdfReport( + query.testing_information_uid, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + case 21: { + this.testingSubjectSV.getPdfReport( + query.testing_information_uid, + ).subscribe( + res => { + const fileURL = URL.createObjectURL(res); + this.fileURL = fileURL; + this.cdr.detectChanges(); + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + break; + } + } + } + + convert(str) { + var date = new Date(str), + mnth = ("0" + (date.getMonth() + 1)).slice(-2), + day = ("0" + date.getDate()).slice(-2); + return [date.getFullYear(), mnth, day].join("-"); + } + +} diff --git a/src/app/feature/report/presenter/report-preview/report-preview.component.html b/src/app/feature/report/presenter/report-preview/report-preview.component.html new file mode 100644 index 0000000..f75a0c3 --- /dev/null +++ b/src/app/feature/report/presenter/report-preview/report-preview.component.html @@ -0,0 +1,6 @@ +
+
+ +
+
+ diff --git a/src/app/feature/report/presenter/report-preview/report-preview.component.scss b/src/app/feature/report/presenter/report-preview/report-preview.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-preview/report-preview.component.spec.ts b/src/app/feature/report/presenter/report-preview/report-preview.component.spec.ts new file mode 100644 index 0000000..b6a7588 --- /dev/null +++ b/src/app/feature/report/presenter/report-preview/report-preview.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportPreviewComponent } from './report-preview.component'; + +describe('ReportPreviewComponent', () => { + let component: ReportPreviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportPreviewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportPreviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-preview/report-preview.component.ts b/src/app/feature/report/presenter/report-preview/report-preview.component.ts new file mode 100644 index 0000000..48ba6a3 --- /dev/null +++ b/src/app/feature/report/presenter/report-preview/report-preview.component.ts @@ -0,0 +1,17 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input} from '@angular/core'; + +@Component({ + selector: 'app-report-preview', + templateUrl: './report-preview.component.html', + styleUrls: ['./report-preview.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportPreviewComponent implements OnInit { + @Input() URLfile: any = []; + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.html b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.html new file mode 100644 index 0000000..e7f53e9 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.html @@ -0,0 +1,106 @@ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
+ + + diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.scss b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.spec.ts b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.spec.ts new file mode 100644 index 0000000..fff01e9 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportCandidateRegisterByCenterComponent } from './report-candidate-register-by-center.component'; + +describe('ReportCandidateRegisterByCenterComponent', () => { + let component: ReportCandidateRegisterByCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportCandidateRegisterByCenterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportCandidateRegisterByCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.ts b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.ts new file mode 100644 index 0000000..8264365 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component.ts @@ -0,0 +1,121 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../core/service/settings/academic-semester.service'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {SubjectsService} from '../../../../../core/service/settings/subjects.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-candidate-register-by-center', + templateUrl: './report-candidate-register-by-center.component.html', + styleUrls: ['./report-candidate-register-by-center.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportCandidateRegisterByCenterComponent implements OnInit { + @Input() TestcenterLists: any = []; + @Input() TestFieldLists: any = []; + @Input() TestRoomLists: any = []; + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + private academicYearSV: AcademicYearService, + private academicSemSV: AcademicSemesterService, + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + private subjectSV: SubjectsService, + ) { } + + ngOnInit(): void { + console.log(this.TestcenterLists); + this.testcenterSV.getAll().subscribe( + result => { + this.TestRoomLists = result; + } + ); + this.subjectSV.getAll().subscribe( + result => { + this.SubjectLists = result; + } + ); + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub?.subject_name_th + } + + filterTestingFiled(data){ + this.testingFieldSV.getByBrandID(data).subscribe( + result => { + const TestFieldLists = result; + this.TestFieldLists = TestFieldLists + } + ) + } + + filterTestingRoom(data){ + this.testcenterSV.getByFiledID(data).subscribe( + result => { + const TestRoomLists = result; + this.TestRoomLists = TestRoomLists + } + ) + } +} diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.html b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.html new file mode 100644 index 0000000..e0a35ef --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.html @@ -0,0 +1,45 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + + +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.scss b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.spec.ts b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.spec.ts new file mode 100644 index 0000000..eed63a7 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportCandidateRegisterBySubjectComponent } from './report-candidate-register-by-subject.component'; + +describe('ReportCandidateRegisterBySubjectComponent', () => { + let component: ReportCandidateRegisterBySubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportCandidateRegisterBySubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportCandidateRegisterBySubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.ts b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.ts new file mode 100644 index 0000000..c8b5d66 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component.ts @@ -0,0 +1,71 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-candidate-register-by-subject', + templateUrl: './report-candidate-register-by-subject.component.html', + styleUrls: ['./report-candidate-register-by-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportCandidateRegisterBySubjectComponent implements OnInit { + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + + query = { + subject_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + console.log(this.SubjectLists) + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + subject_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub?.subject_name_th + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.html b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.html new file mode 100644 index 0000000..e0a35ef --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.html @@ -0,0 +1,45 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + + +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.scss b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.spec.ts b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.spec.ts new file mode 100644 index 0000000..c9fd038 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportCandidateSubjectComponent } from './report-candidate-subject.component'; + +describe('ReportCandidateSubjectComponent', () => { + let component: ReportCandidateSubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportCandidateSubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportCandidateSubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.ts b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.ts new file mode 100644 index 0000000..35fd6a7 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-subject/report-candidate-subject.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-candidate-subject', + templateUrl: './report-candidate-subject.component.html', + styleUrls: ['./report-candidate-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportCandidateSubjectComponent implements OnInit { + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + academic_year_uid: null, + academic_semester_uid: null, + subject_uid: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + academic_year_uid: null, + academic_semester_uid: null, + subject_uid: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub?.subject_name_th + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.html b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.html new file mode 100644 index 0000000..9f4bf1a --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.html @@ -0,0 +1,86 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ + + +
+
+ + + +
+
+ + + + diff --git a/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.scss b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.spec.ts b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.spec.ts new file mode 100644 index 0000000..fdb9373 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportCandidateSummaryComponent } from './report-candidate-summary.component'; + +describe('ReportCandidateSummaryComponent', () => { + let component: ReportCandidateSummaryComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportCandidateSummaryComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportCandidateSummaryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.ts b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.ts new file mode 100644 index 0000000..d1f19ef --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate-summary/report-candidate-summary.component.ts @@ -0,0 +1,154 @@ +import {Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, Output, ChangeDetectorRef} from '@angular/core'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import {TestingFieldService} from "../../../../../core/service/settings/testing-field.service"; +import {TestingCenterService} from "../../../../../core/service/TestingCenter/testing-center.service"; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-candidate-summary', + templateUrl: './report-candidate-summary.component.html', + styleUrls: ['./report-candidate-summary.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportCandidateSummaryComponent implements OnInit { + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Input() TestingInformationLists = []; + @Input() TestcenterLists: any = []; + @Input() TestRoomLists: any = []; + @Input() TestFieldLists: any = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + isUseTestCenterList = false; + + curSub; + query = { + testing_information_uid: null, + academic_year_code: null, + academic_semester_code: null, + branch_uid: null, + testing_center_uid: null, + room_name_th: null, + }; + constructor( + private swSV: SweetalertService, + private testingFieldSV: TestingFieldService, + private testcenterSV: TestingCenterService, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + + ) { } + + ngOnInit(): void { + console.log(this.TestRoomLists); + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + + + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + academic_year_code: null, + academic_semester_code: null, + branch_uid: null, + testing_center_uid: null, + room_name_th: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + filterTestingFiled(data){ + this.testingFieldSV.getByBrandID(data).subscribe( + result => { + console.log(result) + const TestFieldLists = result; + this.TestFieldLists = TestFieldLists + } + ) + } + + filterTestingRoom(data){ + console.log(data) + this.testcenterSV.getByFiledID(data).subscribe( + result => { + console.log(result) + const TestRoomLists = result; + this.TestRoomLists = TestRoomLists + } + ) + } + + chooseInfor(uidInformation){ + this.testingInformationSV.get(uidInformation).subscribe( + result => { + console.log(result); + const data:any = result; + this.SubjectLists = data.testing_subjects; + this.cdr.detectChanges(); + } + ); + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_code = academicyearList.academic_year_code; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_code = AcademicsemesterList.academic_semester_code; + } + this.testingInformationSV.get(testinforList.testing_information_uid).subscribe( + result => { + const dataInfor: any = result; + this.isUseTestCenterList = true; + console.log(dataInfor) + this.TestcenterLists = dataInfor.testing_rooms.filter((thing, i, arr) => + arr.findIndex(t => t.branch_uid === thing.branch_uid) === i + ); + this.cdr.detectChanges() + } + ); + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.html b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.html new file mode 100644 index 0000000..3be6c92 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.html @@ -0,0 +1,67 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+ +
+ +
+
+ + + +
+
+ + + + diff --git a/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.scss b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.spec.ts b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.spec.ts new file mode 100644 index 0000000..4fcfc52 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportCandidateComponent } from './report-candidate.component'; + +describe('ReportCandidateComponent', () => { + let component: ReportCandidateComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportCandidateComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportCandidateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.ts b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.ts new file mode 100644 index 0000000..a0bb9e6 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-candidate/report-candidate.component.ts @@ -0,0 +1,110 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, OnChanges} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../core/service/settings/academic-semester.service'; + +@Component({ + selector: 'app-report-candidate', + templateUrl: './report-candidate.component.html', + styleUrls: ['./report-candidate.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportCandidateComponent implements OnInit, OnChanges { + @Input() TestingInformationLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + curSub; + + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + + ) { } + + ngOnInit(): void { + } + + ngOnChanges(){ + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + clear(){ + this.query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + convert(str) { + var date = new Date(str), + mnth = ("0" + (date.getMonth() + 1)).slice(-2), + day = ("0" + date.getDate()).slice(-2); + return [date.getFullYear(), mnth, day].join("-"); + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_uid = academicyearList.academic_year_uid; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + } + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.html b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.html new file mode 100644 index 0000000..baba619 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.html @@ -0,0 +1,23 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.scss b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.spec.ts b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.spec.ts new file mode 100644 index 0000000..20518ae --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportExamDetailComponent } from './report-exam-detail.component'; + +describe('ReportExamDetailComponent', () => { + let component: ReportExamDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportExamDetailComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportExamDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.ts b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.ts new file mode 100644 index 0000000..2f7ff23 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-detail/report-exam-detail.component.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, ChangeDetectorRef} from '@angular/core'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-exam-detail', + templateUrl: './report-exam-detail.component.html', + styleUrls: ['./report-exam-detail.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportExamDetailComponent implements OnInit { + isUseTestCenterList = false; + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + }; + private curSub: any; + private curSub2: any; + constructor( + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingInforSV: TestingInformationService, + ) { } + + ngOnInit(): void { + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.html b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.html new file mode 100644 index 0000000..a349cd5 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.html @@ -0,0 +1,64 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.scss b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.spec.ts b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.spec.ts new file mode 100644 index 0000000..9ef8055 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportExamResultComponent } from './report-exam-result.component'; + +describe('ReportExamResultComponent', () => { + let component: ReportExamResultComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportExamResultComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportExamResultComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.ts b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.ts new file mode 100644 index 0000000..2898f55 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-result/report-exam-result.component.ts @@ -0,0 +1,124 @@ +import {Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, Output, ChangeDetectorRef} from '@angular/core'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-exam-result', + templateUrl: './report-exam-result.component.html', + styleUrls: ['./report-exam-result.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportExamResultComponent implements OnInit { + @Input() SubjectLists: any = []; + @Input() PeriodLists = []; + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + curSub; + curSub2; + query = { + subject_uid: null, + testing_information_uid: null + }; + constructor( + private swSV: SweetalertService, + private testingInformationSV: TestingInformationService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + console.log(this.PeriodLists); + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + console.log(this.query); + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + subject_uid: null, + testing_information_uid: null + }; + } + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + displaySubject(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub2?.subject_name_th + } + + chooseInfor(uidInformation){ + console.log(uidInformation); + this.testingInformationSV.get(uidInformation).subscribe( + result => { + console.log(result); + const data:any = result; + this.SubjectLists = data.testing_subjects; + } + ); + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + this.cdr.detectChanges() + // console.log(this.SubjectLists); + } +} diff --git a/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.html b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.html new file mode 100644 index 0000000..baba619 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.html @@ -0,0 +1,23 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.scss b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.spec.ts b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.spec.ts new file mode 100644 index 0000000..4a8c732 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportExamSubjectComponent } from './report-exam-subject.component'; + +describe('ReportExamSubjectComponent', () => { + let component: ReportExamSubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportExamSubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportExamSubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.ts b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.ts new file mode 100644 index 0000000..a5fe939 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-subject/report-exam-subject.component.ts @@ -0,0 +1,66 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, ChangeDetectorRef} from '@angular/core'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-exam-subject', + templateUrl: './report-exam-subject.component.html', + styleUrls: ['./report-exam-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportExamSubjectComponent implements OnInit { + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + }; + private curSub: any; + private curSub2: any; + constructor( + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingInforSV: TestingInformationService, + ) { } + + ngOnInit(): void { + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.html b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.html new file mode 100644 index 0000000..baba619 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.html @@ -0,0 +1,23 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.scss b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.spec.ts b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.spec.ts new file mode 100644 index 0000000..b8b01ef --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportExamTotalComponent } from './report-exam-total.component'; + +describe('ReportExamTotalComponent', () => { + let component: ReportExamTotalComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportExamTotalComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportExamTotalComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.ts b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.ts new file mode 100644 index 0000000..5d84f23 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-exam-total/report-exam-total.component.ts @@ -0,0 +1,62 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter} from '@angular/core'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-exam-total', + templateUrl: './report-exam-total.component.html', + styleUrls: ['./report-exam-total.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportExamTotalComponent implements OnInit { + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.html b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.html new file mode 100644 index 0000000..fcc43a9 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.html @@ -0,0 +1,66 @@ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+ +
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.scss b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.spec.ts b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.spec.ts new file mode 100644 index 0000000..90a4fe6 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportPaymentAndAppByCenterComponent } from './report-payment-and-app-by-center.component'; + +describe('ReportPaymentAndAppByCenterComponent', () => { + let component: ReportPaymentAndAppByCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportPaymentAndAppByCenterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportPaymentAndAppByCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.ts b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.ts new file mode 100644 index 0000000..1906043 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component.ts @@ -0,0 +1,69 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-payment-and-app-by-center', + templateUrl: './report-payment-and-app-by-center.component.html', + styleUrls: ['./report-payment-and-app-by-center.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportPaymentAndAppByCenterComponent implements OnInit { + + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + + query = { + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.html b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.html new file mode 100644 index 0000000..584b841 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.html @@ -0,0 +1,78 @@ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+ +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.scss b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.spec.ts b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.spec.ts new file mode 100644 index 0000000..16a202b --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportPaymentAndAppBySubjectComponent } from './report-payment-and-app-by-subject.component'; + +describe('ReportPaymentAndAppBySubjectComponent', () => { + let component: ReportPaymentAndAppBySubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportPaymentAndAppBySubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportPaymentAndAppBySubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.ts b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.ts new file mode 100644 index 0000000..9c02787 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component.ts @@ -0,0 +1,74 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-payment-and-app-by-subject', + templateUrl: './report-payment-and-app-by-subject.component.html', + styleUrls: ['./report-payment-and-app-by-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportPaymentAndAppBySubjectComponent implements OnInit { + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + + query = { + academic_year_uid: null, + academic_semester_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + academic_year_uid: null, + academic_semester_uid: null, + subject_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub?.subject_name_th + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.html b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.html new file mode 100644 index 0000000..ae00381 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.html @@ -0,0 +1,49 @@ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + + + +
+ +
+ + +
+
+ +
+
+ + + +
+
+
diff --git a/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.scss b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.spec.ts b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.spec.ts new file mode 100644 index 0000000..2957967 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportReceiptComponent } from './report-receipt.component'; + +describe('ReportReceiptComponent', () => { + let component: ReportReceiptComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportReceiptComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportReceiptComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.ts b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.ts new file mode 100644 index 0000000..26277e4 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-receipt/report-receipt.component.ts @@ -0,0 +1,65 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-receipt', + templateUrl: './report-receipt.component.html', + styleUrls: ['./report-receipt.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportReceiptComponent implements OnInit { + + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + student_code: null, + branch_name_th: null, + testing_field_name_th: null, + testing_room_name_th: null, + testing_datetime: null, + period_id: null, + }; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + + clear(){ + this.query = { + student_code: null, + branch_name_th: null, + testing_field_name_th: null, + testing_room_name_th: null, + testing_datetime: null, + period_id: null, + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.html b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.html new file mode 100644 index 0000000..f498687 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.html @@ -0,0 +1,43 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.scss b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.spec.ts b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.spec.ts new file mode 100644 index 0000000..4b968b0 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportRegisterByPaymentComponent } from './report-register-by-payment.component'; + +describe('ReportRegisterByPaymentComponent', () => { + let component: ReportRegisterByPaymentComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportRegisterByPaymentComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportRegisterByPaymentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.ts b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.ts new file mode 100644 index 0000000..cbe5ec4 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-register-by-payment/report-register-by-payment.component.ts @@ -0,0 +1,93 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-register-by-payment', + templateUrl: './report-register-by-payment.component.html', + styleUrls: ['./report-register-by-payment.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportRegisterByPaymentComponent implements OnInit { + @Input() AcademicYear = []; + @Input() TestingInformationLists = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + + query = { + testing_information_uid: null, + from_date: null, + to_date: null, + }; + private curSub: any; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + // console.log(testinforList) + // const academicyearList = this.AcademicYear.find((member) => { + // return member.academic_year_code === testinforList.academic_year_code; + // }); + // const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + // return member.academic_semester_code === testinforList.academic_semester_code; + // }); + // if (academicyearList.academic_year_uid !== null){ + // this.query.academic_year_uid = academicyearList.academic_year_uid; + // } + // if (AcademicsemesterList.academic_semester_uid !== null){ + // this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + // } + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-search.component.html b/src/app/feature/report/presenter/report-search/report-search.component.html new file mode 100644 index 0000000..3fd1150 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-search.component.html @@ -0,0 +1,181 @@ +

รายงาน

+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ diff --git a/src/app/feature/report/presenter/report-search/report-search.component.scss b/src/app/feature/report/presenter/report-search/report-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-search.component.spec.ts b/src/app/feature/report/presenter/report-search/report-search.component.spec.ts new file mode 100644 index 0000000..47c5095 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSearchComponent } from './report-search.component'; + +describe('ReportSearchComponent', () => { + let component: ReportSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-search.component.ts b/src/app/feature/report/presenter/report-search/report-search.component.ts new file mode 100644 index 0000000..b07535a --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-search.component.ts @@ -0,0 +1,129 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {AcademicYearService} from '../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../core/service/settings/academic-semester.service'; +import {TestingCenterService} from '../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../core/service/settings/testing-field.service'; +import {SubjectsService} from '../../../../core/service/settings/subjects.service'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; +import {BranchService} from "../../../../core/service/settings/branch.service"; + +@Component({ + selector: 'app-report-search', + templateUrl: './report-search.component.html', + styleUrls: ['./report-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSearchComponent implements OnInit { + reportId = 0; + TestingInformationLists = []; + AcademicYear = []; + AcademicsemesterMock = []; + TestcenterLists: any = []; + TestFieldLists = []; + TestRoomLists = []; + SubjectLists = []; + PeriodLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + statusMock = [ + {id: 1, name: 'รายงานใบสมัคร'}, + {id: 2, name: 'รายงานสรุปจำนวนผู้สมัครตามภาคการศึกษา'}, + {id: 3, name: 'รายงานใบลงทะเบียนสอบ'}, + {id: 4, name: 'รายงานสรุปจำนวนผู้ลงทะเบียนสอบ แยกตามกระบวนวิชา'}, + {id: 5, name: 'รายงานสรุปจำนวนผู้ลงทะเบียนสอบ แยกตามศูนย์สอบ'}, + {id: 6, name: 'รายงานสรุปสถานะการชำระเงินและใบสมัคร แยกตามกระบวนวิชา'}, + {id: 7, name: 'รายงานสรุปสถานะการชำระเงินและใบสมัคร แยกตามศูนย์สอบ'}, + {id: 8, name: 'รายงานแสดงรายชื่อผู้ลงทะเบียนสอบแยกตามสถานะการชำระเงินและใบสมัคร'}, + {id: 9, name: 'รายงานข้อมูลศูนย์สอบ สนามสอบ ห้องสอบ'}, + {id: 10, name: 'ใบประกาศเลขที่นั่งสอบและสถานที่สอบ'}, + {id: 12, name: 'ใบลงลายมือชื่อเข้าสอบ'}, + // {id: 13, name: 'รายงานสรุปจำนวนผู้ลงทะเบียนสอบ แยกตามกระบวนวิชา'}, + {id: 14, name: 'การจัดสนามสอบ'}, + {id: 15, name: 'สำหรับการจัดห้องสอบ'}, + {id: 16, name: 'รายงานผลสอบตามกระบวนวิชา'}, + {id: 17, name: 'รายงานสรุปจำนวนผู้เข้าสอบ ผู้ขาดสอบ ผู้สอบผ่าน ผู้สอบไม่ผ่าน'}, + {id: 18, name: 'รายงานสรุปผลสอบตามกระบวนวิชา แยกตามศูนย์สอบ'}, + {id: 19, name: 'สรุปยอดเข้าสอบตามกระบวนวิชา'}, + {id: 20, name: 'ข้อมูลห้องสอบที่เปิดสอบในแต่ละรอบ'}, + {id: 21, name: 'วิชาสอบที่เปิดสอบในแต่ละรอบ'}, + ]; + + constructor( + private academicYearSV: AcademicYearService, + private branchSV: BranchService, + private academicSemSV: AcademicSemesterService, + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + private subjectSV: SubjectsService, + private testinginformationSV: TestingInformationService, + ) { } + + ngOnInit(): void { + this.testinginformationSV.getAll().subscribe( + result => { + this.TestingInformationLists = result; + this.TestingInformationLists = this.TestingInformationLists.filter((x) => { + return x.is_main === true; + }); + } + ); + this.academicYearSV.getAll().subscribe( + result => { + this.AcademicYear = result; + } + ); + this.academicSemSV.getAll().subscribe( + result => { + this.AcademicsemesterMock = result; + console.log(result); + } + ); + this.branchSV.getAllStatus1().subscribe( + result => { + this.TestcenterLists = result; + } + ); + // this.testcenterSV.getAll().subscribe( + // result => { + // this.TestcenterLists = result; + // } + // ); + this.testingFieldSV.getAll().subscribe( + result => { + this.TestFieldLists = result; + } + ); + this.subjectSV.getAll().subscribe( + result => { + this.SubjectLists = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => { + this.PeriodLists = result; + } + ); + this.testcenterSV.getAll().subscribe( + result => { + this.TestRoomLists = result; + } + ); + } + + showReport(reportId){ + console.log(reportId); + this.reportId = reportId; + } + + onSearch(query, reportId){ + // const query = createQueryStringFromObject(this.query); + this.search.emit({query, reportId}); + } + + onExcel(query, reportId){ + this.excel.emit({query, reportId}); + } + + + +} diff --git a/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.html b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.html new file mode 100644 index 0000000..dabbdae --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.html @@ -0,0 +1,70 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.subject_name_th}} ({{x.subject_code}}) + + +
+
+ +
+
+ + +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.scss b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.spec.ts b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.spec.ts new file mode 100644 index 0000000..99a5227 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSeparatedByExamCenterComponent } from './report-separated-by-exam-center.component'; + +describe('ReportSeparatedByExamCenterComponent', () => { + let component: ReportSeparatedByExamCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSeparatedByExamCenterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSeparatedByExamCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.ts b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.ts new file mode 100644 index 0000000..8d15aa5 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component.ts @@ -0,0 +1,110 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, ChangeDetectorRef} from '@angular/core'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-separated-by-exam-center', + templateUrl: './report-separated-by-exam-center.component.html', + styleUrls: ['./report-separated-by-exam-center.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSeparatedByExamCenterComponent implements OnInit { + isUseTestCenterList = false; + @Input() TestingInformationLists = []; + @Input() SubjectLists = []; + @Input() TestcenterLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + subject_uid: null, + branch_uid: null, + from_date: null, + to_date: null, + }; + private curSub: any; + private curSub2: any; + constructor( + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingInforSV: TestingInformationService, + ) { } + + ngOnInit(): void { + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + displaySubject(uid){ + if (uid && this.SubjectLists) return this.SubjectLists.find(x => x.subject_uid === uid)?.subject_name_th + if (uid && !this.SubjectLists) return this.curSub2?.subject_name_th + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.testingInforSV.get(uidInformation).subscribe( + result => { + console.log(result); + const data:any = result; + this.SubjectLists = data.testing_subjects; + } + ); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + console.log(testinforList); + this.testingInforSV.get(testinforList.testing_information_uid).subscribe( + result => { + const dataInfor: any = result; + this.isUseTestCenterList = true; + this.TestcenterLists = dataInfor.testing_rooms.filter((thing, i, arr) => + arr.findIndex(t => t.branch_uid === thing.branch_uid) === i + ); + this.cdr.detectChanges() + } + ); + } + + clear(){ + this.query = { + testing_information_uid: null, + subject_uid: null, + branch_uid: null, + from_date: null, + to_date: null, + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.html b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.html new file mode 100644 index 0000000..e9ff732 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.html @@ -0,0 +1,110 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + + + + + + + + + + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.scss b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.spec.ts b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.spec.ts new file mode 100644 index 0000000..33c2a54 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSettingTestingCenterComponent } from './report-setting-testing-center.component'; + +describe('ReportSettingTestingCenterComponent', () => { + let component: ReportSettingTestingCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSettingTestingCenterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSettingTestingCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.ts b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.ts new file mode 100644 index 0000000..b3ce536 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-center/report-setting-testing-center.component.ts @@ -0,0 +1,154 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, ChangeDetectorRef} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {TestingFieldService} from "../../../../../core/service/settings/testing-field.service"; + +@Component({ + selector: 'app-report-setting-testing-center', + templateUrl: './report-setting-testing-center.component.html', + styleUrls: ['./report-setting-testing-center.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSettingTestingCenterComponent implements OnInit { + @Input() TestcenterLists: any = []; + @Input() TestFieldLists: any = []; + @Input() TestRoomLists: any = []; + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + isUseTestCenterList = false; + PeriodLists: any = []; + curSub; + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + private testingInforSV: TestingInformationService, + private testingInformationSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + filterTestingFiled(data){ + this.testingFieldSV.getByBrandID(data).subscribe( + result => { + const TestFieldLists = result; + this.TestFieldLists = TestFieldLists + } + ) + } + + filterTestingRoom(data){ + this.testcenterSV.getByFiledID(data).subscribe( + result => { + const TestRoomLists = result; + this.TestRoomLists = TestRoomLists + } + ) + } + + chooseInfor(uidInformation){ + console.log(uidInformation); + this.testingInformationSV.get(uidInformation).subscribe( + result => { + console.log(result); + const data: any = result; + this.TestcenterLists = data.testing_rooms; + } + ); + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + console.log(this.SubjectLists); + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_uid = academicyearList.academic_year_uid; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + } + this.testingInforSV.get(testinforList.testing_information_uid).subscribe( + result => { + const dataInfor: any = result; + console.log(dataInfor); + this.isUseTestCenterList = true; + this.TestcenterLists = dataInfor.testing_rooms.filter((thing, i, arr) => + arr.findIndex(t => t.branch_uid === thing.branch_uid) === i + ); + console.log(this.TestcenterLists) + this.cdr.detectChanges() + } + ); + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.html b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.html new file mode 100644 index 0000000..f33c2d3 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.html @@ -0,0 +1,62 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.scss b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.spec.ts b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.spec.ts new file mode 100644 index 0000000..bf12393 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSettingTestingRoomComponent } from './report-setting-testing-room.component'; + +describe('ReportSettingTestingRoomComponent', () => { + let component: ReportSettingTestingRoomComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSettingTestingRoomComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSettingTestingRoomComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.ts b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.ts new file mode 100644 index 0000000..0d3b69b --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-setting-testing-room/report-setting-testing-room.component.ts @@ -0,0 +1,95 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-setting-testing-room', + templateUrl: './report-setting-testing-room.component.html', + styleUrls: ['./report-setting-testing-room.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSettingTestingRoomComponent implements OnInit { + @Input() TestingInformationLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + curSub; + query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_uid = academicyearList.academic_year_uid; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + } + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.html b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.html new file mode 100644 index 0000000..d58a52e --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.html @@ -0,0 +1,97 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + + + + + +
+ + + + + + + + + +
+ + + + +
+
+
+
+ + + +
+
+ + diff --git a/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.scss b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.spec.ts b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.spec.ts new file mode 100644 index 0000000..bbc4a79 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSignatureExaminationComponent } from './report-signature-examination.component'; + +describe('ReportSignatureExaminationComponent', () => { + let component: ReportSignatureExaminationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSignatureExaminationComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSignatureExaminationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.ts b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.ts new file mode 100644 index 0000000..5c18c3a --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-signature-examination/report-signature-examination.component.ts @@ -0,0 +1,180 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-signature-examination', + templateUrl: './report-signature-examination.component.html', + styleUrls: ['./report-signature-examination.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSignatureExaminationComponent implements OnInit { + @Input() TestcenterLists: any = []; + saveTestcenterLists: any = []; + isUseTestCenterList = false; + @Input() TestFieldLists: any = []; + @Input() TestRoomLists: any = []; + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + PeriodLists: any = []; + @Input() TestingInformationLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + curSub; + query = { + testing_information_uid: null, + // academic_year_uid: null, + // academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + period_id: null, + test_date: null, + }; + constructor( + private testcenterSV: TestingCenterService, + private testingFieldSV: TestingFieldService, + private testingInforSV: TestingInformationService, + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + console.log(object); + for (const key in object) { + console.log(key) + console.log(object[key]) + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + // academic_year_uid: null, + // academic_semester_uid: null, + branch_uid: null, + testing_field_uid: null, + testing_center_uid: null, + period_id: null, + test_date: null, + }; + this.testcenterSV.getAll().subscribe( + result => { + this.TestcenterLists = result; + } + ); + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + filterTestingFiled(data){ + console.log(this.TestcenterLists); + this.testingFieldSV.getByBrandID(data).subscribe( + result => { + const TestFieldLists = result; + this.TestFieldLists = TestFieldLists + } + ) + } + + filterTestingRoom(data){ + this.testcenterSV.getByFiledID(data).subscribe( + result => { + const TestRoomLists = result; + this.TestRoomLists = TestRoomLists + } + ) + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + // if (academicyearList.academic_year_uid !== null){ + // this.query.academic_year_uid = academicyearList.academic_year_uid; + // } + // if (AcademicsemesterList.academic_semester_uid !== null){ + // this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + // } + this.testingInforSV.get(testinforList.testing_information_uid).subscribe( + result => { + const dataInfor: any = result; + this.isUseTestCenterList = true; + this.TestcenterLists = this.TestcenterLists.filter(item1 => + !!dataInfor.testing_rooms.find(item2 => item1.branch_uid === item2.branch_uid) + ); + } + ); + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.html b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.html new file mode 100644 index 0000000..9c73970 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.html @@ -0,0 +1,52 @@ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+ +
+
+ + + +
+
+
+ + + diff --git a/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.scss b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.spec.ts b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.spec.ts new file mode 100644 index 0000000..8d0b3a2 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportSummaryCandidateComponent } from './report-summary-candidate.component'; + +describe('ReportSummaryCandidateComponent', () => { + let component: ReportSummaryCandidateComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportSummaryCandidateComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportSummaryCandidateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.ts b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.ts new file mode 100644 index 0000000..61f6231 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-summary-candidate/report-summary-candidate.component.ts @@ -0,0 +1,95 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-summary-candidate', + templateUrl: './report-summary-candidate.component.html', + styleUrls: ['./report-summary-candidate.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportSummaryCandidateComponent implements OnInit { + @Input() TestingInformationLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + query = { + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.html b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.html new file mode 100644 index 0000000..5b4f2c3 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.html @@ -0,0 +1,77 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.scss b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.spec.ts b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.spec.ts new file mode 100644 index 0000000..178bd9c --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportTestingCenterInformationComponent } from './report-testing-center-information.component'; + +describe('ReportTestingCenterInformationComponent', () => { + let component: ReportTestingCenterInformationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportTestingCenterInformationComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportTestingCenterInformationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.ts b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.ts new file mode 100644 index 0000000..4ca626a --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-center-information/report-testing-center-information.component.ts @@ -0,0 +1,111 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-report-testing-center-information', + templateUrl: './report-testing-center-information.component.html', + styleUrls: ['./report-testing-center-information.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportTestingCenterInformationComponent implements OnInit { + @Input() TestingInformationLists = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Input() SubjectLists = []; + @Input() OldSubjectLists = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + curSub; + query = { + testing_information_uid: null, + subject_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + private testingInformationSV: TestingInformationService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + subject_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + chooseInfor(uidInformation){ + console.log(uidInformation); + this.testingInformationSV.get(uidInformation).subscribe( + result => { + console.log(result); + const data:any = result; + this.SubjectLists = data.testing_subjects; + } + ); + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + console.log(this.SubjectLists); + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_uid = academicyearList.academic_year_uid; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + } + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.html b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.html new file mode 100644 index 0000000..3401d41 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.html @@ -0,0 +1,65 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ +
+
+
+ + + +
+
+
diff --git a/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.scss b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.spec.ts b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.spec.ts new file mode 100644 index 0000000..b29125e --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportTestingRegistrationComponent } from './report-testing-registration.component'; + +describe('ReportTestingRegistrationComponent', () => { + let component: ReportTestingRegistrationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportTestingRegistrationComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportTestingRegistrationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.ts b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.ts new file mode 100644 index 0000000..6481c5d --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-registration/report-testing-registration.component.ts @@ -0,0 +1,95 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-report-testing-registration', + templateUrl: './report-testing-registration.component.html', + styleUrls: ['./report-testing-registration.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportTestingRegistrationComponent implements OnInit { + @Input() TestingInformationLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + curSub; + query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + constructor( + private swSV: SweetalertService, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + academic_year_uid: null, + academic_semester_uid: null, + from_date: null, + to_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + if (academicyearList.academic_year_uid !== null){ + this.query.academic_year_uid = academicyearList.academic_year_uid; + } + if (AcademicsemesterList.academic_semester_uid !== null){ + this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + } + } + +} diff --git a/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.html b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.html new file mode 100644 index 0000000..cb4e50f --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.html @@ -0,0 +1,74 @@ +
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+
+ + +
+
+ + + + + + + + + + + + + + + + +
+
+ + +
+
+ + + + + + +
+
+ +
+
+ + + +
+
diff --git a/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.scss b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.spec.ts b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.spec.ts new file mode 100644 index 0000000..7d815e7 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReportTestingSeatAndRoomComponent } from './report-testing-seat-and-room.component'; + +describe('ReportTestingSeatAndRoomComponent', () => { + let component: ReportTestingSeatAndRoomComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ReportTestingSeatAndRoomComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ReportTestingSeatAndRoomComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.ts b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.ts new file mode 100644 index 0000000..ff7bc57 --- /dev/null +++ b/src/app/feature/report/presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component.ts @@ -0,0 +1,158 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input, ChangeDetectorRef} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../shared/util/func'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-report-testing-seat-and-room', + templateUrl: './report-testing-seat-and-room.component.html', + styleUrls: ['./report-testing-seat-and-room.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportTestingSeatAndRoomComponent implements OnInit { + @Input() TestcenterLists: any = []; + @Input() SubjectLists: any = []; + @Input() AcademicYear = []; + @Input() AcademicsemesterMock = []; + @Input() TestingInformationLists = []; + @Input() PeriodLists: any = []; + @Output() search = new EventEmitter(); + @Output() excel = new EventEmitter(); + isUseTestCenterList = false; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + curSub; + query = { + testing_information_uid: null, + branch_uid: null, + period_id: null, + test_date: null, + }; + constructor( + private testcenterSV: TestingCenterService, + private testingInforSV: TestingInformationService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + } + + onSearch(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.search.emit(this.query); + } + } + + onExcel(){ + let checkNULL = false; + checkNULL = this.checkFunction(this.query); + if (checkNULL === false){ + this.excel.emit(this.query); + } + } + + checkFunction(object){ + for (const key in object) { + if (!object[key]) { + this.swSV.errText('กรุณาใส่ข้อมูลให้ครบถ้วน'); + return true; + } + } + return false; + } + + clear(){ + this.query = { + testing_information_uid: null, + branch_uid: null, + period_id: null, + test_date: null, + }; + } + + displayTestInfor(uid){ + if (uid && this.TestingInformationLists) return this.TestingInformationLists.find(x => x.testing_information_uid === uid)?.testing_information_name + if (uid && !this.TestingInformationLists) return this.curSub?.testing_information_name + } + + setregisterdataForm(data){ + const CenterList = this.TestcenterLists.filter((x) => { + return x.branch_uid === data; + }) + console.log(CenterList); + this.testcenterSV.get(CenterList[0].testing_center_uid).subscribe( + result => { + this.PeriodLists = result; + } + ); + } + + chooseInfor(uidInformation){ + const testinforList = this.TestingInformationLists.find((member) => { + return member.testing_information_uid === uidInformation; + }); + this.setQuery(testinforList); + } + + setQuery(testinforList){ + console.log(testinforList); + const academicyearList = this.AcademicYear.find((member) => { + return member.academic_year_code === testinforList.academic_year_code; + }); + const AcademicsemesterList = this.AcademicsemesterMock.find((member) => { + return member.academic_semester_code === testinforList.academic_semester_code; + }); + // if (academicyearList.academic_year_uid !== null){ + // this.query.academic_year_uid = academicyearList.academic_year_uid; + // } + // if (AcademicsemesterList.academic_semester_uid !== null){ + // this.query.academic_semester_uid = AcademicsemesterList.academic_semester_uid; + // } + this.testingInforSV.get(testinforList.testing_information_uid).subscribe( + result => { + const dataInfor: any = result; + this.isUseTestCenterList = true; + // this.TestcenterLists = this.TestcenterLists.filter(item1 => + // !!dataInfor.testing_rooms.find(item2 => item1.branch_uid === item2.branch_uid) + // ); + this.TestcenterLists = dataInfor.testing_rooms.filter((thing, i, arr) => + arr.findIndex(t => t.branch_uid === thing.branch_uid) === i + ); + this.cdr.detectChanges() + } + ); + } + +} diff --git a/src/app/feature/report/report.module.ts b/src/app/feature/report/report.module.ts new file mode 100644 index 0000000..6f55a57 --- /dev/null +++ b/src/app/feature/report/report.module.ts @@ -0,0 +1,77 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReportRouter } from './router/report-router'; +import {SharedModule} from "../../shared/shared.module"; +import {RouterModule, Routes} from "@angular/router"; +import { ReportContainer } from './container/report/report.container'; +import { ReportPreviewComponent } from './presenter/report-preview/report-preview.component'; +import { ReportSearchComponent } from './presenter/report-search/report-search.component'; +import { ReportCandidateComponent } from './presenter/report-search/report-candidate/report-candidate.component'; +import { ReportCandidateRegisterByCenterComponent } from './presenter/report-search/report-candidate-register-by-center/report-candidate-register-by-center.component'; +import { ReportCandidateRegisterBySubjectComponent } from './presenter/report-search/report-candidate-register-by-subject/report-candidate-register-by-subject.component'; +import { ReportCandidateSubjectComponent } from './presenter/report-search/report-candidate-subject/report-candidate-subject.component'; +import { ReportPaymentAndAppByCenterComponent } from './presenter/report-search/report-payment-and-app-by-center/report-payment-and-app-by-center.component'; +import { ReportPaymentAndAppBySubjectComponent } from './presenter/report-search/report-payment-and-app-by-subject/report-payment-and-app-by-subject.component'; +import { ReportReceiptComponent } from './presenter/report-search/report-receipt/report-receipt.component'; +import { ReportRegisterByPaymentComponent } from './presenter/report-search/report-register-by-payment/report-register-by-payment.component'; +import { ReportSettingTestingCenterComponent } from './presenter/report-search/report-setting-testing-center/report-setting-testing-center.component'; +import { ReportSignatureExaminationComponent } from './presenter/report-search/report-signature-examination/report-signature-examination.component'; +import { ReportSummaryCandidateComponent } from './presenter/report-search/report-summary-candidate/report-summary-candidate.component'; +import { ReportTestingCenterInformationComponent } from './presenter/report-search/report-testing-center-information/report-testing-center-information.component'; +import { ReportTestingRegistrationComponent } from './presenter/report-search/report-testing-registration/report-testing-registration.component'; +import { ReportTestingSeatAndRoomComponent } from './presenter/report-search/report-testing-seat-and-room/report-testing-seat-and-room.component'; +import { ReportSettingTestingRoomComponent } from './presenter/report-search/report-setting-testing-room/report-setting-testing-room.component'; +import { ReportExamResultComponent } from './presenter/report-search/report-exam-result/report-exam-result.component'; +import { ReportCandidateSummaryComponent } from './presenter/report-search/report-candidate-summary/report-candidate-summary.component'; +import { ReportSeparatedByExamCenterComponent } from './presenter/report-search/report-separated-by-exam-center/report-separated-by-exam-center.component'; +import { ReportExamTotalComponent } from './presenter/report-search/report-exam-total/report-exam-total.component'; +import { ReportExamDetailComponent } from './presenter/report-search/report-exam-detail/report-exam-detail.component'; +import { ReportExamSubjectComponent } from './presenter/report-search/report-exam-subject/report-exam-subject.component'; + +const routes: Routes = [ + { + path: '', + component: ReportRouter, + children: [ + { + path: '', + component: ReportContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + ReportRouter, + ReportContainer, + ReportPreviewComponent, + ReportSearchComponent, + ReportCandidateComponent, + ReportCandidateRegisterByCenterComponent, + ReportCandidateRegisterBySubjectComponent, + ReportCandidateSubjectComponent, + ReportPaymentAndAppByCenterComponent, + ReportPaymentAndAppBySubjectComponent, + ReportReceiptComponent, + ReportRegisterByPaymentComponent, + ReportSettingTestingCenterComponent, + ReportSignatureExaminationComponent, + ReportSummaryCandidateComponent, + ReportTestingCenterInformationComponent, + ReportTestingRegistrationComponent, + ReportTestingSeatAndRoomComponent, + ReportSettingTestingRoomComponent, + ReportExamResultComponent, + ReportCandidateSummaryComponent, + ReportSeparatedByExamCenterComponent, + ReportExamTotalComponent, + ReportExamDetailComponent, + ReportExamSubjectComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class ReportModule { } diff --git a/src/app/feature/report/router/report-router.ts b/src/app/feature/report/router/report-router.ts new file mode 100644 index 0000000..3347d6a --- /dev/null +++ b/src/app/feature/report/router/report-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-candidate-list-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ReportRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.html b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.html new file mode 100644 index 0000000..72c40d8 --- /dev/null +++ b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.html @@ -0,0 +1,12 @@ + + + diff --git a/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.scss b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.spec.ts b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.spec.ts new file mode 100644 index 0000000..a7cea6b --- /dev/null +++ b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationContainer } from './set-exam-information.container'; + +describe('SetExamInformationContainer', () => { + let component: SetExamInformationContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.ts b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.ts new file mode 100644 index 0000000..08577b5 --- /dev/null +++ b/src/app/feature/set-exam-information/container/set-exam-information/set-exam-information.container.ts @@ -0,0 +1,77 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {Router} from '@angular/router'; +import {SubjectsService} from '../../../../core/service/settings/subjects.service'; +import {TestingInformationService} from '../../../../core/service/testing-information/testing-information.service'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {ExcelAllTestService} from '../../../../core/service/report/excel-all-test/excel-all-test.service'; + +@Component({ + selector: 'app-set-exam-information', + templateUrl: './set-exam-information.container.html', + styleUrls: ['./set-exam-information.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationContainer implements OnInit { + subjectList$ = new Observable(); + + constructor( + private router: Router, + private TestinforSV: TestingInformationService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private reportExcelAllTestSV: ExcelAllTestService + ) { } + + ngOnInit(): void { + this.subjectList$ = this.TestinforSV.getMaintrue(); + } + + add(){ + this.router.navigate(['exam-information/add']); + } + + edit(id){ + this.router.navigate(['exam-information/edit', id]); + } + + export(id){ + this.reportExcelAllTestSV.get(id).subscribe( + (res: any) => { + // console.log(res) + window.open(res); + }, + err => { + this.swSV.errText(err.error); + return throwError(err); + }); + } + + view(id){ + this.router.navigate(['exam-information/view', id]); + } + + expand(id){ + this.router.navigate(['exam-information/expand', id]); + } + + search(query){ + if(query) return this.subjectList$ = this.TestinforSV.search(`?${query}`); + if(!query) return this.subjectList$ = this.TestinforSV.getAll(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.TestinforSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjectList$ = this.TestinforSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.html b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.html new file mode 100644 index 0000000..233a6ec --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.html @@ -0,0 +1,204 @@ + + + +
+
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+ ไม่กำหนดวิชา +
+
+ กำหนดวิชา +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
รหัสวิชา +
+ +
+
ชื่อวิชา +
+ +
+
เลขที่นั่งเริ่มต้น + (เลขที่นั่งสูงสุด {{item.getRawValue() | checkmaxseat}}) + +
+ + + + + + + + + + +
+
เลขที่นั่งสิ้นสุด + (เลขที่นั่งสูงสุด {{item.getRawValue() | checkmaxseat}}) + +
+ +
+
+ + + + + + + + + + + +
+
+ หมายเหตุ
+
+ ช่วงเลขที่นั่งซ้ำ +
+
+ + + + + + + + + + + + + + + +
+ มีที่นั่งนี้อยู่แล้ว +
+
+ ไม่เปิดแถวนั่งสอบ +
+
+ +
+
+
+ +
+ + +
+
+
+ + + + + + +
+
+
+ + + diff --git a/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.scss b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.scss new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.spec.ts b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.spec.ts new file mode 100644 index 0000000..76dd7ab --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationDialogComponent } from './set-exam-information-dialog.component'; + +describe('SetExamInformationDialogComponent', () => { + let component: SetExamInformationDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.ts b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.ts new file mode 100644 index 0000000..7f9426c --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component.ts @@ -0,0 +1,272 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {FormArray, FormBuilder, Validators} from '@angular/forms'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {BaseForm} from '../../../../../core/base/base-form'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; + +@Component({ + selector: 'app-set-exam-information-dialog', + templateUrl: './set-exam-information-dialog.component.html', + styleUrls: ['./set-exam-information-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationDialogComponent extends BaseForm implements OnInit { + displayedColumns: string[] = ['1', '2', '3', '4', '5']; + dataSource; + form; + default = true; + rowsdata; + ishidden = false; + constructor( + private TestcenterSV: TestingCenterService, + private TestInformationSV: TestingInformationService, + private formBuilder: FormBuilder, + private swSV: SweetalertService, + private cdf: ChangeDetectorRef, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.form = this.formBuilder.group({ + testing_seat: this.formBuilder.array([ + this.testing_seat() + ]) + }); + } + testing_seat(data?){ + return this.formBuilder.group({ + testing_seat_uid: data?.testing_seat_uid, + status_id: data?.status_id, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_center_row_uid: data?.testing_center_row_uid, + // is_specify_subject: data?.is_specify_subject, + is_specify_subject: data?.is_specify_subject !== undefined ? data?.is_specify_subject : false, + testing_room_uid: data?.testing_room_uid, + row_name: [data?.row_name, Validators.required], + no_of_seats: [data?.no_of_seats, Validators.required], + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]) + }); + + } + + testing_seat_subjects(data?){ + // console.log(data) + return this.formBuilder.group({ + testing_seat_uid: data?.testing_seat_uid, + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: [data?.start_seat_no, [Validators.required , Validators.min]], + end_seat_no: [data?.end_seat_no, [Validators.required , Validators.min]], + }); + } + + ngOnInit(): void { + console.log(this.data); + // this.dataSource = this.data.subjectlist; + const form = this.form.get('testing_seat') as FormArray; + form.clear(); + const form2 = this.form.get('testing_seat_subjects') as FormArray; + // console.log( form.insert(1,)); + // const form2 = form.get('control')('testing_seat_subjects') as FormArray; + // console.log(form2); + // for (let i = 0; i < this.data.subjectlist.length; i++) { + // console.log(i); + // const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + // console.log(formArray3); + // formArray3.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + // } + switch (this.data.state) { + case 'add': { + this.TestcenterSV.get(this.data.id).subscribe( + result => { + // console.log(result); + this.rowsdata = result; + // console.log(this.rowsdata.testing_center_rows); + form.clear(); + for (let i = 0; i < this.rowsdata.testing_center_rows.length; i++) { + // console.log(typeof this.rowsdata.testing_center_rows[i].no_of_seats); + form.push(this.testing_seat((this.rowsdata.testing_center_rows[i]))); + const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray3.removeAt(0); + for (let i = 0; i < this.data.subjectlist.length; i++) { + // console.log(i); + // console.log(formArray3); + // console.log(this.data.subjectlist[i]); + formArray3.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + } + } + this.cdf.detectChanges(); + } + ); + break; + } + case 'edit': { + // console.log(this.data); + console.log(this.data.id); + this.rowsdata = this.data.centerList; + console.log(this.rowsdata); + if (this.rowsdata.testing_seats[0].testing_center_row_uid !== null){ + for (let i = 0 ; i < this.rowsdata.testing_seats.length ; i++){ + form.push(this.testing_seat(this.rowsdata.testing_seats[i])); + const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray3.clear(); + for (let j = 0; j < this.rowsdata.testing_seats[i].testing_seat_subjects.length; j++){ + formArray3.push(this.testing_seat_subjects((this.rowsdata.testing_seats[i].testing_seat_subjects[j]))); + } + } + break; + }else { + this.TestcenterSV.get(this.data.id).subscribe( + result => { + this.rowsdata = result; + form.clear(); + // console.log(this.rowsdata.testing_center_rows); + for (let i = 0; i < this.rowsdata.testing_center_rows.length; i++) { + form.push(this.testing_seat((this.rowsdata.testing_center_rows[i]))); + const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray3.removeAt(0); + // for (let i = 0; i < this.data.subjectlist.length; i++) { + // console.log(i); + // console.log(formArray3); + // console.log(this.data.subjectlist[i]); + // formArray3.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + // } + } + this.cdf.detectChanges(); + } + ); + break; + } + } + case 'view': { + // console.log(this.data); + console.log(this.data.id); + this.rowsdata = this.data.centerList; + console.log(this.rowsdata); + if (this.rowsdata.testing_seats[0].testing_center_row_uid !== null){ + for (let i = 0 ; i < this.rowsdata.testing_seats.length ; i++){ + console.log(this.rowsdata.testing_seats[i]); + form.push(this.testing_seat(this.rowsdata.testing_seats[i])); + const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray3.clear(); + for (let j = 0; j < this.rowsdata.testing_seats[i].testing_seat_subjects.length; j++){ + console.log(this.rowsdata.testing_seats[i].testing_seat_subjects[j]); + formArray3.push(this.testing_seat_subjects((this.rowsdata.testing_seats[i].testing_seat_subjects[j]))); + } + } + break; + }else { + this.TestcenterSV.get(this.data.id).subscribe( + result => { + console.log(result); + this.rowsdata = result; + form.clear(); + // console.log(this.rowsdata.testing_center_rows); + for (let i = 0; i < this.rowsdata.testing_center_rows.length; i++) { + console.log(typeof this.rowsdata.testing_center_rows[i].no_of_seats); + form.push(this.testing_seat((this.rowsdata.testing_center_rows[i]))); + const formArray3 = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray3.removeAt(0); + for (let i = 0; i < this.data.subjectlist.length; i++) { + // console.log(i); + // console.log(formArray3); + // console.log(this.data.subjectlist[i]); + formArray3.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + } + } + this.cdf.detectChanges(); + } + ); + break; + } + } + } + this.dataSource = this.data.subjectlist; + } + + save(){ + const form = this.form; + this.dialogRef.close({ event: 'close', data: form }); + } + + cancel(){ + this.dialogRef.close(); + } + + settestingseat(i, boolean: boolean){ + const form = this.form.get('testing_seat') as FormArray; + const form2 = form.controls[i].get('testing_seat_subjects') as FormArray; + // switch (boolean) { + // case true: { + // form2.clear(); + // break; + // } + // case false: { + // if (form2.getRawValue().length === 0){ + // form2.clear(); + // for (i = 0; i < this.data.subjectlist.length; i++) { + // console.log(i); + // console.log(form2); + // form2.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + // } + // } + // break; + // } + // + // } + // console.log(form2.getRawValue()); + if (boolean === false){ + form2.clear(); + } + if (boolean === true){ + if (form2.getRawValue().length === 0){ + form2.clear(); + for (i = 0; i < this.data.subjectlist.length; i++) { + form2.push(this.testing_seat_subjects((this.data.subjectlist[i]))); + } + } + } + } + + displayValue(data){ + console.log(data) + return true; + } + + checkInput(data, indexFormTestSeat, indexFormSeatSubject){ + const form = this.form.get('testing_seat') as FormArray; + const formArray = form.at(indexFormTestSeat).get('testing_seat_subjects') as FormArray; + if (formArray.at(indexFormSeatSubject).get('start_seat_no').value === null && formArray.at(indexFormSeatSubject).get('end_seat_no').value !== null){ + formArray.at(indexFormSeatSubject).get('end_seat_no').setValue(null); + } + } + + checkInputMax(data, indexFormTestSeat, indexFormSeatSubject){ + + } + +} diff --git a/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.html b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.html new file mode 100644 index 0000000..1a6b4e5 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.html @@ -0,0 +1,552 @@ +
+ + +
+
+
+ เปิดรอบสอบ +
+
+
+
+
+ + +
+ + +
+ + +
+ +
+ +
+
+ + +
+ +
+ + +
+
+
+ +
+
+ + +
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+ + +
+
+ + + ใช้คะแนนที่ดีที่สุด + + + ใช้คะแนนครั้งสุดท้าย + + + ใช้คะแนนเฉลี่ย + +
+
+
+
+ +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+ + + + + {{ value | date }} + cancel + + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+ + + + ปฏิทินกิจกรรมอื่นๆ + + + +
+
+ + +
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+ +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ปฏิทินการสอบ {{element.calendar_type_name_th}} วันที่เริ่มต้น {{element.start_datetime | thaidate}} วันที่สิ้นสุด {{element.end_datetime | thaidate}} +
+ +
+
ไม่มีข้อมูล
+
+
+
+
+ + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+
+ +
+
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.branch_name_th}} + + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{subject2.testing_field_name_th}} + + +
+
+ +
+
+ + + + + --กรุณาเลือก-- + + + {{subject3.testing_room_name_th}} + + +
+ +
+
+
+ + +
+
+
+ +
+
+
+
+ +

แสดงรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ศูนย์สอบ {{element.branch_name_th}} สนามสอบ {{element.testing_field_name_th}} ห้องสอบ {{element.testing_room_name_th}} ผู้คุมสอบ {{element.testing_auth_name}} สุ่มที่นั่งสอบ + + + จัดการที่นั่งสอบ* + + + + +
+ +
+
ไม่มีข้อมูล
+
+
+
+
+ +
+ +
+ + +
+
+
+ +
+
+
+ + + นักศึกษา ม.ราม Upload File & API
+ นักศึกษาโครงการ / บุคคลทั่วไป แบบ Upload File
+ บุคคลทั่วไป +
+
+
+
+ ระบุเงื่อนไข +
+
+
+ อัพโหลดเอกสารยืนยันตัวตน +
+
+ ลงทะเบียนเพื่อยืนยันตันตน +
+
+ สมัครผ่านระบบลงทะเบียน +
+
+ สมัครผ่านเคาเตอร์รับสมัคร +
+ +
+ +
+
+
+
+ + + +
+
+
+ + +
{{setexamform.getRawValue() | json}}
+ + + + + + diff --git a/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.scss b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.scss new file mode 100644 index 0000000..2f88c86 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.scss @@ -0,0 +1,55 @@ +/* Styles for tab labels */ +:host ::ng-deep.mat-tab-label { + min-width: 25px !important; + //padding: 5px; + background-color: #F2F0F0; + color: #53C0E5; + font-weight: 700; + border-radius: 5px 5px 0px 0px; +} + + +// .test{ +// min-width: 25px !important; +// //padding: 5px; +// background-color: #F2F0F0; +// color: #53C0E5; +// font-weight: 700; +// border-radius: 5px 5px 0px 0px; +// } + +/* Styles for the active tab label */ +:host ::ng-deep .mat-tab-label.mat-tab-label-active { + min-width: 25px !important; + //padding: 5px; + background-color: #53C0E5; + color: white; + font-weight: 700; + border-radius: 5px 5px 0px 0px; +} + +/* Styles for the ink bar */ +:host ::ng-deep .mat-ink-bar { + background-color: gray !important; + //@apply bg-transparent +} + +.disable{ + @apply bg-gray-300 border-gray-400 pointer-events-none +} + +.mat-column-select { + overflow: initial; +} + +/** No CSS for this example */ +::ng-deep mat-form-field { + width: 100%; +} + +::ng-deep .mat-calendar-body-cell.selected > .mat-calendar-body-cell-content, +::ng-deep .mat-calendar-body-cell.selected:hover > .mat-calendar-body-cell-content, +::ng-deep .mat-calendar-body-cell.selected > .mat-calendar-body-cell-content:hover { + background-color: #673ab7 !important; + color: #fff !important; +} diff --git a/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.spec.ts b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.spec.ts new file mode 100644 index 0000000..679c64b --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationFormComponent } from './set-exam-information-form.component'; + +describe('SetExamInformationFormComponent', () => { + let component: SetExamInformationFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.ts b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.ts new file mode 100644 index 0000000..f7631bb --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/set-exam-information-form/set-exam-information-form.component.ts @@ -0,0 +1,1028 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + ViewChild, + AfterViewInit +} from '@angular/core'; +import { formatDate } from '@angular/common'; +import {MatTableDataSource} from '@angular/material/table'; +import {MatPaginator} from '@angular/material/paginator'; +import {MatSort} from '@angular/material/sort'; +import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; +import {BaseForm} from '../../../../../core/base/base-form'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {catchError, tap} from 'rxjs/operators'; +import {Observable, throwError} from 'rxjs'; +import {SubjectsService} from '../../../../../core/service/settings/subjects.service'; +import {SelectionModel} from '@angular/cdk/collections'; +import {PeriodicElement} from '../../../../manage-test-center/presenter/manage-test-center-table/manage-test-center-table.component'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {EducationTypesService} from '../../../../../core/service/settings/education-types.service'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../core/service/settings/academic-semester.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SetExamInformationDialogComponent} from '../../dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import {BranchService} from '../../../../../core/service/settings/branch.service'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {data} from 'autoprefixer'; +import {CalendarTypeService} from '../../../../../core/service/settings/calendar-type.service'; +import {MatDatepicker, MatDatepickerInputEvent} from '@angular/material/datepicker'; +import {MatSlideToggleModule} from '@angular/material/slide-toggle'; + +// @ts-ignore +@Component({ + selector: 'app-set-exam-information-form', + templateUrl: './set-exam-information-form.component.html', + styleUrls: ['./set-exam-information-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class SetExamInformationFormComponent extends BaseForm implements OnInit , AfterViewInit { + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + typeofdetails = [ + {id: 1, name: 'อัพโหลดเอกสารยืนยันตัวตน', type_of_data: 1, is_check: false}, + {id: 2, name: 'ลงทะเบียนเพื่อยืนยันตันตน', type_of_data: 1, is_check: false}, + {id: 3, name: 'สมัครผ่านระบบลงทะเบียน', type_of_data: 2, is_check: false}, + {id: 4, name: 'สมัครผ่านเคาเตอร์รับสมัคร', type_of_data: 2, is_check: false}, + {id: 5, name: 'อัพโหลดเอกสารยืนยันตัวตน', type_of_data: 2, is_check: false}, + {id: 6, name: 'สมัครผ่านระบบลงทะเบียน', type_of_data: 3, is_check: false}, + {id: 7, name: 'สมัครผ่านเคาเตอร์รับสมัคร', type_of_data: 3, is_check: false}, + {id: 8, name: 'อัพโหลดเอกสารยืนยันตัวตน', type_of_data: 3, is_check: false}, + ]; + daywithout = { + days_without_testing_uid: null, + date_without_testing: null, + }; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": true, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": true, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": true, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": true, + "start_time": "18:00" + } + ]; + sectionsFakeFalse = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": false, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": false, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": false, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": false, + "start_time": "18:00" + } + ]; + private curSub: any; + private curSub2: any; + private curSub3: any; + constructor( + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private TestInformationSV: TestingInformationService, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + ) { + super( + router, + activeRoute, + formBuilder, + location + ); + this.setexamform = this.formBuilder.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_information_uid: null, + testing_information_name: [null, Validators.required], + testing_information_code: null, + academic_semester_code: [null, Validators.required], + academic_year_code: [null, Validators.required], + testing_information_status: null, + type_of_examinee: [null, Validators.required], + is_student_code: false, + first_student_code: '', + last_student_code: '', + registration_start_datetime: null, + registration_end_datetime: null, + testing_start_datetime: null, + testing_end_datetime: null, + is_number_of_times_testing: false, + is_online_register: true, + number_of_times_testing: null, + times_the_score_is_calculated: 1, + is_main: true, + main_testing_information_uid: null, + registration_type: 1, + is_upload_document: false, + is_register_verify: false, + is_register: false, + is_counter: false, + days_without_testings: this.formBuilder.array([ + this.block_days(null) + ]), + testing_calendars: this.formBuilder.array([ + this.testing_calendars(null) + ]), + testing_subjects: this.formBuilder.array([ + this.testing_subjects() + ]), + testing_rooms: this.formBuilder.array([ + this.testing_rooms() + ]), + testing_periods: this.formBuilder.array([ + this.testing_periods() + ]) + }); + this.calendarForm = this.formBuilder.group({ + calendar_type_uid: null, + calendar_type_name_th: null, + start_datetime: null, + end_datetime: null, + }); + this.subjectForm = this.formBuilder.group({ + subjectcode: null, + subjectname: null, + }); + this.setroomcenterForm = this.formBuilder.group({ + branch_name_th: null, + branch_uid: null, + testing_center_uid: null, + testing_field_name_th: null, + testing_field_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + is_random_seat: null, + }); + } + // MainForm + setexamform: FormGroup; + // Subform + SubjectGetCheck$ = new Observable; + subjectListSend = []; + calendarForm: FormGroup; + subjectForm: FormGroup; + setroomcenterForm: FormGroup; + EducationTypeLists; + eductionTypeList; + academicYearList; + calendarLists; + academicSemList; + saveUsername = true; + subjectList; + subjectList2: any = []; + subjectList3; + isDisable = true; + selectCalendar; + fixSubjectlist = false; + Today; + // selected = new FormControl(0); + selectdIndex = 0; + form; + selection = new SelectionModel(true, []); + public CLOSE_ON_SELECTED = false; + public init = new Date(); + public resetModel = new Date(0); + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + @ViewChild('picker7', { static: true }) _picker: MatDatepicker; + @ViewChild(MatSort, { static: true }) sort: MatSort; + @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; + candidateTypes = + [ + { + candidate_type_uid: '6dff8faf-0b30-4fb1-8274-42df8debe8a0', + candidate_type_name_th: 'นักศึกษา', + }, + { + candidate_type_id: 'd056ba6d-5a15-4df6-ade0-c9e8c239d1b1', + candidate_type_name_th: 'บุคคลทั่วไป', + }, + ]; + displayedColumns: string[] = ['1', '2', '3', '4']; + displayedColumns2: string[] = ['select', '1', '2']; + displayedColumns3: string[] = ['1', '2', '3', '4', '5', '6', '7']; + dataSource = new MatTableDataSource(); + dataSource2; + dataSource3 = new MatTableDataSource(); + setupdata = { + testing_center_uid: null, + testing_center_name_th: null, + branch_uid: null, + branch_name_th: null, + testing_field_uid: null, + testing_field_name_th: null, + testing_room_uid: null, + testing_room_name_th: null, + testing_auth_name: null, + }; + + i = { + education_type_id: null, + }; + calendar = { + name: null, + dateStart: null, + dateEnd: null, + }; + testing_seats(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + no_of_seats: data?.no_of_seats, + row_name: data?.row_name, + testing_seat_uid: data?.testing_seat_uid, + testing_center_row_uid: data?.testing_center_row_uid, + is_specify_subject: data?.is_specify_subject, + testing_room_uid: data?.testing_room_uid, + testing_seat_subjects: this.formBuilder.array([ + this.testing_seat_subjects(data?.testing_seat_subjects) + ]), + }); + } + + testing_seat_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + testing_seat_subject_uid: data?.testing_seat_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + start_seat_no: data?.start_seat_no, + end_seat_no: data?.end_seat_no, + testing_seat_uid: data?.testing_seat_uid, + }); + } + + block_days(blockdays?){ + return this.formBuilder.group({ + status_id: null, + testing_information_uid: blockdays?.testing_information_uid, + days_without_testing_uid: blockdays?.days_without_testing_uid, + date_without_testing: blockdays?.date_without_testing, + }); + } + + testing_calendars(calender?){ + return this.formBuilder.group({ + status_id: null, + testing_calendar_uid: calender?.testing_calendar_uid, + start_datetime: calender?.start_datetime, + end_datetime: calender?.end_datetime, + calendar_type_uid: calender?.calendar_type_uid, + calendar_type_name_th: calender?.calendar_type_name_th, + testing_information_uid: calender?.testing_information_uid, + }); + } + + testing_subjects(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_subject_uid: data?.testing_subject_uid, + subject_uid: data?.subject_uid, + subject_code: data?.subject_code, + subject_name_th: data?.subject_name_th, + }); + } + + testing_periods(data?){ + return this.formBuilder.group({ + status_id: null, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + // deleted_datetime: null, + is_check: data?.is_check, + testing_information_uid: data?.testing_information_uid, + testing_period_uid: data?.testing_period_uid, + period_id: data?.period_id, + start_time: data?.start_time, + }); + } + + testing_rooms(data?){ + return this.formBuilder.group({ + testing_room_uid: data?.testing_room_uid, + testing_center_uid: data?.testing_center_uid, + // testing_center_name_th: data?.testing_center_name_th, + branch_uid: data?.branch_uid, + branch_name_th: data?.branch_name_th, + testing_field_uid: data?.testing_field_uid, + testing_information_uid: data?.testing_information_uid, + testing_field_name_th: data?.testing_field_name_th, + testing_room_name_th: data?.testing_room_name_th, + testing_auth_name: data?.testing_auth_name, + is_random_seat: data?.is_random_seat, + testing_seats: this.formBuilder.array([ + this.testing_seats(data?.testing_seats) + ]), + }); + } + + ngOnInit(): void { + this.getCommondata() + } + + async getCommondata(){ + await this.EductiontionTypeSV.getAll().subscribe( + result => { + this.eductionTypeList = result; + } + ); + await this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + await this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + await this.TestInformationSV.getDatatype().subscribe( + result => { + this.EducationTypeLists = result; + } + ); + await this.CalendarTypeSV.getAll().subscribe( + result => { + this.calendarLists = result; + } + ); + await this.branchSV.getAll().pipe( + tap(x => this.subjectList = x), + ).subscribe(); + // await this.testingFieldSV.getAll().pipe( + // tap(x => this.subjectList2 = x), + // ).subscribe(); + await this.testcenterSV.getAll().pipe( + tap(x => this.subjectList3 = x), + ).subscribe(); + await this.subjectSV.getAll().pipe( + tap(x => this.subjectListSend = x), + // tap(x => { + // this.dataSource2 = new MatTableDataSource(x); + // this.dataSource2.paginator = this.paginator; + // this.dataSource2.sort = this.sort; + // }), + ).subscribe(); + await this.AftergetCommonData(); + } + + AftergetCommonData(){ + this.Today = this.formatDate(new Date()); + const form = this.setexamform.get('testing_calendars') as FormArray; + const form2 = this.setexamform.get('testing_subjects') as FormArray; + const form3 = this.setexamform.get('testing_rooms') as FormArray; + const form4 = this.setexamform.get('testing_periods') as FormArray; + const form5 = this.setexamform.get('days_without_testings') as FormArray; + switch (this.state) { + case 'edit': + this.TestInformationSV.get(this.id).pipe( + tap(x => console.log(x)), + tap(x => { + form.clear(); + // form2.clear(); + form3.clear(); + form4.clear(); + form5.clear(); + }), + tap(x => { + const data: any = x; + if (data.number_of_times_testing != null){ + this.setexamform.get('is_number_of_times_testing').setValue(true); + } + data.registration_start_datetime = this.formatDate(data.registration_start_datetime); + data.registration_end_datetime = this.formatDate(data.registration_end_datetime); + data.testing_start_datetime = this.formatDate(data.testing_start_datetime); + data.testing_end_datetime = this.formatDate(data.testing_end_datetime); + this.setexamform.patchValue(data); + }), + tap(x => this.addCalendaEdit(x)), + tap(x => this.add3Edit(x)), + tap(x => this.addPeriodEdit(x)), + // tap(x => this.checkPeriodEdit(x)), + tap(x => this.addEditBlockadd(x)), + // tap(x => this.selectValueEdit(x)), + tap(x => this.cdRef.detectChanges()), + ).subscribe(); + break; + case 'add': + form.clear(); + form2.clear(); + form3.clear(); + form4.clear(); + for (let i = 0; i < this.sectionsFake.length; i++) { + form4.push(this.testing_periods(this.sectionsFake[i])); + } + form5.clear(); + break; + } + } + + formatDate(date) { + let d = new Date(date), + month = '' + (d.getMonth() + 1), + day = '' + d.getDate(), + year = d.getFullYear(); + + if (month.length < 2) { + month = '0' + month; + } + if (day.length < 2) { + day = '0' + day; + } + + return [year, month, day].join('-'); + } + + ngAfterViewInit() { + } + + list(res){ + res = new MatTableDataSource(res); + res.paginator = this.paginator; + res.sort = this.sort; + return res; + } + + selectionValue(data, i){ + switch (this.state) { + case 'edit': + break; + case 'add': + let israndom = true; + if (data.is_random_seat === true){ + israndom = false; + }else if (data.is_random_seat === false){ + israndom = true; + } + const form = this.setexamform.get('testing_rooms') as FormArray; + form.at(i).get('is_random_seat').setValue(israndom); + const table = form.getRawValue(); + this.dataSource3.data = table; + break; + } + } + selectValueEdit(x){ + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + console.log(subjectForm.getRawValue()) + // this.SubjectGetCheck = subjectForm.getRawValue(); + subjectForm.clear(); + // for (let option of x.testing_subjects) { + // subjectForm.push(this.testing_subjects(option)); + // const exists = this.dataSource2.data.filter(x => x.subject_uid === option.subject_uid)[0]; + // this.selection.toggle(exists); + // } + // console.log(this.selection.selected); + this.cdRef.detectChanges(); + } + + moveToSelectedTab(tabName: string) { + console.log(tabName); + this.selectdIndex ++; + + } + + changeRegisterType(){ + const regisType = this.setexamform.get('registration_type').value; + this.setexamform.get('is_register_verify').setValue(false); + this.setexamform.get('is_register').setValue(false); + this.setexamform.get('is_counter').setValue(false); + this.setexamform.get('is_upload_document').setValue(false); + } + + OpenForm(){ + const isStudent = this.setexamform.get('is_student_code').value; + console.log(isStudent); + if (isStudent === false){ + // อย่าลืมล้างค่า + this.setexamform.controls.is_student_code.setValue(true); + }else { + // this.setexamform.controls['this.setexamform'].setValue(false); + this.setexamform.controls.is_student_code.setValue(false); + } + } + + addEditBlockadd(x){ + const form = this.setexamform.get('days_without_testings') as FormArray; + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + form.push(this.block_days(x.days_without_testings[i])); + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + + addCalendar(){ + const form = this.calendarForm.getRawValue(); + const form2 = this.setexamform.get('testing_calendars') as FormArray; + console.log(form); + form2.push(this.testing_calendars(form)); + const table = form2.getRawValue(); + this.dataSource.data = table; + } + addCalendaEdit(x){ + const form2 = this.setexamform.get('testing_calendars') as FormArray; + for (let i = 0; i < x.testing_calendars.length; i++) { + x.testing_calendars[i].end_datetime = this.formatDate(x.testing_calendars[i].start_datetime); + x.testing_calendars[i].start_datetime = this.formatDate( x.testing_calendars[i].start_datetime); + form2.push(this.testing_calendars(x.testing_calendars[i])); + } + const table = form2.getRawValue(); + this.dataSource.data = table; + } + addPeriodEdit(x){ + console.log(x.testing_periods); + const form = this.setexamform.get('testing_periods') as FormArray; + // for (let i = 0; i < x.testing_periods.length; i++) { + // // console.log(x.testing_periods[i].period_id); + // this.sectionsFakeFalse.find(v => v.period_id === x.testing_periods[i].period_id).is_check = true; + // } + for (let i = 0; i < x.testing_periods.length; i++) { + const foundIndex = this.sectionsFakeFalse.findIndex(v => v.period_id === x.testing_periods[i].period_id); + this.sectionsFakeFalse[foundIndex].is_check = true; + this.sectionsFakeFalse[foundIndex].start_time = x.testing_periods[i].start_time; + } + console.log(this.sectionsFakeFalse); + for (let i = 0; i < this.sectionsFakeFalse.length; i++) { + form.push(this.testing_periods(this.sectionsFakeFalse[i])); + } + } + checkPeriodEdit(x){ + console.log(this.sectionsFake); + for (let i = 0; i < x.testing_periods.length; i++) { + // console.log(x.testing_periods[i].period_id); + this.sectionsFake.find(v => v.period_id === x.testing_periods[i].period_id).is_check = true; + } + console.log(this.sectionsFake); + this.cdRef.detectChanges(); + } + removeArray(i){ + const form = this.setexamform.get('testing_calendars') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource.data = table; + } + + + + add3(){ + const form = this.setroomcenterForm.getRawValue(); + const form3 = this.setexamform.get('testing_rooms') as FormArray; + // this.setupdata.testing_auth_name = form.testing_auth_name; + form3.push(this.testing_rooms(form)); + const table = form3.getRawValue(); + this.dataSource3.data = table; + } + + add3Edit(data){ + const form = this.setexamform.get('testing_rooms') as FormArray; + this.SubjectGetCheck$ = data.testing_subjects; + for (let i = 0; i < data.testing_rooms.length; i++) { + form.push(this.testing_rooms(data.testing_rooms[i])); + const formArray = form.controls[i].get('testing_seats') as FormArray; + const FormArraySeat = form.controls[i].get('testing_seat_subjects') as FormArray; + formArray.clear(); + for (let j = 0; j < data.testing_rooms[i].testing_seats.length; j++) { + formArray.push(this.testing_seats(data.testing_rooms[i].testing_seats[j])); + const formArraySeatSubject = formArray.controls[j].get('testing_seat_subjects') as FormArray; + formArraySeatSubject.clear(); + // console.log(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[0]); + // formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[0])); + for (let k = 0; k < data.testing_rooms[i].testing_seats[j].testing_seat_subjects.length; k++) { + // console.log(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k]); + formArraySeatSubject.push(this.testing_seat_subjects(data.testing_rooms[i].testing_seats[j].testing_seat_subjects[k])); + } + } + } + const table = form.getRawValue(); + this.dataSource3.data = table; + } + removeArray3(i){ + const form = this.setexamform.get('testing_rooms') as FormArray; + form.removeAt(i); + const table = form.getRawValue(); + this.dataSource3.data = table; + } + + add2(data){ + console.log(data); + const form = this.setexamform.get('testing_subjects') as FormArray; + form.push(this.testing_subjects(data)); + } + + setBranchname(data){ + + } + + displayBranchname(uid){ + if (uid && this.subjectList) return this.subjectList.find(x => x.branch_uid === uid)?.branch_name_th + if (uid && !this.subjectList) return this.curSub?.branch_name_th + } + + displayFieldname(uid){ + if (uid && this.subjectList2) return this.subjectList2.find(x => x.testing_field_uid === uid)?.testing_field_name_th + if (uid && !this.subjectList2) return this.curSub2?.testing_field_name_th + } + + displayRoomname(uid){ + if (uid && this.subjectList3) return this.subjectList3.find(x => x.testing_center_uid === uid)?.testing_room_name_th + if (uid && !this.subjectList3) return this.curSub3?.testing_room_name_th + } + + setFieldname(uid){ + const branch = this.subjectList.filter((x) => { + return x.branch_uid === uid; + }); + this.setroomcenterForm.get('branch_name_th').setValue(branch[0].branch_name_th); + this.testingFieldSV.getByBrandID(uid).pipe( + tap(x => console.log(x)), + tap(x => this.subjectList2 = x), + ).subscribe(); + } + + setRoomname(uid){ + const branch = this.subjectList2.filter((x) => { + return x.testing_field_uid === uid; + }); + this.setroomcenterForm.get('testing_field_name_th').setValue(branch[0].testing_field_name_th); + this.testcenterSV.getByFiledID(uid).pipe( + tap(x => console.log(x)), + tap(x => this.subjectList3 = x), + ).subscribe(); + } + + setRoomnameth(uid){ + const branch = this.subjectList3.filter((x) => { + return x.testing_center_uid === uid; + }); + this.setroomcenterForm.get('testing_room_name_th').setValue(branch[0].testing_room_name_th); + } + + + + openDialogexam(id:any,index:any){ + console.log(id); + console.log(index); + const form = this.setexamform.get('testing_rooms') as FormArray; + const subjectForm = this.setexamform.get('testing_subjects') as FormArray; + const centerList = form.getRawValue(); + switch (this.state) { + case 'edit': + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + centerList : centerList[index], + subjectlist : subjectForm.getRawValue(), + state : this.state, + } + }); + dialogRefedit.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const testseat = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + // for (let i = 0; i < form.getRawValue().length; i++) { + // const formArray = form.controls[index].get('testing_seats') as FormArray; + // for (let j = 0; j < testseat.testing_seat.length; j++) { + // formArray.push(testseatdata.get('testing_seat').controls[j]); + // } + // } + this.cdRef.detectChanges(); + } + ); + break; + case 'add': + const dialogRefadd = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + subjectlist : subjectForm.getRawValue(), + state : this.state, + } + }); + dialogRefadd.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(index).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + const formArray = form.controls[index].get('testing_seats') as FormArray; + for (let i = 0; i < testseat.testing_seat.length; i++) { + formArray.push(testseatdata.get('testing_seat').controls[i]); + } + // for (let i = 0; i < form.getRawValue().length; i++) { + // const formArray = form.controls[index].get('testing_seats') as FormArray; + // for (let j = 0; j < testseat.testing_seat.length; j++) { + // formArray.push(testseatdata.get('testing_seat').controls[j]); + // } + // } + this.cdRef.detectChanges(); + } + ); + break; + } + } + + openDialogEdit(testseat){ + console.log(testseat); + const form = this.setexamform.get('testing_rooms') as FormArray; + console.log(form.getRawValue()); + switch (this.state) { + case 'edit': + const uidInformtion = this.id; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id : uidInformtion, + centerList : form.getRawValue(), + testseat : testseat, + subjectlist : this.selection.selected, + state : this.state, + } + }); + dialogRefedit.afterClosed().subscribe( + result => { + const testseatdata = result.data; + const data = testseatdata.getRawValue(); + const formArray3 = form.at(0).get('testing_seats') as FormArray; + formArray3.clear(); + console.log(data); + const testseat = data; + for (let i = 0; i < form.getRawValue().length; i++) { + const formArray = form.controls[i].get('testing_seats') as FormArray; + for (let j = 0; j < testseat.testing_seat.length; j++) { + formArray.push(testseatdata.get('testing_seat').controls[j]); + } + } + this.cdRef.detectChanges(); + } + ); + break; + } + } + + save(){ + switch (this.state) { + case 'edit': + const form1 = this.setexamform.getRawValue(); + const dataselect2 = this.selection.selected; + const results2 = dataselect2.map(({ subject_uid }) => ({ subject_uid })); + form1.testing_periods = form1.testing_periods.filter((member) => { + return member.is_check === true; + }); + // const formEdit = this.setexamform.get('testing_subjects') as FormArray; + // formEdit.clear(); + // for (const key of Object.keys(results2)) { + // const mealName = results2[key]; + // this.add2(mealName); + // } + this.TestInformationSV.update2(form1).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + + case 'add': + const form = this.setexamform.getRawValue(); + form.testing_periods = form.testing_periods.filter((member) => { + return member.is_check === true; + }); + // tslint:disable-next-line:max-line-length + if (form.testing_start_datetime == null || form.testing_end_datetime == null || form.registration_start_datetime == null || form.registration_end_datetime == null){ + return this.swSV.errText('กรุณาใส่วันที่'); + } + this.TestInformationSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err(); + return throwError(err); + }) + ).subscribe(); + break; + } + } + + setcalendarForm(selectCalendar){ + const CalendarChoose = this.calendarLists.filter(x => x.calendar_type_uid === selectCalendar); + this.calendarForm.get('calendar_type_name_th').setValue(CalendarChoose[0].calendar_type_name_th); + } + + setDatecalendarForm(choose, Date){ + const Dateset:any = formatDate(Date, 'yyyy-MM-dd', 'en-US') + switch(choose) { + case 'start': { + this.calendarForm.get('start_datetime').setValue(Dateset); + break; + } + case 'end': { + this.calendarForm.get('end_datetime').setValue(Dateset); + break; + } + } + } + + onChangeSelection(selected) { + console.log(selected); + // this.i.education_type_id = parseInt(selected); + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource2.filter = filterValue.trim().toLowerCase(); + } + + GetSubjectChoose(data){ + const form = this.setexamform.get('testing_subjects') as FormArray; + form.clear(); + for (let i = 0; i < data.length; i++) { + form.push(this.testing_subjects(data[i])); + } + } + + convert(str) { + var date = new Date(str), + mnth = ("0" + (date.getMonth() + 1)).slice(-2), + day = ("0" + date.getDate()).slice(-2); + return [date.getFullYear(), mnth, day].join('-'); + } + + onCheckChange(event,choice) { + const formArraySecttion = this.setexamform.get('testing_periods') as FormArray; + // /* Selected */ + if (event.target.checked) { + // Add a new control in the arrayForm + formArraySecttion.push(this.testing_periods(choice)); + } else { + // console.log(formArraySecttion.getRawValue()) + const ArrayPeriods = formArraySecttion.getRawValue(); + const Found = ArrayPeriods.findIndex(x => x.period_id === choice.period_id) + // console.log(Found); + formArraySecttion.removeAt(Found); + + } + } + + removeChoice(i){ + // const form = this.setexamform.get('testing_periods') as FormArray; + // form.removeAt(i); + } + toggle(event){ + console.log(event); + console.log(event.checked); + console.log(event.value); + } + public dateClass = (date: Date) => { + if (this._findDate(date) !== -1) { + return [ 'selected' ]; + } + return [ ]; + } + + public dateChanged(event: MatDatepickerInputEvent): void { + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + if (event.value) { + const date = event.value; + const index = this._findDate(date); + if (index === -1) { + this.model.push(date); + this.updateBlockdate(date); + } else { + this.model.splice(index, 1); + formblockdays.removeAt(index); + } + + this.resetModel = new Date(0); + if (!this.CLOSE_ON_SELECTED) { + const closeFn = this._picker.close; + this._picker.close = () => { }; + this._picker['_popupComponentRef'].instance._calendar.monthView._createWeekCells() + setTimeout(() => { + this._picker.close = closeFn; + }); + } + } + } + + public remove(date: Date): void { + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + const index = this._findDate(date); + formblockdays.removeAt(index) + this.model.splice(index, 1); + } + + private _findDate(date: Date): number { + return this.model.map((m) => +m).indexOf(+date); + } + + updateBlockdate(date){ + const formblockdays = this.setexamform.get('days_without_testings') as FormArray; + switch (this.state) { + case 'edit': + this.daywithout.date_without_testing = formatDate(date, 'yyyy-MM-dd', 'en-US'); + formblockdays.push(this.block_days(this.daywithout)); + break; + case 'add': + // this.daywithout.id_day = null; + this.daywithout.date_without_testing = formatDate(date, 'yyyy-MM-dd', 'en-US'); + formblockdays.push(this.block_days(this.daywithout)); + break; + } + } +} diff --git a/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.html b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.html new file mode 100644 index 0000000..7a11df6 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.html @@ -0,0 +1,100 @@ +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + ชื่อวิชา + {{element.subject_name_th}} ({{element.subject_code}}) + + + + + + + ไม่มีพบข้อมูล จากค้นหาคำว่า "{{input.value}}" + + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+
+
+ + + +
+
+ + + + + + + + + + + + + + + ชื่อวิชา + {{element.subject_name_th}} ({{element.subject_code}}) + + + + + + ไม่มีพบข้อมูล จากค้นหาคำว่า "{{input2.value}}" + + + + + + +
+
+
+ + + diff --git a/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.scss b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.spec.ts b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.spec.ts new file mode 100644 index 0000000..13794e0 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TableSwapSubjectComponent } from './table-swap-subject.component'; + +describe('TableSwapSubjectComponent', () => { + let component: TableSwapSubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TableSwapSubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TableSwapSubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.ts b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.ts new file mode 100644 index 0000000..43b1d22 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/form/table-swap-subject/table-swap-subject.component.ts @@ -0,0 +1,137 @@ +import { + Component, + OnInit, + ChangeDetectionStrategy, + Input, + ViewChild, + OnChanges, + ChangeDetectorRef, + Output, + EventEmitter +} from '@angular/core'; +import {SelectionModel} from '@angular/cdk/collections'; +import {MatTableDataSource} from '@angular/material/table'; +import {MatPaginator} from '@angular/material/paginator'; +import {BaseList} from '../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../core/service/security/app-token.service'; + +@Component({ + selector: 'app-table-swap-subject', + templateUrl: './table-swap-subject.component.html', + styleUrls: ['./table-swap-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TableSwapSubjectComponent extends BaseList implements OnInit , OnChanges { + @Input() dataSource: any = []; + @Input() SubjectGetCheck: any = []; + column = ['1', '2']; + // data = Object.assign(this.dataSourceRecieve); + // dataSource = new MatTableDataSource(this.data); + selection = new SelectionModel(true, []); + uncheckedData = []; + @Output() SubjectChecked = new EventEmitter(); + + checkedData = []; + checkedDataSource = new MatTableDataSource(this.checkedData); + checkedSelection = new SelectionModel(true, []); + + selectedRows = []; + selectedRowsChecked = []; + + @ViewChild('paginator') paginator: MatPaginator; + @ViewChild('checkedpaginator') checkedpaginator: MatPaginator; + constructor( + private cdRef: ChangeDetectorRef, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges() { + this.uncheckedData = this.dataSource; + this.dataSource = this.updateMatTable(this.dataSource ? this.dataSource : []); + const DatatableLength = this.dataSource.data; + if (DatatableLength.length !== 0){ + for (const option of this.SubjectGetCheck) { + // const exists = DatatableLength.find((x) => x.subject_uid === option.subject_uid); + const exists = Array.isArray(DatatableLength) ? DatatableLength.find((x) => x.subject_uid === option.subject_uid) : 0; + if (exists !== 0){ + this.selection.toggle(exists); + this.transferSelectedRows(); + } + } + } + this.checkedDataSource.paginator = this.checkedpaginator; + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected === numRows; + } + + isAllCheckedSelected() { + const numSelected = this.checkedSelection.selected.length; + const numRows = this.checkedDataSource.data.length; + return numSelected === numRows; + } + + + transferSelectedRows() { + this.selection.selected.forEach(item => { + const index: number = this.uncheckedData.findIndex(d => d === item); + this.checkedData.push(this.uncheckedData[index]); + this.uncheckedData.splice(index,1); + }); + this.selection = new SelectionModel(true, []); + this.dataSource = new MatTableDataSource(this.uncheckedData); + this.checkedDataSource = new MatTableDataSource(this.checkedData); + this.dataSource.paginator = this.paginator; + this.checkedDataSource.paginator = this.checkedpaginator; + this.sendDataback(this.checkedData); + } + + + removeSelectedRows() { + this.checkedSelection.selected.forEach(item => { + const index: number = this.checkedData.findIndex(d => d === item); + this.uncheckedData.push(this.checkedData[index]); + this.checkedData.splice(index,1); + }); + this.checkedSelection = new SelectionModel(true, []); + this.dataSource = new MatTableDataSource(this.uncheckedData); + this.checkedDataSource = new MatTableDataSource(this.checkedData); + this.dataSource.paginator = this.paginator; + this.checkedDataSource.paginator = this.checkedpaginator; + this.sendDataback(this.checkedData); + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); + } + + masterCheckedToggle() { + this.isAllCheckedSelected()? + this.checkedSelection.clear() : this.checkedDataSource.data.forEach(row => this.checkedSelection.select(row)); + } + + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + } + + applyFilter2(event: Event) { + const filterValue2 = (event.target as HTMLInputElement).value; + this.checkedDataSource.filter = filterValue2.trim().toLowerCase(); + } + + sendDataback(datasend){ + this.SubjectChecked.emit(datasend); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.html b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.html new file mode 100644 index 0000000..33398e9 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.html @@ -0,0 +1,110 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} รหัสรอบ {{x.testing_information_code}} วันที่เริ่มต้น-สิ้นสุด {{x.start_datetime | thaidate}} - {{x.end_datetime | thaidate}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} สถานะ +
+
check_circle มีวิชา
+ cancel ไม่มีวิชา +
+
+
check_circle มีห้องสอบ
+ cancel ไม่มีห้องสอบ +
+
+
check_circle มีค่าสอบ
+ cancel ไม่มีค่าสอบ +
+
สถานะการเปิดรอบ +
+
เปิดรอบสอบ
+
ปิดรอบสอบ
+
ยังไม่เปิดรอบ
+
+
วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + + + +
+
+
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.scss b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.spec.ts b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.spec.ts new file mode 100644 index 0000000..eb17e53 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationListComponent } from './set-exam-information-list.component'; + +describe('SetExamInformationListComponent', () => { + let component: SetExamInformationListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.ts b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.ts new file mode 100644 index 0000000..84fe367 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/list/set-exam-information-list/set-exam-information-list.component.ts @@ -0,0 +1,75 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; +import {AppTokenService} from '../../../../../core/service/security/app-token.service'; +import {OBJECT} from '../../../../../core/enum/role'; + +@Component({ + selector: 'app-set-exam-information-list', + templateUrl: './set-exam-information-list.component.html', + styleUrls: ['./set-exam-information-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationListComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + role = []; + roleConfig = OBJECT; + @Output() edit = new EventEmitter(); + @Output() view = new EventEmitter(); + @Output() expand = new EventEmitter(); + @Output() export = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + '8', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + '6', + 'is_open', + 'created_datetime', + '7', + '9' + ]; + reload: boolean; + + constructor( + private appTokenSV: AppTokenService + ) { + super(); + } + + ngOnInit(): void { + this.role = this.appTokenSV.user.rights; + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onView(id){ + this.view.emit(id); + } + + onExportExcel(id){ + this.export.emit(id); + } + + onExpand(id){ + this.expand.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.html b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.html new file mode 100644 index 0000000..578bba0 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.html @@ -0,0 +1,28 @@ +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.scss b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.spec.ts b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.spec.ts new file mode 100644 index 0000000..f0a7e90 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationSearchComponent } from './set-exam-information-search.component'; + +describe('SetExamInformationSearchComponent', () => { + let component: SetExamInformationSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.ts b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.ts new file mode 100644 index 0000000..72ce66f --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/search/set-exam-information-search/set-exam-information-search.component.ts @@ -0,0 +1,53 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from "../../../../../shared/util/func"; +import {AcademicYearService} from "../../../../../core/service/settings/academic-year.service"; + +@Component({ + selector: 'app-set-exam-information-search', + templateUrl: './set-exam-information-search.component.html', + styleUrls: ['./set-exam-information-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + constructor( + private AcademicYearSV: AcademicYearService, + ) { } + + ngOnInit(): void { + this.AcademicYearSV.getAll().subscribe( + result => { + console.log(result); + this.academicYearList = result; + } + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null + }; + } + +} diff --git a/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.html b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.html new file mode 100644 index 0000000..7a8fe18 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.html @@ -0,0 +1,44 @@ +
+
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ + + create + + +
+
+ + + + + +
+ + +
+
+
+ +
+  {{form.getRawValue() | json}}
+
diff --git a/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.scss b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.spec.ts new file mode 100644 index 0000000..c59bcea --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChangeTimeSectionComponent } from './change-time-section.component'; + +describe('ChangeTimeSectionComponent', () => { + let component: ChangeTimeSectionComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ChangeTimeSectionComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ChangeTimeSectionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.ts b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.ts new file mode 100644 index 0000000..fd12274 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/dialog/change-time-section/change-time-section.component.ts @@ -0,0 +1,86 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {TestingPeriodService} from '../../../../../../core/service/testing-information/testing-period.service'; +import {catchError, tap} from 'rxjs/operators'; +import {BaseForm} from '../../../../../../core/base/base-form'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {throwError} from 'rxjs'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-change-time-section', + templateUrl: './change-time-section.component.html', + styleUrls: ['./change-time-section.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ChangeTimeSectionComponent extends BaseForm implements OnInit { + time = '6:00 am'; + form; + OldSectionTime; + constructor( + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + public router: Router, + private swSV: SweetalertService, + private testingPeriodSV: TestingPeriodService, + private cdr: ChangeDetectorRef, + ) { + super( + router, + activeRoute, + fb, + location + ); + } + + createForm(): FormGroup { + return this.fb.group({ + testing_period_uid: null, + testing_release_exam_dates: null, + period_id: null, + start_time: [null, Validators.required], + print_start_time: null, + print_end_time: null, + testing_information_uid: null, + status_id: null, + created_by: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + }); + } + + ngOnInit(): void { + this.testingPeriodSV.get(this.id).pipe( + tap(x => this.OldSectionTime = x), + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + + save(){ + const form = this.form; + // this.dialogRef.close({ event: 'close', data: form }); + this.testingPeriodSV.update2(form.getRawValue()).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe(); + } + + cancel(){ + this.location.back(); + } + + onChangeHour(data){ + this.form.get('start_time').setValue(data) + } + +} diff --git a/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.html b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.html new file mode 100644 index 0000000..6c876a8 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.html @@ -0,0 +1,232 @@ +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+ + +
+ + + + + + + + + + + + +
+
+
+
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+ + + + + {{ value | thaidate }} + + + + + + +
+
+
+
+
+
+ +
+
+
+
+

ระบุเงื่อนไข

+
+
+ + อัพโหลดเอกสารยืนยันตัวตน + + ลงทะเบียนสอบผ่านระบบออนไลน์ + ลงทะเบียนสอบผ่านเค้าเตอร์รับสมัคร +
+
+
+
+ + + + + + + +
+ + + diff --git a/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.scss b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.spec.ts new file mode 100644 index 0000000..021d079 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetExamInformationViewComponent } from './set-exam-information-view.component'; + +describe('SetExamInformationViewComponent', () => { + let component: SetExamInformationViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetExamInformationViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetExamInformationViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.ts b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.ts new file mode 100644 index 0000000..8b4274b --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/set-exam-information-view/set-exam-information-view.component.ts @@ -0,0 +1,216 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild} from '@angular/core'; +import { async } from '@angular/core/testing'; +import {FormBuilder, FormGroup} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {tap} from 'rxjs/operators'; +import {TestingInformationService} from '../../../../../core/service/testing-information/testing-information.service'; +import {MatTableDataSource} from '@angular/material/table'; +import {SubjectsService} from '../../../../../core/service/settings/subjects.service'; +import {TestingCenterService} from '../../../../../core/service/TestingCenter/testing-center.service'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {BranchService} from '../../../../../core/service/settings/branch.service'; +import {MatDialog} from '@angular/material/dialog'; +import {formatDate, Location} from '@angular/common'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {EducationTypesService} from '../../../../../core/service/settings/education-types.service'; +import {AcademicYearService} from '../../../../../core/service/settings/academic-year.service'; +import {AcademicSemesterService} from '../../../../../core/service/settings/academic-semester.service'; +import {CalendarTypeService} from '../../../../../core/service/settings/calendar-type.service'; +import {MatSort} from '@angular/material/sort'; +import {MatPaginator} from '@angular/material/paginator'; +import {Observable} from 'rxjs'; + +@Component({ + selector: 'app-set-exam-information-view', + templateUrl: './set-exam-information-view.component.html', + styleUrls: ['./set-exam-information-view.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationViewComponent implements OnInit { + data; + TestinforUid; + EducationTypeLists; + eductionTypeList; + academicYearList; + calendarLists; + academicSemList; + saveUsername = true; + subjectList; + subjectList2; + subjectList3; + isDisable = true; + selectCalendar; + dataSource5; + dataSource4; + dataSource3; + dataSource2; + dataSource; + setexamform: FormGroup; + fixSubjectlist = false; + Today; + candidateTypes = + [ + { + candidate_type_uid: '6dff8faf-0b30-4fb1-8274-42df8debe8a0', + candidate_type_name_th: 'นักศึกษา', + }, + { + candidate_type_id: 'd056ba6d-5a15-4df6-ade0-c9e8c239d1b1', + candidate_type_name_th: 'บุคคลทั่วไป', + }, + ]; + sectionsFake = [ + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 1, + "is_check": true, + "start_time": "09:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 2, + "is_check": true, + "start_time": "12:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 3, + "is_check": true, + "start_time": "15:00" + }, + { + "status_id": 1, + "testing_center_period_uid": null, + "period_id": 4, + "is_check": true, + "start_time": "18:00" + } + ]; + public model = [ + // new Date('2/8/2022'), + // new Date('2/9/2022'), + // new Date('2/11/2022'), + ]; + @ViewChild(MatSort, { static: true }) sort: MatSort; + @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; + constructor( + public _router: Router, + public _activeRouter: ActivatedRoute, + private TestInformationSV: TestingInformationService, + private subjectSV: SubjectsService, + private testcenterSV: TestingCenterService, + private testFiledSV: TestingFieldService, + private branchSV: BranchService, + private testingFieldSV: TestingFieldService, + private formBuilder: FormBuilder, + private dialog: MatDialog, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdRef: ChangeDetectorRef, + private EductiontionTypeSV: EducationTypesService, + private AcademicYearSV: AcademicYearService, + private AcademicSemSV: AcademicSemesterService, + private CalendarTypeSV: CalendarTypeService, + ) { + } + + ngOnInit(): void { + this._activeRouter.params.subscribe( + result => { + const uid: any = result; + this.TestinforUid = uid.id; + this.getGeneralData(uid.id) + } + ); + } + + async getGeneralData(id) { + await this.EductiontionTypeSV.getAll().subscribe( + result => { + console.log(result); + this.eductionTypeList = result; + } + ); + await this.AcademicYearSV.getAll().subscribe( + result => { + this.academicYearList = result; + } + ); + await this.AcademicSemSV.getAll().subscribe( + result => { + this.academicSemList = result; + } + ); + await this.TestInformationSV.getDatatype().subscribe( + result => { + this.EducationTypeLists = result; + } + ); + await this.CalendarTypeSV.getAll().subscribe( + result => { + this.calendarLists = result; + } + ); + await this.branchSV.getAll().subscribe( + result => { + this.subjectList = result; + } + ); + this.testingFieldSV.getAll().subscribe( + result => { + this.subjectList2 = result; + } + ); + await this.testcenterSV.getAll().subscribe( + result => { + this.subjectList3 = result; + } + ); + // await this.subjectSV.getAll().subscribe( + // result => { + // // this.dataSource2 = new MatTableDataSource(result); + // this.dataSource2 = result; + // } + // ); + await this.SetData(id); + } + SetData(id) { + this.TestInformationSV.get(id).subscribe( + result => { + this.data = result; + this.addEditBlockadd(result); + this.dataSource2 = this.data.testing_subjects; + this.dataSource = this.data.testing_rooms; + this.dataSource3 = this.data.testing_calendars; + this.dataSource4 = this.data.testing_periods; + this.cdRef.detectChanges(); + } + ); + } + + addEditBlockadd(x){ + // const form = this.setexamform.get('days_without_testings') as FormArray; + console.log(x.days_without_testings); + for (let i = 0; i < x.days_without_testings.length; i++) { + x.days_without_testings[i].date_without_testing = formatDate(x.days_without_testings[i].date_without_testing, 'yyyy-MM-dd', 'en-US') + this.model.push(x.days_without_testings[i].date_without_testing); + } + } + + searchSummarySubject(testdate){ + this.TestInformationSV.getSummarySubject(this.TestinforUid, testdate).subscribe( + result => { + this.dataSource5 = result; + this.cdRef.detectChanges(); + } + ); + } + + + +} diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.html b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.html new file mode 100644 index 0000000..19a112f --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.html @@ -0,0 +1,51 @@ +
+
+
+

รายการปฏิทิน

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสวิชา {{x.calendar_type_name_th}} วันที่เริ่มต้น {{x.start_datetime | thaidate}} วันที่สิ้นสุด {{x.end_datetime | thaidate}}
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.scss b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.spec.ts new file mode 100644 index 0000000..bd0718a --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamViewTableCalendarComponent } from './setting-exam-view-table-calendar.component'; + +describe('SettingExamViewTableCalendarComponent', () => { + let component: SettingExamViewTableCalendarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamViewTableCalendarComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamViewTableCalendarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.ts new file mode 100644 index 0000000..e4edcee --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component.ts @@ -0,0 +1,26 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; + +@Component({ + selector: 'app-setting-exam-view-table-calendar', + templateUrl: './setting-exam-view-table-calendar.component.html', + styleUrls: ['./setting-exam-view-table-calendar.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamViewTableCalendarComponent extends BaseList implements OnInit, OnChanges { + @Input() calendarList: any = []; + + column = ['1', '2', '3', '4']; + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.calendarList); + this.calendarList = this.updateMatTable(this.calendarList ? this.calendarList : []); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.html b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.html new file mode 100644 index 0000000..f552376 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.html @@ -0,0 +1,87 @@ +
+
+
+
+

รายการห้องสอบ

+
+ + + +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสศูนย์สอบ {{x.branch_code}} ศูนย์สอบ {{x.branch_name_th}} รหัสสนามสอบ {{x.testing_field_code}} ชื่อสนามสอบ {{x.testing_field_name_th}} ห้องสอบ {{x.testing_room_name_th}} สุ่มที่นั่งสอบ + + จัดการที่นั่งสอบ + +
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.scss b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.spec.ts new file mode 100644 index 0000000..e044502 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamViewTableCenterComponent } from './setting-exam-view-table-center.component'; + +describe('SettingExamViewTableCenterComponent', () => { + let component: SettingExamViewTableCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamViewTableCenterComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamViewTableCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.ts new file mode 100644 index 0000000..7ba55f7 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component.ts @@ -0,0 +1,71 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {FormArray} from '@angular/forms'; +import {SetExamInformationDialogComponent} from '../../dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import {data} from 'autoprefixer'; +import {MatDialog} from '@angular/material/dialog'; +import {ActivatedRoute} from '@angular/router'; +import {tap} from 'rxjs/operators'; +import {TestingRoomService} from '../../../../../core/service/report/testing-room/testing-room.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-setting-exam-view-table-center', + templateUrl: './setting-exam-view-table-center.component.html', + styleUrls: ['./setting-exam-view-table-center.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamViewTableCenterComponent extends BaseList implements OnInit, OnChanges { + @Input() centerList: any = []; + @Input() subjectList: any = []; + column = ['1', '2', '3', '4', '5', '6', '7', '8']; + + constructor( + private dialog: MatDialog, + private cdRef: ChangeDetectorRef, + private activeRouter: ActivatedRoute, + private testingRoomSV: TestingRoomService, + private swSV: SweetalertService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.centerList = this.updateMatTable(this.centerList ? this.centerList : []); + } + + openDialogexam(id:any,index:any){ + const centerList = this.centerList.data; + const dialogRefedit = this.dialog.open(SetExamInformationDialogComponent, { + width: '1000px', + height: '700px', + data: { + id, + centerList : centerList[index], + subjectlist : this.subjectList, + state : 'view', + } + }); + } + + onExcel(){ + this.activeRouter.params.pipe( + tap((y: any) => { + console.log(y.id); + this.testingRoomSV.getExcelReport( + y.id, + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.html b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.html new file mode 100644 index 0000000..be9811a --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.html @@ -0,0 +1,60 @@ +
+
+
+

รายการSection

+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} Section {{x.period_id}} เวลาเริ่มสอบ {{x.start_time}} เครื่องมือ +
+ + + + +
+
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.scss b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.spec.ts new file mode 100644 index 0000000..a84e108 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamViewTableSectionComponent } from './setting-exam-view-table-section.component'; + +describe('SettingExamViewTableSectionComponent', () => { + let component: SettingExamViewTableSectionComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamViewTableSectionComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamViewTableSectionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.ts new file mode 100644 index 0000000..6c093bb --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, ChangeDetectorRef} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {MatDialog} from '@angular/material/dialog'; +import {SetExamInformationDialogComponent} from '../../dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import {ChangeTimeSectionComponent} from '../dialog/change-time-section/change-time-section.component'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-setting-exam-view-table-section', + templateUrl: './setting-exam-view-table-section.component.html', + styleUrls: ['./setting-exam-view-table-section.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamViewTableSectionComponent extends BaseList implements OnInit, OnChanges { + @Input() sectionList: any = []; + column = ['1', '2', '3', '4']; + + constructor( + private dialog: MatDialog, + private cdRef: ChangeDetectorRef, + public router: Router, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + console.log(this.sectionList); + this.sectionList = this.updateMatTable(this.sectionList ? this.sectionList : []); + } + + openDialogexam(id: any, index: any){ + console.log(id); + console.log(index); + // const centerList = this.centerList.data; + const dialogRefedit = this.dialog.open(ChangeTimeSectionComponent, { + width: '1000px', + height: '280px', + data: { + id + } + }); + } + + + onRoute(id: any, index: any){ + console.log(id); + console.log(index); + // const centerList = this.centerList.data; + this.router.navigate(['exam-information/section/edit',id]) + + } + + +} diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.html b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.html new file mode 100644 index 0000000..ca665db --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.html @@ -0,0 +1,48 @@ +
+
+
+

รายการรายวิชา

+
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}}
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.scss b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.spec.ts new file mode 100644 index 0000000..b2838fb --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamViewTableSubjectComponent } from './setting-exam-view-table-subject.component'; + +describe('SettingExamViewTableSubjectComponent', () => { + let component: SettingExamViewTableSubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamViewTableSubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamViewTableSubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.ts b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.ts new file mode 100644 index 0000000..733e934 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component.ts @@ -0,0 +1,50 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {tap} from 'rxjs/operators'; +import {ActivatedRoute} from '@angular/router'; +import {TestingRoomService} from '../../../../../core/service/report/testing-room/testing-room.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TesingSubjectService} from '../../../../../core/service/report/testing-subject/tesing-subject.service'; + +@Component({ + selector: 'app-setting-exam-view-table-subject', + templateUrl: './setting-exam-view-table-subject.component.html', + styleUrls: ['./setting-exam-view-table-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamViewTableSubjectComponent extends BaseList implements OnInit, OnChanges { + @Input() subjectList: any = []; + column = ['1', '2', '3']; + constructor( + private activeRouter: ActivatedRoute, + private testingSubjectSV: TesingSubjectService, + private swSV: SweetalertService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onExcel(){ + this.activeRouter.params.pipe( + tap((y: any) => { + console.log(y.id); + this.testingSubjectSV.getExcelReport( + y.id, + ).subscribe( + res => { + // window.open(fileURL, '_blank'); + }, + error => { + this.swSV.errText('ไม่พบข้อมูล') + }); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.html b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.html new file mode 100644 index 0000000..6066cca --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.html @@ -0,0 +1,74 @@ +
+
+
+

สรุปยอดตามกระบวนวิชา

+
+
+
+ + + + + +
+
+ +
+ + + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสวิชา {{x.subject_code}} วันสอบ {{x.testing_datetime | thaidate}} ลงทะเบียน {{x.count_register}} เข้าสอบ {{x.count_test}} ขาดสอบ {{x.count_missing_test}} มีเกรด {{x.count_grade}} ยังไม่มีเกรด {{x.count_no_grade}}
+ +
+
+
diff --git a/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.scss b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.spec.ts b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.spec.ts new file mode 100644 index 0000000..9bc9bcf --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingViewTableSummarySubjectComponent } from './setting-view-table-summary-subject.component'; + +describe('SettingViewTableSummarySubjectComponent', () => { + let component: SettingViewTableSummarySubjectComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingViewTableSummarySubjectComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingViewTableSummarySubjectComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.ts b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.ts new file mode 100644 index 0000000..03e7585 --- /dev/null +++ b/src/app/feature/set-exam-information/presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component.ts @@ -0,0 +1,36 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import {BaseList} from '../../../../../core/base/base-list'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-setting-view-table-summary-subject', + templateUrl: './setting-view-table-summary-subject.component.html', + styleUrls: ['./setting-view-table-summary-subject.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingViewTableSummarySubjectComponent extends BaseList implements OnInit, OnChanges{ + query = { + testing_date: null, + }; + @Input() subjectList: any = []; + @Input() TestinforUid: any = []; + @Output() search = new EventEmitter(); + + column = ['1', '2', '3', '4', '5', '6', '7', '8']; + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList ? this.subjectList : []); + } + + onSearch(){ + this.query.testing_date = formatDate(this.query.testing_date, 'yyyy-MM-dd', 'en-US'); + this.search.emit(this.query.testing_date); + } + +} diff --git a/src/app/feature/set-exam-information/router/set-exam-information-router.ts b/src/app/feature/set-exam-information/router/set-exam-information-router.ts new file mode 100644 index 0000000..24988d2 --- /dev/null +++ b/src/app/feature/set-exam-information/router/set-exam-information-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-set-exam-information-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetExamInformationRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-exam-information/set-exam-information.module.ts b/src/app/feature/set-exam-information/set-exam-information.module.ts new file mode 100644 index 0000000..047b7e4 --- /dev/null +++ b/src/app/feature/set-exam-information/set-exam-information.module.ts @@ -0,0 +1,80 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SetExamInformationRouter } from './router/set-exam-information-router'; +import { SetExamInformationContainer } from './container/set-exam-information/set-exam-information.container'; +import { SetExamInformationListComponent } from './presenter/list/set-exam-information-list/set-exam-information-list.component'; +import { SetExamInformationFormComponent } from './presenter/form/set-exam-information-form/set-exam-information-form.component'; +import { SetExamInformationSearchComponent } from './presenter/search/set-exam-information-search/set-exam-information-search.component'; +import {MatTabsModule} from '@angular/material/tabs'; +import { SetExamInformationDialogComponent } from './presenter/dialog/set-exam-information-dialog/set-exam-information-dialog.component'; +import { SetExamInformationViewComponent } from './presenter/view/set-exam-information-view/set-exam-information-view.component'; +import { SettingExamViewTableSubjectComponent } from './presenter/view/setting-exam-view-table-subject/setting-exam-view-table-subject.component'; +import { SettingExamViewTableCenterComponent } from './presenter/view/setting-exam-view-table-center/setting-exam-view-table-center.component'; +import { SettingExamViewTableCalendarComponent } from './presenter/view/setting-exam-view-table-calendar/setting-exam-view-table-calendar.component'; +import { TableSwapSubjectComponent } from './presenter/form/table-swap-subject/table-swap-subject.component'; +import { SettingExamViewTableSectionComponent } from './presenter/view/setting-exam-view-table-section/setting-exam-view-table-section.component'; +import { SettingViewTableSummarySubjectComponent } from './presenter/view/setting-view-table-summary-subject/setting-view-table-summary-subject.component'; +import { ChangeTimeSectionComponent } from './presenter/view/dialog/change-time-section/change-time-section.component'; +import {NgxMaterialTimepickerModule} from 'ngx-material-timepicker'; + + +const routes: Routes = [ + { + path: '', + component: SetExamInformationRouter, + children: [ + { + path: '', + component: SetExamInformationContainer + }, + { + path: 'add', + component: SetExamInformationFormComponent + }, + { + path: 'edit/:id', + component: SetExamInformationFormComponent + }, + { + path: 'view/:id', + component: SetExamInformationViewComponent + }, + { + path: 'section/edit/:id', + component: ChangeTimeSectionComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + SetExamInformationRouter, + SetExamInformationContainer, + SetExamInformationListComponent, + SetExamInformationFormComponent, + SetExamInformationSearchComponent, + SetExamInformationDialogComponent, + SetExamInformationViewComponent, + SettingExamViewTableSubjectComponent, + SettingExamViewTableCenterComponent, + SettingExamViewTableCalendarComponent, + TableSwapSubjectComponent, + SettingExamViewTableSectionComponent, + SettingViewTableSummarySubjectComponent, + ChangeTimeSectionComponent + ], + exports: [ + TableSwapSubjectComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatTabsModule, + NgxMaterialTimepickerModule + ] +}) +export class SetExamInformationModule { } diff --git a/src/app/feature/set-permission/create-user/container/create-user/create-user.container.html b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.html new file mode 100644 index 0000000..c600cd2 --- /dev/null +++ b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.html @@ -0,0 +1,7 @@ + + + diff --git a/src/app/feature/set-permission/create-user/container/create-user/create-user.container.scss b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/create-user/container/create-user/create-user.container.spec.ts b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.spec.ts new file mode 100644 index 0000000..c907e5c --- /dev/null +++ b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateUserContainer } from './create-user.container'; + +describe('CreateUserContainer', () => { + let component: CreateUserContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateUserContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateUserContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/create-user/container/create-user/create-user.container.ts b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.ts new file mode 100644 index 0000000..59870f4 --- /dev/null +++ b/src/app/feature/set-permission/create-user/container/create-user/create-user.container.ts @@ -0,0 +1,43 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Observable } from 'rxjs'; +import { filter, concatMap, tap } from 'rxjs/operators'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-create-user', + templateUrl: './create-user.container.html', + styleUrls: ['./create-user.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateUserContainer implements OnInit { + userList$ = new Observable() + constructor( + private userOpenidSV: UserOpenidService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.userList$ = this.userOpenidSV.getAll() + } + + search(query){ + if(query) return this.userList$ = this.userOpenidSV.searchUser(`?${query}`) + if(!query) return this.userList$ = this.userOpenidSV.getAll() + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.userOpenidSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.userList$ = this.userOpenidSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/set-permission/create-user/create-user.module.ts b/src/app/feature/set-permission/create-user/create-user.module.ts new file mode 100644 index 0000000..989fe36 --- /dev/null +++ b/src/app/feature/set-permission/create-user/create-user.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { CreateUserRouter } from './router/router'; +import { CreateUserContainer } from './container/create-user/create-user.container'; +import { FormComponent } from './presenter/form/form/form.component'; +import { ListComponent } from './presenter/list/list/list.component'; +import { SearchComponent } from './presenter/search/search/search.component'; + +const routes: Routes = [ + { + path: '', + component: CreateUserRouter, + children: [ + { + path: '', + component: CreateUserContainer + }, + { + path: 'add', + component: FormComponent + }, + { + path: 'edit/:id', + component: FormComponent + } + ] + } +]; + +@NgModule({ + declarations: [ + CreateUserRouter, + CreateUserContainer, + FormComponent, + ListComponent, + SearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class CreateUserModule { } diff --git a/src/app/feature/set-permission/create-user/presenter/form/form/form.component.html b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.html new file mode 100644 index 0000000..c30f214 --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.html @@ -0,0 +1,75 @@ +
+

ข้อมูลผู้ดูแลระบบ

+
+
+
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + +
+
+ + + + visibility + visibility_off + + ใส่รหัสไม่ถูกต้องตามเงื่อนไข +
+
+ + + + visibility + visibility_off + + ใส่รหัสไม่ถูกต้องตามเงื่อนไข +
+
+ +
+
+ + +
+
+ +
+ รหัสผ่านควรมี พิมพ์เล็ก พิมพ์ใหญ่ ตัวเลขและต้องมีมากกว่า 8 ตัวอักษร +
+
+ + +
+ +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/set-permission/create-user/presenter/form/form/form.component.scss b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.scss new file mode 100644 index 0000000..69c55c1 --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.scss @@ -0,0 +1,4 @@ +input:focus::placeholder { + color:transparent !important; + +} diff --git a/src/app/feature/set-permission/create-user/presenter/form/form/form.component.spec.ts b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.spec.ts new file mode 100644 index 0000000..31024eb --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormComponent } from './form.component'; + +describe('FormComponent', () => { + let component: FormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/create-user/presenter/form/form/form.component.ts b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.ts new file mode 100644 index 0000000..17cd242 --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/form/form/form.component.ts @@ -0,0 +1,111 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { EMPTY, throwError } from 'rxjs'; +import { catchError, concatMap, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormComponent extends BaseFormUid implements OnInit { + confirm; + canEdit: boolean + viewPass = { + password: false, + confirm: false + }; + constructor( + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + public fb: FormBuilder, + private userOpenidSV: UserOpenidService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.canEdit = this.state == 'edit'? true : false + if(this.state == 'edit'){ + this.userOpenidSV.get(this.id).pipe( + tap(x => this.setupForm(x)), + tap(x => this.cdr.detectChanges()), + ).subscribe() + } + } + + setupForm(x){ + this.form.patchValue(x) + this.form.get('password').setValue(null) + } + + createForm(){ + return this.fb.group({ + user_uid: null, + login_name: [null,Validators.required], + display_name: [null,Validators.required], + password: [null,[ + Validators.required, + Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,30})') + ]], + confirm: [null,[ + Validators.required, + Validators.pattern('((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,30})') + ]], + agency_uid: "00000000-0000-0000-0000-000000000000", + image_url: "", + is_active: true, + group_name: "", + agency_name: "" + }) + } + + save(){ + const form = this.form.getRawValue() + const uid = form.user_uid + if(form.password == form.confirm){ + const save$ = this.state === 'edit'? this.userOpenidSV.changePassword(uid,form) : this.userOpenidSV.add(form); + return save$.pipe( + tap(() => this.state === 'edit'? this.swSV.updateSuccess() : this.swSV.saveSuccess()), + concatMap(() => { + if(this.state === 'edit'){ + const status$ = form.is_active === true ? this.userOpenidSV.active(uid) : this.userOpenidSV.inactive(uid); + return status$; + }else{ + return EMPTY; + } + }), + tap(() => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + }else{ + this.swSV.errText('รหัสผ่านไม่ตรงกัน') + } + } + + cancel(){ + this.location.back() + } + + changeViewPass(type){ + if (type === 'confirm'){ + this.viewPass.confirm = !this.viewPass.confirm; + }else { + this.viewPass.password = !this.viewPass.password; + } + } + +} diff --git a/src/app/feature/set-permission/create-user/presenter/list/list/list.component.html b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.html new file mode 100644 index 0000000..05fc8dc --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.html @@ -0,0 +1,44 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อ Login {{x.login_name}} ชื่อ-นามสกุล {{x.display_name}} สถานะ {{x.is_active? 'ใช้งาน' : 'ไม่ใช้งาน'}} เครื่องมือ +
+ +   + +
+
+ +
+
+
diff --git a/src/app/feature/set-permission/create-user/presenter/list/list/list.component.scss b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/create-user/presenter/list/list/list.component.spec.ts b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/create-user/presenter/list/list/list.component.ts b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.ts new file mode 100644 index 0000000..e5cf2ef --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/list/list/list.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() userList: any = []; + @Output() delete = new EventEmitter() + column = ['4','0','1','2','3'] + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.userList = this.updateMatTable(this.userList? this.userList:[]) + } + + onEdit(id){ + this.router.navigate(['create-user/edit',id]) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/set-permission/create-user/presenter/search/search/search.component.html b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.html new file mode 100644 index 0000000..fa3e9ab --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.html @@ -0,0 +1,20 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/set-permission/create-user/presenter/search/search/search.component.scss b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/create-user/presenter/search/search/search.component.spec.ts b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/create-user/presenter/search/search/search.component.ts b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.ts new file mode 100644 index 0000000..a091d1e --- /dev/null +++ b/src/app/feature/set-permission/create-user/presenter/search/search/search.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { Router } from '@angular/router'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Output() search = new EventEmitter() + query = { + login_name: null, + display_name: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + login_name: null, + display_name: null + } + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + add(){ + this.router.navigate(['create-user/add']) + } + +} diff --git a/src/app/feature/set-permission/create-user/router/router.ts b/src/app/feature/set-permission/create-user/router/router.ts new file mode 100644 index 0000000..d15b2c7 --- /dev/null +++ b/src/app/feature/set-permission/create-user/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-create-user-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateUserRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-permission/set-role/container/set-role/set-role.container.html b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.html new file mode 100644 index 0000000..d2230c3 --- /dev/null +++ b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.html @@ -0,0 +1,5 @@ + + + diff --git a/src/app/feature/set-permission/set-role/container/set-role/set-role.container.scss b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-role/container/set-role/set-role.container.spec.ts b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.spec.ts new file mode 100644 index 0000000..319d460 --- /dev/null +++ b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetRoleContainer } from './set-role.container'; + +describe('SetRoleContainer', () => { + let component: SetRoleContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetRoleContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetRoleContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-role/container/set-role/set-role.container.ts b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.ts new file mode 100644 index 0000000..f7cdc7a --- /dev/null +++ b/src/app/feature/set-permission/set-role/container/set-role/set-role.container.ts @@ -0,0 +1,43 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Observable } from 'rxjs'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { AppRoleService } from 'src/app/core/service/security/app-role.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-set-role', + templateUrl: './set-role.container.html', + styleUrls: ['./set-role.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetRoleContainer implements OnInit { + roleList$ = new Observable() + constructor( + private appRoleSV: AppRoleService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.roleList$ = this.appRoleSV.getAll() + } + + search(query){ + if(query) return this.roleList$ = this.appRoleSV.search(`?${query}`) + if(!query) return this.roleList$ = this.appRoleSV.getAll() + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.appRoleSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.roleList$ = this.appRoleSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.html b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.html new file mode 100644 index 0000000..fa9cf13 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.html @@ -0,0 +1,82 @@ +
+

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+
+
+
+
+

เพิ่มเมนู

+ +
+
+
+ + + + + {{x.app_object_name_th}} + + +
+
+ +
+ add_circle_outline +
+
+
+ + + +
+
+ + +
+ +
+ + +
+ +
+ +
+ add_circle_outline + remove_circle_outline +
+ +
+
+
+
+
+
+
+ + +
+ +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.scss b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.spec.ts b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.spec.ts new file mode 100644 index 0000000..3738644 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetRoleFormComponent } from './set-role-form.component'; + +describe('SetRoleFormComponent', () => { + let component: SetRoleFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetRoleFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetRoleFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.ts b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.ts new file mode 100644 index 0000000..d382800 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/form/set-role-form/set-role-form.component.ts @@ -0,0 +1,180 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormArray, FormBuilder, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { catchError, map, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { AppObjectService } from 'src/app/core/service/security/app-object.service'; +import { AppPermissionService } from 'src/app/core/service/security/app-permission.service'; +import { AppRoleService } from 'src/app/core/service/security/app-role.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { makeRandom } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-set-role-form', + templateUrl: './set-role-form.component.html', + styleUrls: ['./set-role-form.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetRoleFormComponent extends BaseForm implements OnInit { + object$ = new Observable() + perm$ = new Observable() + object:any = []; + currentObject; + perm; + role; + currentRole; + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + private appRoleSV: AppRoleService, + private appPermSV: AppPermissionService, + private appObjectSV: AppObjectService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.appObjectSV.getAll().pipe( + map((res: any) => res.filter(object => object.status_id == 1)), + tap(x => this.object = x) + ).subscribe() + this.appPermSV.getAll().pipe(tap(x => this.perm = x)).subscribe() + this.appRoleSV.getAll().pipe(tap(x => this.role = x)).subscribe() + if(this.state == 'edit'){ + this.appRoleSV.get(this.id).pipe( + tap(x => this.setupForm(x)) + ).subscribe() + } + this.cdr.detectChanges() + } + + setCurrentObject(x){ + this.currentObject = x + } + + addObject(){ + const form = this.form.get('app_securities') as FormArray + form.push(this.createDataSearchPerm(this.currentObject)) + } + + setupForm(x){ + this.currentRole = x; + this.form.patchValue(x) + this.form.setControl('app_securities',this.fb.array(x.app_securities.map(z => this.createArray(z)))) + this.cdr.detectChanges() + } + + createForm(){ + return this.fb.group({ + app_role_id: [null], + app_role_code: [makeRandom()], + app_role_name_en: ['',Validators.required], + app_role_name_th: [''], + app_role_type_id: [null], + status_id: [1], + create_by: [null], + create_datetime: [null], + last_update_by: [null], + last_update_datetime: [null], + app_securities: this.fb.array([ + // this.createArray() + ]) + }) + } + + createArray(role?){ + return this.fb.group({ + app_security_id: role?.app_security_id, + app_role_id: role?.app_role_id, + app_object_code: role?.app_object_code, + app_object_id: [role?.app_object_id,Validators.required], + app_permission_id: [role?.app_permission_id,Validators.required], + app_permission_code: role?.app_permission_code, + restrict_user: [role?.restrict_user || true] + }) + } + + createFullPerm(role){ + return this.fb.group({ + app_security_id: role?.app_security_id, + app_role_id: role?.app_role_id, + app_object_code: role?.app_object_code, + app_object_id: [role?.app_object_id,Validators.required], + app_permission_id: 4, + app_permission_code: role?.app_permission_code, + restrict_user: [role?.restrict_user || true] + }) + } + + createDataSearchPerm(role){ + return this.fb.group({ + app_security_id: role?.app_security_id, + app_role_id: role?.app_role_id, + app_object_code: role?.app_object_code, + app_object_id: [role?.app_object_id,Validators.required], + app_permission_id: [role?.app_permission_id,Validators.required], + app_permission_code: role?.app_permission_code, + restrict_user: [role?.restrict_user || true] + }) + } + + addAllPerm(event){ + const form = this.form.get('app_securities') as FormArray + if(event){ + this.form.setControl('app_securities',this.fb.array(this.object.map(x => this.createFullPerm(x)))) + } else { + form.clear() + form.push(this.createArray()) + } + + } + + add(){ + const form = this.form.get('app_securities') as FormArray + form.push(this.createArray()) + } + + remove(i){ + const form = this.form.get('app_securities') as FormArray + form.removeAt(i) + } + + save(){ + const form = this.form.getRawValue() + form.app_role_name_th = form.app_role_name_en + const isDuplicate = this.role.find(x => x.app_role_code == form.app_role_code)? true : false + const current = form.app_role_code == this.currentRole?.app_role_code? true : false + if(this.state == 'edit' && (isDuplicate == false || current == true)){ + this.appRoleSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } else if (this.state == 'add' && (isDuplicate == false || current == true)){ + this.appRoleSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } else { + this.swSV.errText('รหัสซ้ำกัน') + } + } + + cancel(){ + this.location.back() + } +} diff --git a/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.html b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.html new file mode 100644 index 0000000..e508d70 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.html @@ -0,0 +1,40 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} รหัส {{x.app_role_code}} ชื่อสิทธิ์ {{x.app_role_name_en}} เครื่องมือ +
+ +   + +
+
+ +
+
+
diff --git a/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.scss b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.spec.ts b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.spec.ts new file mode 100644 index 0000000..d2001df --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetRoleListComponent } from './set-role-list.component'; + +describe('SetRoleListComponent', () => { + let component: SetRoleListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetRoleListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetRoleListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.ts b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.ts new file mode 100644 index 0000000..25526ae --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/list/set-role-list/set-role-list.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'set-role-list', + templateUrl: './set-role-list.component.html', + styleUrls: ['./set-role-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetRoleListComponent extends BaseList implements OnInit,OnChanges { + @Input() roleList: any = []; + @Output() delete = new EventEmitter() + column = ['4','1','2','3'] + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.roleList = this.updateMatTable(this.roleList? this.roleList:[]) + } + + onEdit(id){ + this.router.navigate(['set-role/edit',id]) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.html b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.html new file mode 100644 index 0000000..4dcb353 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.html @@ -0,0 +1,20 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.scss b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.spec.ts b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.spec.ts new file mode 100644 index 0000000..a86c879 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetRoleSearchComponent } from './set-role-search.component'; + +describe('SetRoleSearchComponent', () => { + let component: SetRoleSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetRoleSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetRoleSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.ts b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.ts new file mode 100644 index 0000000..2bfdec7 --- /dev/null +++ b/src/app/feature/set-permission/set-role/presenter/search/set-role-search/set-role-search.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { Router } from '@angular/router'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'set-role-search', + templateUrl: './set-role-search.component.html', + styleUrls: ['./set-role-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetRoleSearchComponent implements OnInit { + @Output() search = new EventEmitter() + query = { + app_role_name_en: null, + app_role_code: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + app_role_name_en: null, + app_role_code: null + } + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + add(){ + this.router.navigate(['set-role/add']) + } + +} diff --git a/src/app/feature/set-permission/set-role/router/router.ts b/src/app/feature/set-permission/set-role/router/router.ts new file mode 100644 index 0000000..61d5fcb --- /dev/null +++ b/src/app/feature/set-permission/set-role/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-set-role-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetRoleRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-permission/set-role/set-role.module.ts b/src/app/feature/set-permission/set-role/set-role.module.ts new file mode 100644 index 0000000..4bb8640 --- /dev/null +++ b/src/app/feature/set-permission/set-role/set-role.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SetRoleRouter } from './router/router'; +import { SetRoleContainer } from './container/set-role/set-role.container'; +import { SetRoleFormComponent } from './presenter/form/set-role-form/set-role-form.component'; +import { SetRoleListComponent } from './presenter/list/set-role-list/set-role-list.component'; +import { SetRoleSearchComponent } from './presenter/search/set-role-search/set-role-search.component'; + +const routes: Routes = [ + { + path: '', + component: SetRoleRouter, + children: [ + { + path: '', + component: SetRoleContainer + }, + { + path: 'add', + component: SetRoleFormComponent + }, + { + path: 'edit/:id', + component: SetRoleFormComponent + } + ] + } +]; + +@NgModule({ + declarations: [ + SetRoleRouter, + SetRoleContainer, + SetRoleFormComponent, + SetRoleListComponent, + SetRoleSearchComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class SetRoleModule { } diff --git a/src/app/feature/set-permission/set-user/container/set-user/set-user.container.html b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.html new file mode 100644 index 0000000..f1cb2ff --- /dev/null +++ b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/feature/set-permission/set-user/container/set-user/set-user.container.scss b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-user/container/set-user/set-user.container.spec.ts b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.spec.ts new file mode 100644 index 0000000..fc5a2a0 --- /dev/null +++ b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SetUserContainer } from './set-user.container'; + +describe('SetUserContainer', () => { + let component: SetUserContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SetUserContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SetUserContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-user/container/set-user/set-user.container.ts b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.ts new file mode 100644 index 0000000..014a215 --- /dev/null +++ b/src/app/feature/set-permission/set-user/container/set-user/set-user.container.ts @@ -0,0 +1,44 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Observable } from 'rxjs'; +import { filter } from 'rxjs/internal/operators/filter'; +import { concatMap, tap } from 'rxjs/operators'; +import { AppUserService } from 'src/app/core/service/security/app-user.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-set-user', + templateUrl: './set-user.container.html', + styleUrls: ['./set-user.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetUserContainer implements OnInit { + userList$ = new Observable() + constructor( + private appUserSV: AppUserService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.userList$ = this.appUserSV.getAll() + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.appUserSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.userList$ = this.appUserSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.userList$ = this.appUserSV.search(`?${query}`) + if(!query) return this.userList$ = this.appUserSV.getAll() + } + +} diff --git a/src/app/feature/set-permission/set-user/presenter/form/form/form.component.html b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.html new file mode 100644 index 0000000..2a54c2b --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.html @@ -0,0 +1,55 @@ +
+

ข้อมูลผู้ดูแลระบบ

+
+
+
+ + + + + {{x.login_name}} + + +
+ +
+ + +
+
+
+
+
+

เพิ่มสิทธิ์การเข้าถึงเมนู

+ + +
+
+ + +
+ +
+ +
+ add_circle_outline + remove_circle_outline +
+
+
+
+
+
+
+
+ + +
+ +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/set-permission/set-user/presenter/form/form/form.component.scss b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-user/presenter/form/form/form.component.spec.ts b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.spec.ts new file mode 100644 index 0000000..31024eb --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormComponent } from './form.component'; + +describe('FormComponent', () => { + let component: FormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-user/presenter/form/form/form.component.ts b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.ts new file mode 100644 index 0000000..1912ffe --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/form/form/form.component.ts @@ -0,0 +1,113 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, Validators, FormArray } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { OpenidService } from 'src/app/core/base/base-openid-service'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { AppRoleService } from 'src/app/core/service/security/app-role.service'; +import { AppUserService } from 'src/app/core/service/security/app-user.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormComponent extends BaseForm implements OnInit { + role$ = new Observable() + user: any = []; + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + private appRoleSV: AppRoleService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private appUserSV: AppUserService, + private userOpenidSV: UserOpenidService + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + this.userOpenidSV.getAll().pipe(tap(x => this.user = x)).subscribe() + this.role$ = this.appRoleSV.getAll() + if(this.state == 'edit'){ + this.appUserSV.get(this.id).pipe( + tap(x => this.setupForm(x)), + ).subscribe() + } + } + + setDisplayName(x){ + this.form.get('display_name').setValue(x.display_name) + } + + setupForm(x){ + this.form.patchValue(x) + this.form.setControl('app_user_roles',this.fb.array(x.app_user_roles.map(z => this.createArray(z)))) + this.cdr.detectChanges() + } + + createForm(){ + return this.fb.group({ + app_user_id: [null], + login_name: ['',Validators.required], + display_name: [''], + app_user_type_id: 1, + app_user_roles: this.fb.array([ + this.createArray() + ]) + }) + } + + createArray(role?){ + return this.fb.group({ + app_user_id: role?.app_user_id, + app_role_id: [role?.app_role_id,Validators.required], + app_user_role_id: role?.app_user_role_id + }) + } + + add(){ + const form = this.form.get('app_user_roles') as FormArray + form.push(this.createArray()) + } + + remove(i){ + const form = this.form.get('app_user_roles') as FormArray + form.removeAt(i) + } + + save(){ + const form = this.form.getRawValue() + if(this.state == 'edit'){ + this.appUserSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } else { + this.appUserSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.location.back() + } +} diff --git a/src/app/feature/set-permission/set-user/presenter/list/list/list.component.html b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.html new file mode 100644 index 0000000..784f417 --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.html @@ -0,0 +1,40 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อ Login {{x.login_name}} ชื่อ-นามสกุล {{x.display_name}} เครื่องมือ +
+ +   + +
+
+ +
+
+
diff --git a/src/app/feature/set-permission/set-user/presenter/list/list/list.component.scss b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-user/presenter/list/list/list.component.spec.ts b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-user/presenter/list/list/list.component.ts b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.ts new file mode 100644 index 0000000..c2b8109 --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/list/list/list.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() userList: any = []; + @Output() delete = new EventEmitter() + column = ['3','0','1','2'] + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.userList = this.updateMatTable(this.userList? this.userList:[]) + } + + onEdit(id){ + this.router.navigate(['set-user/edit',id]) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/set-permission/set-user/presenter/search/search/search.component.html b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.html new file mode 100644 index 0000000..cd6ac00 --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.html @@ -0,0 +1,20 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/set-permission/set-user/presenter/search/search/search.component.scss b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/set-user/presenter/search/search/search.component.spec.ts b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/set-user/presenter/search/search/search.component.ts b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.ts new file mode 100644 index 0000000..04876a3 --- /dev/null +++ b/src/app/feature/set-permission/set-user/presenter/search/search/search.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { Router } from '@angular/router'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Output() search = new EventEmitter() + query = { + login_name: null, + display_name: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + login_name: null, + display_name: null + } + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + add(){ + this.router.navigate(['set-user/add']) + } + +} diff --git a/src/app/feature/set-permission/set-user/router/router.ts b/src/app/feature/set-permission/set-user/router/router.ts new file mode 100644 index 0000000..a870a7b --- /dev/null +++ b/src/app/feature/set-permission/set-user/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-set-user-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SetUserRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-permission/set-user/set-user.module.ts b/src/app/feature/set-permission/set-user/set-user.module.ts new file mode 100644 index 0000000..fc975c8 --- /dev/null +++ b/src/app/feature/set-permission/set-user/set-user.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SetUserRouter } from './router/router'; +import { SetUserContainer } from './container/set-user/set-user.container'; +import { SearchComponent } from './presenter/search/search/search.component'; +import { ListComponent } from './presenter/list/list/list.component'; +import { FormComponent } from './presenter/form/form/form.component'; + +const routes: Routes = [ + { + path: '', + component: SetUserRouter, + children: [ + { + path: '', + component: SetUserContainer + }, + { + path: 'add', + component: FormComponent + }, + { + path: 'edit/:id', + component: FormComponent + } + ] + } +]; + +@NgModule({ + declarations: [ + SetUserRouter, + SetUserContainer, + SearchComponent, + ListComponent, + FormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class SetUserModule { } diff --git a/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.html b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.html new file mode 100644 index 0000000..8ee20ef --- /dev/null +++ b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.html @@ -0,0 +1,10 @@ + + + diff --git a/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.scss b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.spec.ts b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.spec.ts new file mode 100644 index 0000000..2c6a1a9 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCouterContainer } from './user-couter.container'; + +describe('UserCouterContainer', () => { + let component: UserCouterContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserCouterContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserCouterContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.ts b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.ts new file mode 100644 index 0000000..b477b8d --- /dev/null +++ b/src/app/feature/set-permission/user-couter/container/user-couter/user-couter.container.ts @@ -0,0 +1,55 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import {Observable} from 'rxjs'; +import {Router} from '@angular/router'; +import { UserCountersService } from 'src/app/core/service/permission/user-counters.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { concatMap, filter, tap } from 'rxjs/operators'; + +@Component({ + selector: 'app-user-couter', + templateUrl: './user-couter.container.html', + styleUrls: ['./user-couter.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCouterContainer implements OnInit { + userCounterList$ = new Observable(); + + constructor( + private router: Router, + private userCounterSV: UserCountersService, + public swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.userCounterList$ = this.userCounterSV.getAll() + } + + add(){ + this.router.navigate(['user-counter/add']); + } + + edit(id){ + this.router.navigate(['user-counter/edit', id]); + } + + delete(id){ + console.log(id); + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.userCounterSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.userCounterList$ = this.userCounterSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.userCounterList$ = this.userCounterSV.search(`?${query}`); + if(!query) return this.userCounterList$ = this.userCounterSV.getAll(); + } + +} diff --git a/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.html b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.html new file mode 100644 index 0000000..79708c2 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.html @@ -0,0 +1,113 @@ +
+

กำหนด Counter

+
+
+
+ + + + + + + +
+
+ + + + + + +
+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ กำหนด User +
+

จำนวน

+ +
+ +
+ + + +
+
+ + +
+
+ + +
+
+ + +
+ ใช้งาน +
+
+ ไม่ได้ใช้งาน +
+
+
+
+
+
+
+
+
+
+ + +
+
+
+  {{form.getRawValue() | json}}
+
diff --git a/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.scss b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.spec.ts b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.spec.ts new file mode 100644 index 0000000..3ce3fbe --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCouterFormComponent } from './user-couter-form.component'; + +describe('UserCouterFormComponent', () => { + let component: UserCouterFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserCouterFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserCouterFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.ts b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.ts new file mode 100644 index 0000000..4930101 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/form/user-couter-form/user-couter-form.component.ts @@ -0,0 +1,191 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, ViewChild} from '@angular/core'; +import {FormArray, FormBuilder, Validators} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {BaseForm, sortByProperty} from '../../../../../../core/base/base-form'; +import { UserCountersService } from 'src/app/core/service/permission/user-counters.service'; +import { catchError, tap } from 'rxjs/operators'; +import { throwError } from 'rxjs'; +import { splitAtColon } from '@angular/compiler/src/util'; + +@Component({ + selector: 'app-user-couter-form', + templateUrl: './user-couter-form.component.html', + styleUrls: ['./user-couter-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCouterFormComponent extends BaseForm implements OnInit { + today = new Date(); + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private userCounterSV: UserCountersService + ) { + super(router,activeRoute,fb,location); + } + + ngOnInit(): void { + if(this.state == 'edit'){ + this.userCounterSV.get(this.id).pipe( + tap(x => this.setupForm(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + } + + setupForm(x){ + this.form.patchValue(x) + this.form.get('counter_amount').setValue(x.counter_details.length) + this.form.setControl('counter_periods',this.fb.array(x.counter_periods.map(a => this.createCounterPeriods(a)))) + this.form.setControl('counter_details',this.fb.array(x.counter_details.sort(sortByProperty('counter_no')).map(a => this.createCounterDetails(null,a)))) + } + + createForm(){ + return this.fb.group({ + counter_amount: null, + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + counter_uid: null, + counter_open_date: [null,Validators.required], + counter_close_date: [null,Validators.required], + total_counter: [null], + fiscal_year: null, + counter_periods: this.fb.array([ + this.createCounterPeriods() + ]), + counter_details: this.fb.array([],Validators.required) + }) + } + + createCounterPeriods(update?){ + return this.fb.group({ + status_id: update?.status_id, + created_by: update?.created_by, + created_datetime: update?.created_datetime, + updated_by: update?.updated_by, + updated_datetime: update?.updated_datetime, + deleted_by: update?.deleted_by, + deleted_datetime: update?.deleted_datetime, + counter_period_uid: update?.counter_period_uid, + counter_uid: update?.counter_uid, + period: [update?.period,Validators.required], + counter_open_time: [update?.counter_open_time,Validators.required], + counter_close_time: [update?.counter_close_time,Validators.required], + summary_end_time: [update?.summary_end_time,Validators.required], + }) + } + + createCounterDetails(pin,update?){ + return this.fb.group({ + status_id: update?.status_id, + created_by: update?.created_by, + created_datetime: update?.created_datetime, + updated_by: update?.updated_by, + updated_datetime: update?.updated_datetime, + deleted_by: update?.deleted_by, + deleted_datetime: update?.deleted_datetime, + counter_detail_uid: update?.counter_detail_uid, + counter_uid: update?.counter_uid, + counter_no: [update?.counter_no,Validators.required], + counter_pin: update? update.counter_pin : pin, + is_use: [update?.is_use? update.is_use: false] + }) + } + + addCounterPeriods(){ + const form = this.form.get('counter_periods') as FormArray + form.push(this.createCounterPeriods()) + } + + removeCounterPeriods(index){ + const form = this.form.get('counter_periods') as FormArray + form.removeAt(index) + } + + addCounterDetails(){ + const no = this.form.get('counter_amount').value + const form = this.form.get('counter_details') as FormArray + form.clear() + Array.from({ length: no }, (x, i) => { + const pin = Math.floor(10000 + Math.random() * 90000).toString(); + form.push(this.createCounterDetails(pin)) + }); + } + + save(){ + const form = this.form.getRawValue() + form.total_counter = form.counter_details.length + if(this.state == 'add'){ + this.userCounterSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + }else{ + this.userCounterSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.location.back() + } + + checkTimeValidation(event,currentForm,type){ + const formRawValue = currentForm.getRawValue() + const isOpenTimeInitial = formRawValue.counter_open_time? false : true + const isCloseTimeInitial = formRawValue.counter_close_time? false : true + const isEndTimeInitial = formRawValue.summary_end_time? false : true + const openTimeStamp = new Date(`2022-01-01 ${formRawValue.counter_open_time? formRawValue.counter_open_time: ""}`).getTime() + const closeTimeStamp = new Date(`2022-01-01 ${formRawValue.counter_close_time? formRawValue.counter_close_time: ""}`).getTime() + const endTimeStamp = new Date(`2022-01-01 ${formRawValue.summary_end_time? formRawValue.summary_end_time: ""}`).getTime() + + if(type == 'open'){ + if(isCloseTimeInitial) return + if(openTimeStamp > closeTimeStamp) { + this.swSV.errText('เวลาเปิดเค้าเตอร์มากกว่าเวลาปิดเค้าเตอร์') + return currentForm.get('counter_open_time').setValue("00:00") + } + } + if(type == 'close'){ + if(openTimeStamp > closeTimeStamp) { + if(isOpenTimeInitial) return + this.swSV.errText('เวลาปิดเค้าเตอร์มากกว่าเวลาเปิดเค้าเตอร์') + if(!isEndTimeInitial) return currentForm.get('counter_close_time').setValue(currentForm.get('summary_end_time').value) + return currentForm.get('counter_close_time').setValue("23:59") + } + if(endTimeStamp < closeTimeStamp){ + if(isEndTimeInitial) return + this.swSV.errText('เวลาปิดเค้าเตอร์มากกว่าเวลาสรุปยอด') + return currentForm.get('counter_close_time').setValue(currentForm.get('summary_end_time').value) + } + } + if(type == 'end'){ + if(isCloseTimeInitial) return + if(endTimeStamp < closeTimeStamp) { + this.swSV.errText('เวลาสรุปยอดน้อยกว่าเวลาปิดเค้าเตอร์') + return currentForm.get('summary_end_time').setValue(currentForm.get('counter_close_time').value) + } + } + } + +} diff --git a/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.html b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.html new file mode 100644 index 0000000..d0cac30 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.html @@ -0,0 +1,45 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
เครื่องมือ +
+ + +
+
จำนวนเค้าเตอร์ {{x.total_counter}} วันที่เปิดเค้าเตอร์ {{x.counter_open_date | thaidate }} วันที่ปิดเค้าเตอร์ {{x.counter_close_date | thaidate }} ผู้สร้าง {{x.created_by}} วันที่สร้าง {{x.created_datetime | thaidate}}
+ +
+
+
diff --git a/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.scss b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.spec.ts b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.spec.ts new file mode 100644 index 0000000..1ce25a2 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCouterListComponent } from './user-couter-list.component'; + +describe('UserCouterListComponent', () => { + let component: UserCouterListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserCouterListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserCouterListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.ts b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.ts new file mode 100644 index 0000000..52f7c0d --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/list/user-couter-list/user-couter-list.component.ts @@ -0,0 +1,34 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-user-couter-list', + templateUrl: './user-couter-list.component.html', + styleUrls: ['./user-couter-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCouterListComponent extends BaseList implements OnInit,OnChanges { + @Input() userCounterList: any = []; + @Output() delete = new EventEmitter(); + @Output() edit = new EventEmitter(); + column = ['1','2','3','4','5','6']; + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.userCounterList = this.updateMatTable(this.userCounterList? this.userCounterList:[]) + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.html b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.html new file mode 100644 index 0000000..184b308 --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.html @@ -0,0 +1,32 @@ +

ค้นหา

+
+
+
+
+ + + + + + +
+ +
+ + + + + + +
+
+ +
+ + + +
+
+
+ + diff --git a/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.scss b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.spec.ts b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.spec.ts new file mode 100644 index 0000000..fa618cc --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCouterSearchComponent } from './user-couter-search.component'; + +describe('UserCouterSearchComponent', () => { + let component: UserCouterSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserCouterSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserCouterSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.ts b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.ts new file mode 100644 index 0000000..792714d --- /dev/null +++ b/src/app/feature/set-permission/user-couter/presenter/search/user-couter-search/user-couter-search.component.ts @@ -0,0 +1,44 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {formatDate} from '@angular/common'; + +@Component({ + selector: 'app-user-couter-search', + templateUrl: './user-couter-search.component.html', + styleUrls: ['./user-couter-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCouterSearchComponent implements OnInit { + + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + query = { + counter_close_date: null, + counter_open_date: null + }; + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + if(this.query.counter_open_date) this.query.counter_open_date = formatDate(this.query.counter_open_date, 'yyyy-MM-dd', 'en-US'); + if(this.query.counter_close_date) this.query.counter_close_date = formatDate(this.query.counter_close_date, 'yyyy-MM-dd', 'en-US'); + const query = createQueryStringFromObject(this.query); + this.search.emit(query) ; + } + + clear(){ + this.query = { + counter_close_date: null, + counter_open_date: null + }; + const query = createQueryStringFromObject(this.query); + this.search.emit(query) ; + } + +} diff --git a/src/app/feature/set-permission/user-couter/user-couter-router/user-couter-router.ts b/src/app/feature/set-permission/user-couter/user-couter-router/user-couter-router.ts new file mode 100644 index 0000000..2aaaabf --- /dev/null +++ b/src/app/feature/set-permission/user-couter/user-couter-router/user-couter-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-user-couter-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UserCouterRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/set-permission/user-couter/user-couter.module.ts b/src/app/feature/set-permission/user-couter/user-couter.module.ts new file mode 100644 index 0000000..932394f --- /dev/null +++ b/src/app/feature/set-permission/user-couter/user-couter.module.ts @@ -0,0 +1,54 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { UserCouterRouter } from './user-couter-router/user-couter-router'; +import { UserCouterContainer } from './container/user-couter/user-couter.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import {MatTabsModule} from '@angular/material/tabs'; +import { UserCouterFormComponent } from './presenter/form/user-couter-form/user-couter-form.component'; +import { UserCouterListComponent } from './presenter/list/user-couter-list/user-couter-list.component'; +import { UserCouterSearchComponent } from './presenter/search/user-couter-search/user-couter-search.component'; + +const routes: Routes = [ + { + path: '', + component: UserCouterRouter, + children: [ + { + path: '', + component: UserCouterContainer + }, + { + path: 'add', + component: UserCouterFormComponent + }, + { + path: 'edit/:id', + component: UserCouterFormComponent + } + // { + // path: '', + // component: SetExamInformationContainer + // }, + // { + // path: 'add', + // component: SetExamInformationFormComponent + // }, + // { + // path: 'edit/:id', + // component: SetExamInformationFormComponent + // }, + ] + } +]; + +@NgModule({ + declarations: [UserCouterRouter, UserCouterContainer, UserCouterFormComponent, UserCouterListComponent, UserCouterSearchComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + MatTabsModule + ] +}) +export class UserCouterModule { } diff --git a/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.html b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.html new file mode 100644 index 0000000..c760bd6 --- /dev/null +++ b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.html @@ -0,0 +1,11 @@ + + + + + + diff --git a/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.scss b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.spec.ts b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.spec.ts new file mode 100644 index 0000000..583772f --- /dev/null +++ b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamContainer } from './setting-exam.container'; + +describe('SettingExamContainer', () => { + let component: SettingExamContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.ts b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.ts new file mode 100644 index 0000000..d185637 --- /dev/null +++ b/src/app/feature/setting-exam/container/setting-exam/setting-exam.container.ts @@ -0,0 +1,43 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { SubjectsService } from 'src/app/core/service/settings/subjects.service'; +import {SweetalertService} from '../../../../core/service/sweetalert/sweetalert'; +import {tap} from 'rxjs/operators'; + +@Component({ + selector: 'app-setting-exam', + templateUrl: './setting-exam.container.html', + styleUrls: ['./setting-exam.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamContainer implements OnInit { + subjectList$ = new Observable() + constructor( + private router: Router, + private subjectSV: SubjectsService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + this.swSV.loadingStart(); + this.subjectList$ = this.subjectSV.getAll().pipe( + tap(x => this.swSV.close()), + ); + } + + add(){ + this.router.navigate(['setting-exam/add']) + } + + edit(id){ + this.router.navigate(['setting-exam/edit',id]) + } + + search(query){ + if(query) return this.subjectList$ = this.subjectSV.search(`?${query}`) + if(!query) return this.subjectList$ = this.subjectSV.getAll() + } + +} diff --git a/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.html b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.html new file mode 100644 index 0000000..7c49dd9 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.html @@ -0,0 +1,122 @@ +
+ +

{{state == 'edit' ? 'แก้ไขข้อมูลรายวิชา' : 'เพิ่มข้อมูลรายวิชา'}}

+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + + กรองเป็นภาษาอังกฤษเท่านั้น +
+
+ +
+
+ + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.faculty_name_th}} + + +
+
+ + +
+
+ + + +
+ +
+
+ + + + +
+ +
+ + +
+
+ + search +
+
+
+ +
+

หมายเหตุในการสอบสำหรับผู้สอบ

+ + + +
+ +
+ + + +
+
+ +
+
{{form.getRawValue() | json}}
diff --git a/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.scss b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.spec.ts b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.spec.ts new file mode 100644 index 0000000..61e0067 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamFormComponent } from './setting-exam-form.component'; + +describe('SettingExamFormComponent', () => { + let component: SettingExamFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.ts b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.ts new file mode 100644 index 0000000..7c1e390 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/form/setting-exam-form/setting-exam-form.component.ts @@ -0,0 +1,218 @@ +import {Location} from '@angular/common'; +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, ViewChild} from '@angular/core'; +import {FormBuilder, Validators} from '@angular/forms'; +import {MatGridTileHeaderCssMatStyler} from '@angular/material/grid-list'; +import {ActivatedRoute, NavigationEnd, Router} from '@angular/router'; +import {concat, Observable, throwError} from 'rxjs'; +import {catchError, concatMap, debounceTime, filter, map, startWith, switchMap, tap} from 'rxjs/operators'; +import {BaseForm} from 'src/app/core/base/base-form'; +import {BaseTiny} from 'src/app/core/base/tinymce'; +import {DepartmentService} from 'src/app/core/service/settings/department.service'; +import {EducationTypesService} from 'src/app/core/service/settings/education-types.service'; +import {FacultysService} from 'src/app/core/service/settings/facultys.service'; +import {SubjectTypesService} from 'src/app/core/service/settings/subject-types.service'; +import {SubjectsService} from 'src/app/core/service/settings/subjects.service'; +import {SweetalertService} from 'src/app/core/service/sweetalert/sweetalert'; +import {UploadService} from 'src/app/core/service/upload/upload.service'; + +@Component({ + selector: 'app-setting-exam-form', + templateUrl: './setting-exam-form.component.html', + styleUrls: ['./setting-exam-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamFormComponent extends BaseForm implements OnInit { + @ViewChild('res', {static: true}) res: ElementRef + form; + subjectType$ = new Observable(); + educationType$ = new Observable(); + faculty; + selectfile; + subject; + curSub; + departmentList: any = []; + filteredDepartmentList: any = []; + isUse: boolean + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + + constructor( + public fb: FormBuilder, + private subjectTypeSV: SubjectTypesService, + private subjectSV: SubjectsService, + private educationTypeSV: EducationTypesService, + private facultySV: FacultysService, + private swSV: SweetalertService, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private cdr: ChangeDetectorRef, + private uploadSV: UploadService, + private departMentSV: DepartmentService + ) { + super( + router, + activeRoute, + fb, + location + ) + this.form = this.fb.group({ + status_id: [null, Validators.required], + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + subject_uid: null, + subject_code: [null, Validators.required], + subject_name_th: [null, Validators.required], + subject_name_en: [null, [Validators.pattern('^[a-zA-Z0-9_]*$'), Validators.required]], + education_type_uid: [null, Validators.required], + subject_type_uid: [null, Validators.required], + responsible_faculty_uid: [null, Validators.required], + major_name_th: null, + major_name_en: null, + remark: null, + file_url: null, + file_name: null, + }) + } + + ngOnInit(): void { + this.subjectType$ = this.subjectTypeSV.getAll() + this.educationType$ = this.educationTypeSV.getAll() + this.departMentSV.getAll().pipe( + tap(x => this.departmentList = x) + ).subscribe() + this.facultySV.getAll().pipe(tap(x => this.faculty = x)).subscribe() + this.subjectSV.getAll().pipe(tap(x => this.subject = x)).subscribe() + switch (this.state) { + case 'edit': + this.subjectSV.get(this.id).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.curSub = x), + tap(x => this.filterDepartment(null, x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.subjectSV.check(this.id).pipe( + tap((x: any) => this.isUse = x.is_use), + ).subscribe() + break; + + case 'add': + break; + } + } + + setupForm(x) { + + } + + filterDepartment(id, edit?) { + if (edit) { + this.filteredDepartmentList = this.departmentList.filter(x => x.faculty_uid == edit.responsible_faculty_uid) + } else { + this.form.get('major_name_th').setValue(null) + this.filteredDepartmentList = this.departmentList.filter(x => x.faculty_uid == id) + } + + } + + + save() { + const form = this.form.getRawValue() + const code = this.form.get('subject_code').value + const data = this.subject.find(x => x.subject_code == code) ? true : false + const cur = form.subject_code == this.curSub?.subject_code ? true : false + if (data == false || cur == true) { + switch (this.state) { + case 'edit': + if (this.isUse == true) { + this.swSV.confirm('วิชานี้มีการใช้งานอยู่ต้องการแก้ไขหรือไม่').pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.subjectSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ) + }) + ).subscribe() + } else { + this.subjectSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + } + break; + + case 'add': + this.subjectSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + break; + } + } else { + this.swSV.errText('รหัสวิชาซ้ำกัน') + } + } + + delete() { + const id = this.form.get('subject_uid').value + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.subjectSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.back()), + catchError(err => { + this.swSV.errText('เกิดข้อผิดพลาดหรือมีการใช้งานข้อมูลนี้อยู่') + return throwError(err) + }) + ) + }) + ).subscribe() + } + + cancel() { + window.history.back() + } + + onSelectFile(event) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + console.log(formData); + this.uploadSV.add(formData).pipe( + tap((x: any) => this.form.get('file_url').setValue(x[0].file_name)), + tap((x: any) => this.form.get('file_name').setValue(x[0].name)), + tap(x => this.cdr.detectChanges()), + ).subscribe() + } + } + + download() { + window.open(this.form.get('file_url').value) + } + + display(uid) { + // console.log(uid) + // console.log(this.faculty) + if (uid && this.faculty) return this.faculty.find(x => x.faculty_uid === uid)?.faculty_name_th + if (uid && !this.faculty) return this.curSub?.responsible_faculty_name_th + } + +} diff --git a/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.html b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.html new file mode 100644 index 0000000..03555ea --- /dev/null +++ b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.html @@ -0,0 +1,77 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} รหัสวิชา {{x.subject_code}} ชื่อวิชา (TH) {{x.subject_name_th}} ชื่อวิชา (EN) {{x.subject_name_en}} ประเภทวิชา {{x.subject_type_name_th}} หน่วยงาน {{x.responsible_faculty_name_th}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} สถานะ + ใช้งาน + ยกเลิก + มีข้อสอบ + {{x.is_use ? 'มี' : 'ไม่มี'}} + เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.scss b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.spec.ts b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.spec.ts new file mode 100644 index 0000000..2fc3098 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamListComponent } from './setting-exam-list.component'; + +describe('SettingExamListComponent', () => { + let component: SettingExamListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.ts b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.ts new file mode 100644 index 0000000..c0c2449 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/list/setting-exam-list/setting-exam-list.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; +import { BaseListRole } from 'src/app/core/base/base-list-role'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; + +@Component({ + selector: 'app-setting-exam-list', + templateUrl: './setting-exam-list.component.html', + styleUrls: ['./setting-exam-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamListComponent extends BaseList implements OnInit,OnChanges { + @Input() subjectList :any = []; + @Output() edit = new EventEmitter() + column = [ + '11', + '1', + 'subject_code', + 'subject_name_th', + 'subject_name_en', + 'subject_type_name_th', + 'responsible_faculty_name_th', + 'created_by', + 'created_datetime', + 'status_id', + 'is_use' + ]; + reload: boolean; + constructor( + // public route: Router, + // public activeRoute: ActivatedRoute, + // public appTokenSV: AppTokenService + ) { + super() + // super(route,activeRoute,appTokenSV) + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + // console.log(this.role) + } + + ngOnChanges(){ + this.subjectList = this.updateMatTable(this.subjectList? this.subjectList: []) + } + + onEdit(id){ + this.edit.emit(id) + } + +} diff --git a/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.html b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.html new file mode 100644 index 0000000..955fd48 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.html @@ -0,0 +1,30 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.scss b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.spec.ts b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.spec.ts new file mode 100644 index 0000000..e568c22 --- /dev/null +++ b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingExamSearchComponent } from './setting-exam-search.component'; + +describe('SettingExamSearchComponent', () => { + let component: SettingExamSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingExamSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingExamSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.ts b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.ts new file mode 100644 index 0000000..4deb00a --- /dev/null +++ b/src/app/feature/setting-exam/presenter/search/setting-exam-search/setting-exam-search.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-setting-exam-search', + templateUrl: './setting-exam-search.component.html', + styleUrls: ['./setting-exam-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamSearchComponent implements OnInit { + @Output() add = new EventEmitter() + @Output() search = new EventEmitter() + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + query = { + status_id: null, + subject_code: null, + responsible_faculty_name_th: null + } + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit() + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + status_id: null, + subject_code: null, + responsible_faculty_name_th: null + } + } + +} diff --git a/src/app/feature/setting-exam/router/setting-exam-router.ts b/src/app/feature/setting-exam/router/setting-exam-router.ts new file mode 100644 index 0000000..9751dc9 --- /dev/null +++ b/src/app/feature/setting-exam/router/setting-exam-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-setting-exam-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingExamRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/setting-exam/setting-exam.module.ts b/src/app/feature/setting-exam/setting-exam.module.ts new file mode 100644 index 0000000..1f04d17 --- /dev/null +++ b/src/app/feature/setting-exam/setting-exam.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { SettingExamContainer } from './container/setting-exam/setting-exam.container'; +import { SettingExamRouter } from './router/setting-exam-router'; +import { SettingExamSearchComponent } from './presenter/search/setting-exam-search/setting-exam-search.component'; +import { SettingExamListComponent } from './presenter/list/setting-exam-list/setting-exam-list.component'; +import { SettingExamFormComponent } from './presenter/form/setting-exam-form/setting-exam-form.component'; + +const routes : Routes =[ + { + path:'', + component: SettingExamRouter, + children:[ + { + path:'', + component: SettingExamContainer + }, + { + path:'add', + component: SettingExamFormComponent + }, + { + path:'edit/:id', + component: SettingExamFormComponent + }, + ] + } +] + +@NgModule({ + declarations: [ + SettingExamContainer, + SettingExamSearchComponent, + SettingExamRouter, + SettingExamListComponent, + SettingExamFormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class SettingExamModule { } diff --git a/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.html b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.html new file mode 100644 index 0000000..16dcca2 --- /dev/null +++ b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.html @@ -0,0 +1 @@ + diff --git a/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.scss b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.spec.ts b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.spec.ts new file mode 100644 index 0000000..7e5b026 --- /dev/null +++ b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SettingPrintCardContainer } from './setting-print-card.container'; + +describe('SettingPrintCardContainer', () => { + let component: SettingPrintCardContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingPrintCardContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingPrintCardContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.ts b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.ts new file mode 100644 index 0000000..c589f8b --- /dev/null +++ b/src/app/feature/setting-print-card/container/setting-print-card/setting-print-card.container.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-setting-print-card', + templateUrl: './setting-print-card.container.html', + styleUrls: ['./setting-print-card.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingPrintCardContainer implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/setting-print-card/presenter/search/search.component.html b/src/app/feature/setting-print-card/presenter/search/search.component.html new file mode 100644 index 0000000..7178170 --- /dev/null +++ b/src/app/feature/setting-print-card/presenter/search/search.component.html @@ -0,0 +1,56 @@ +
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.testing_information_name}} + + +
+ +
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
Section {{x.period_id}} เวลาเริ่มต้น + {{x.start_time}} + เวลาเริ่มต้น + + เวลาสิ้นสุด + +
+
+
+
+
+ + +
diff --git a/src/app/feature/setting-print-card/presenter/search/search.component.scss b/src/app/feature/setting-print-card/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/setting-print-card/presenter/search/search.component.spec.ts b/src/app/feature/setting-print-card/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/setting-print-card/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/setting-print-card/presenter/search/search.component.ts b/src/app/feature/setting-print-card/presenter/search/search.component.ts new file mode 100644 index 0000000..605df2d --- /dev/null +++ b/src/app/feature/setting-print-card/presenter/search/search.component.ts @@ -0,0 +1,62 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { CardPrintingTimeService } from 'src/app/core/service/card-print/card-printing-time.service'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + testingInfo; + time; + query = { + testing_information_uid: null + } + constructor( + private testingInfoSV: TestingInformationService, + private cardSV: CardPrintingTimeService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private location: Location + ) { } + + ngOnInit(): void { + this.testingInfoSV.getAll().pipe(tap(x => this.testingInfo = x)).subscribe() + } + + onSearch(){ + // console.log(this.query) + this.cardSV.getTime(this.query.testing_information_uid).pipe( + tap(x => this.time = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + displayBranch(item:string){ + if (item) return this.testingInfo.find(x => x.testing_information_uid == item)?.testing_information_name + } + + save(){ + // console.log(this.time) + this.cardSV.changeTime(this.time).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + + cancel(){ + this.location.back() + } + +} diff --git a/src/app/feature/setting-print-card/router/router.ts b/src/app/feature/setting-print-card/router/router.ts new file mode 100644 index 0000000..83fcf75 --- /dev/null +++ b/src/app/feature/setting-print-card/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-setting-print-card-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SettingPrintCardRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/setting-print-card/setting-print-card.module.ts b/src/app/feature/setting-print-card/setting-print-card.module.ts new file mode 100644 index 0000000..92d4d6e --- /dev/null +++ b/src/app/feature/setting-print-card/setting-print-card.module.ts @@ -0,0 +1,34 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { SettingPrintCardRouter } from './router/router'; +import { SettingPrintCardContainer } from './container/setting-print-card/setting-print-card.container'; +import { SearchComponent } from './presenter/search/search.component'; + +const routes: Routes = [ + { + path: '', + component: SettingPrintCardRouter, + children: [ + { + path: '', + component: SettingPrintCardContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + SettingPrintCardRouter, + SettingPrintCardContainer, + SearchComponent +], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class SettingPrintCardModule { } diff --git a/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.html b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.html new file mode 100644 index 0000000..369a072 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.scss b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.spec.ts b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.spec.ts new file mode 100644 index 0000000..0996817 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExamFinanceContainer } from './exam-finance.container'; + +describe('ExamFinanceContainer', () => { + let component: ExamFinanceContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExamFinanceContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExamFinanceContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.ts b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.ts new file mode 100644 index 0000000..643edc8 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/container/exam-finance/exam-finance.container.ts @@ -0,0 +1,47 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-exam-finance', + templateUrl: './exam-finance.container.html', + styleUrls: ['./exam-finance.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceContainer implements OnInit { + examFinanceList$ = new Observable(); + examFinanceListFalse$ = new Observable(); + index = 0 + constructor( + private examFinanceSV: TestingInformationService, //later change + private router: Router + ) { } + + ngOnInit(): void { + this.examFinanceList$ = this.examFinanceSV.getMaintrue(); + this.examFinanceListFalse$ = this.examFinanceSV.getMainfalse(); + } + + onIndex(index){ + this.index = index + } + + search(query){ + if(this.index == 0){ + query.is_main = true + let data = createQueryStringFromObject(query) + if(data) return this.examFinanceList$ = this.examFinanceSV.search(`?${data}`); + } + if(this.index == 1){ + let data = createQueryStringFromObject(query) + return this.examFinanceListFalse$ = this.examFinanceSV.searchFalse(`?${data}`); + } + } + + info(id){ + this.router.navigate(['setting-exam-finance/info/',id]) + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/exam-finance.module.ts b/src/app/feature/settings-finance/exam-finance/exam-finance.module.ts new file mode 100644 index 0000000..c4a68fb --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/exam-finance.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { ExamFinanceContainer } from './container/exam-finance/exam-finance.container'; +import { ExamFinanceRouter } from './router/exam-finance-router'; +import { ExamFinanceSearchComponent } from './presenter/search/exam-finance-search/exam-finance-search.component'; +import { ExamFinanceListComponent } from './presenter/list/exam-finance-list/exam-finance-list.component'; +import { ExamFinanceDialogComponent } from './presenter/dialog/exam-finance-dialog/exam-finance-dialog.component'; +import { ExamFinanceInfoComponent } from './presenter/info/exam-finance-info/exam-finance-info.component'; +import { FinanceIsMainTrueComponent } from './presenter/list/finance-is-main-true/finance-is-main-true.component'; +import { FinanceIsMainFalseComponent } from './presenter/list/finance-is-main-false/finance-is-main-false.component'; + +const routes : Routes =[ + { + path:'', + component: ExamFinanceRouter, + children:[ + { + path:'', + component: ExamFinanceContainer + }, + { + path:'info/:id', + component: ExamFinanceInfoComponent + }, + ] + } +] + +@NgModule({ + declarations: [ + ExamFinanceContainer, + ExamFinanceRouter, + ExamFinanceSearchComponent, + ExamFinanceListComponent, + ExamFinanceDialogComponent, + ExamFinanceInfoComponent, + FinanceIsMainTrueComponent, + FinanceIsMainFalseComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class ExamFinanceModule { } diff --git a/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.html b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.html new file mode 100644 index 0000000..ab75b96 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.html @@ -0,0 +1,30 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.spec.ts new file mode 100644 index 0000000..89ce857 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExamFinanceDialogComponent } from './exam-finance-dialog.component'; + +describe('ExamFinanceDialogComponent', () => { + let component: ExamFinanceDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExamFinanceDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExamFinanceDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.ts new file mode 100644 index 0000000..45774ff --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/dialog/exam-finance-dialog/exam-finance-dialog.component.ts @@ -0,0 +1,63 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingFeeService } from 'src/app/core/service/testing-information/testing-fee.service'; + +@Component({ + selector: 'app-exam-finance-dialog', + templateUrl: './exam-finance-dialog.component.html', + styleUrls: ['./exam-finance-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceDialogComponent implements OnInit { + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + constructor( + private fb: FormBuilder, + private testingFeeSV: TestingFeeService, //change later + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + testing_subject_uid: null, + subject_uid: null, + amount: null, + testing_information_uid: null, + }) + } + + ngOnInit(): void { + console.log(this.data) + this.form.patchValue(this.data.info) + } + + save(){ + const form = this.form.getRawValue() + this.testingFeeSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + + cancel(){ + this.dialogRef.close() + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.html b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.html new file mode 100644 index 0000000..9f2fe44 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.html @@ -0,0 +1,79 @@ +
+

กำหนดค่าใช้จ่ายของรอบการสอบ {{info?.testing_information_name}}

+
+
+ + +
+ +
+
+ + +
+
+ + +
+
+
+ +
+
+ + +
+ +
+
+ + +
+ + +
+
+ +
+ +
+ +
+ + +
+
+

แสดงผลรายการกระบวนวิชาสอบ

+
+ + + + + + + + + + + + + + + + + + + +
รหัสวิชา {{x.subject_code}} ชื่อวิชา {{x.subject_name_th}} ค่าธรรมเนียม {{x.amount}} เครื่องมือ +
+ +
+
+ +
+
+
diff --git a/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.spec.ts new file mode 100644 index 0000000..9ac6414 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExamFinanceInfoComponent } from './exam-finance-info.component'; + +describe('ExamFinanceInfoComponent', () => { + let component: ExamFinanceInfoComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExamFinanceInfoComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExamFinanceInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.ts new file mode 100644 index 0000000..013040a --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/info/exam-finance-info/exam-finance-info.component.ts @@ -0,0 +1,83 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, OnChanges, ChangeDetectorRef, ViewChild, AfterViewInit } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialog } from '@angular/material/dialog'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatTableDataSource } from '@angular/material/table'; +import { ActivatedRoute, Router } from '@angular/router'; +import { concatMap, tap } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BaseList } from 'src/app/core/base/base-list'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingFeeService } from 'src/app/core/service/testing-information/testing-fee.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { AcademicYearsDialogComponent } from 'src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component'; +import { ExamFinanceDialogComponent } from '../../dialog/exam-finance-dialog/exam-finance-dialog.component'; + +@Component({ + selector: 'app-exam-finance-info', + templateUrl: './exam-finance-info.component.html', + styleUrls: ['./exam-finance-info.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceInfoComponent extends BaseForm implements OnInit { + @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; + subjectList; + info: any; + id; + amount; + column=['1','2','3','4'] + constructor( + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private testingFeeSV: TestingFeeService, + private testingInformationSV: TestingInformationService, + public route: ActivatedRoute, + public router: Router, + public fb: FormBuilder, + public location: Location, + public swSV: SweetalertService + ) { + super(router,route,fb,location) + } + + ngOnInit(): void { + this.testingFeeSV.get(this.id).subscribe((x:any) => { + this.subjectList = new MatTableDataSource(x) + this.subjectList.paginator = this.paginator + }) + this.testingInformationSV.search('?testing_information_uid='+this.id).subscribe(x => { + this.info = x[0] + this.cdr.detectChanges() + }) + } + + edit(x){ + const dialogRef = this.dialog.open(ExamFinanceDialogComponent, { + width: '500px', + height: '460px', + data: { + info : x, + type : this.info.type_of_examinee + }, + }); + dialogRef.afterClosed().subscribe( + x => { + this.testingFeeSV.get(this.id).subscribe((x:any) => { + this.subjectList = new MatTableDataSource(x) + this.subjectList.paginator = this.paginator + }) + } + ) + } + + onAdd(){ + this.subjectList.data.map(x => { + x.amount = +this.amount + this.testingFeeSV.update2(x).subscribe(x => { + this.swSV.updateSuccess() + }) + }) + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.html b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.html new file mode 100644 index 0000000..0ccbd9e --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.html @@ -0,0 +1,29 @@ +
+
+

แสดงผลรายการค้นหา

+ + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.spec.ts new file mode 100644 index 0000000..c66c983 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExamFinanceListComponent } from './exam-finance-list.component'; + +describe('ExamFinanceListComponent', () => { + let component: ExamFinanceListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExamFinanceListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExamFinanceListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.ts new file mode 100644 index 0000000..9cf9a07 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/exam-finance-list/exam-finance-list.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'exam-finance-list', + templateUrl: './exam-finance-list.component.html', + styleUrls: ['./exam-finance-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceListComponent extends BaseList implements OnInit, OnChanges { + @Input() examFinanceList: any = []; + @Input() examFinanceListFalse: any = []; + @Output() info = new EventEmitter(); + @Output() delete = new EventEmitter(); + @Output() tabIndex = new EventEmitter(); + column = ['1', '2', '3', '4', '5', '6']; + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + } + + onTabChanged(event){ + // console.log(event) + // this.index = event.index + this.tabIndex.emit(event.index) + } + + onInfo(id){ + this.info.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.html b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.html new file mode 100644 index 0000000..0514bac --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.html @@ -0,0 +1,78 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรอบการสอบ {{x.testing_information_name}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.spec.ts new file mode 100644 index 0000000..e84cad5 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FinanceIsMainFalseComponent } from './finance-is-main-false.component'; + +describe('FinanceIsMainFalseComponent', () => { + let component: FinanceIsMainFalseComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FinanceIsMainFalseComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FinanceIsMainFalseComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.ts new file mode 100644 index 0000000..fa5e67a --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-false/finance-is-main-false.component.ts @@ -0,0 +1,55 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-finance-is-main-false', + templateUrl: './finance-is-main-false.component.html', + styleUrls: ['./finance-is-main-false.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FinanceIsMainFalseComponent extends BaseList implements OnInit, OnChanges { + @Input() dataFalse: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + @Output() info = new EventEmitter(); + reload: boolean; + column = [ + '1', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '12', + 'count_subject', + 'is_open', + 'created_by', + 'created_datetime', + '8' + ]; + constructor() { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.dataFalse = this.updateMatTable(this.dataFalse ? this.dataFalse : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onInfo(id){ + this.info.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.html b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.html new file mode 100644 index 0000000..8a9538f --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.html @@ -0,0 +1,83 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} วันที่เริ่มต้น-สิ้นสุด {{x.registration_start_datetime | thaidate}} - {{x.registration_end_datetime | thaidate}} จำนวนวิชา {{x.count_subject}} สถานะรอบสอบ +
+ เปิดรอบสอบแล้ว +
+
+ ปิดรอบสอบแล้ว +
+
+ กำลังสร้าง +
+
ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.spec.ts new file mode 100644 index 0000000..4f1210f --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FinanceIsMainTrueComponent } from './finance-is-main-true.component'; + +describe('FinanceIsMainTrueComponent', () => { + let component: FinanceIsMainTrueComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FinanceIsMainTrueComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FinanceIsMainTrueComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.ts new file mode 100644 index 0000000..3604bf7 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/list/finance-is-main-true/finance-is-main-true.component.ts @@ -0,0 +1,57 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-finance-is-main-true', + templateUrl: './finance-is-main-true.component.html', + styleUrls: ['./finance-is-main-true.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FinanceIsMainTrueComponent extends BaseList implements OnInit, OnChanges { + @Input() dataTrue: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + @Output() info = new EventEmitter(); + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'academic_semester_code', + 'academic_year_code', + '12', + 'count_subject', + 'is_open', + 'created_by', + 'created_datetime', + '8' + ]; + reload: boolean; + + constructor() { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(){ + this.dataTrue = this.updateMatTable(this.dataTrue ? this.dataTrue : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onInfo(id){ + this.info.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.html b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.html new file mode 100644 index 0000000..ad78810 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.html @@ -0,0 +1,21 @@ +

ค้นหา

+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
diff --git a/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.scss b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.spec.ts b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.spec.ts new file mode 100644 index 0000000..1287b89 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExamFinanceSearchComponent } from './exam-finance-search.component'; + +describe('ExamFinanceSearchComponent', () => { + let component: ExamFinanceSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ExamFinanceSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ExamFinanceSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.ts b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.ts new file mode 100644 index 0000000..f563593 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/presenter/search/exam-finance-search/exam-finance-search.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'exam-finance-search', + templateUrl: './exam-finance-search.component.html', + styleUrls: ['./exam-finance-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceSearchComponent implements OnInit { + + @Output() add = new EventEmitter() + @Output() search = new EventEmitter() + query = { + testing_information_name:null, + academic_semester_code:null, + academic_year_code :null, + is_main: null + } + constructor() { } + + ngOnInit(): void { + } + + onSearch(){ + + this.search.emit(this.query) + } + + clear(){ + this.query = { + testing_information_name:null, + academic_semester_code:null, + academic_year_code :null, + is_main:null + } + this.search.emit(this.query) + } + +} diff --git a/src/app/feature/settings-finance/exam-finance/router/exam-finance-router.ts b/src/app/feature/settings-finance/exam-finance/router/exam-finance-router.ts new file mode 100644 index 0000000..38b3d49 --- /dev/null +++ b/src/app/feature/settings-finance/exam-finance/router/exam-finance-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-exam-finance-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ExamFinanceRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.html b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.html new file mode 100644 index 0000000..b779c74 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.html @@ -0,0 +1,10 @@ + + + + + diff --git a/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.scss b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.spec.ts b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.spec.ts new file mode 100644 index 0000000..a92b1fa --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InvigilateFinanceContainer } from './invigilate-finance.container'; + +describe('InvigilateFinanceContainer', () => { + let component: InvigilateFinanceContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InvigilateFinanceContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InvigilateFinanceContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.ts b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.ts new file mode 100644 index 0000000..20c4cf3 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/container/invigilate-finance/invigilate-finance.container.ts @@ -0,0 +1,56 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { catchError, filter, switchMap, tap } from 'rxjs/operators'; +import { invigilatorCostService } from 'src/app/core/service/settingPayment/invigilator-cost.service'; +import { AcademicSemesterService } from 'src/app/core/service/settings/academic-semester.service'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-invigilate-finance', + templateUrl: './invigilate-finance.container.html', + styleUrls: ['./invigilate-finance.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceContainer implements OnInit { + invigilateList$ = new Observable() + acdmSem$ = new Observable() + acdmYear$ = new Observable() + constructor( + private router: Router, + private invCostSV: invigilatorCostService, + private acdmSemSV: AcademicSemesterService, + private acdmYearSV: AcademicYearService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.invigilateList$ = this.invCostSV.getAll() + this.acdmSem$ = this.acdmSemSV.getAll() + this.acdmYear$ = this.acdmYearSV.getAll() + } + + edit(id){ + this.router.navigate(['/setting-invigilate-finance/edit',id]) + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.invCostSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.invigilateList$ = this.invCostSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/invigilate-finance.module.ts b/src/app/feature/settings-finance/invigilate-finance/invigilate-finance.module.ts new file mode 100644 index 0000000..8c87444 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/invigilate-finance.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { InvigilateFinanceContainer } from './container/invigilate-finance/invigilate-finance.container'; +import { InvigilateFinanceRouter } from './router/invigilate-finance-router'; +import { InvigilateFinanceSearchComponent } from './presenter/search/invigilate-finance-search/invigilate-finance-search.component'; +import { InvigilateFinanceListComponent } from './presenter/list/invigilate-finance-list/invigilate-finance-list.component'; +import { InvigilateFinanceFormComponent } from './presenter/form/invigilate-finance-form/invigilate-finance-form.component'; +import { InvigilateFinanceFormArrayComponent } from './presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component'; + +const routes : Routes =[ + { + path:'', + component: InvigilateFinanceRouter, + children:[ + { + path:'', + component: InvigilateFinanceContainer + }, + { + path:'edit/:id', + component: InvigilateFinanceFormComponent + }, + { + path:'add', + component: InvigilateFinanceFormComponent + }, + ] + } +] + +@NgModule({ + declarations: [ + InvigilateFinanceContainer, + InvigilateFinanceRouter, + InvigilateFinanceSearchComponent, + InvigilateFinanceListComponent, + InvigilateFinanceFormComponent, + InvigilateFinanceFormArrayComponent +], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class InvigilateFinanceModule { } diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.html b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.html new file mode 100644 index 0000000..6553875 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.html @@ -0,0 +1,48 @@ +
+
+
+
+
+ + + + + {{x.login_name}} + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+  {{x.value.invigilator_date | thaidate}}  + +
+
+
+
+ +
+ +
+
+
+
diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.scss b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.spec.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.spec.ts new file mode 100644 index 0000000..adfe157 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InvigilateFinanceFormArrayComponent } from './invigilate-finance-form-array.component'; + +describe('InvigilateFinanceFormArrayComponent', () => { + let component: InvigilateFinanceFormArrayComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InvigilateFinanceFormArrayComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InvigilateFinanceFormArrayComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.ts new file mode 100644 index 0000000..a6476c8 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/array-form/invigilate-finance-form-array/invigilate-finance-form-array.component.ts @@ -0,0 +1,40 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; +import { FormGroup } from '@angular/forms'; +import { tap } from 'rxjs/operators'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; + +@Component({ + selector: 'invigilate-finance-form-array', + templateUrl: './invigilate-finance-form-array.component.html', + styleUrls: ['./invigilate-finance-form-array.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceFormArrayComponent implements OnInit { + @Input() form: FormGroup + @Output() remove = new EventEmitter() + @Input() user: any = []; + constructor( + + ) { } + + ngOnInit(): void { + + } + + setDisplayName(x){ + this.form.get('invigilator_name').setValue(x.display_name) + this.form.get('invigilator_uid').setValue(x.user_uid) + } + + onRemove(){ + this.remove.emit() + } + + calculateTotal(){ + const otherCost = parseInt(this.form.get('other_cost').value == null? 0: this.form.get('other_cost').value) + const amount = parseInt(this.form.get('amount').value == null? 0: this.form.get('amount').value) + const sum = (otherCost+amount).toString() + this.form.get('total_amount').setValue(sum) + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.html b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.html new file mode 100644 index 0000000..b375240 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.html @@ -0,0 +1,112 @@ +
+

สร้างข้อมูลค่าคุมสอบ

+
+
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ + + + + + +
+ +
+ + + + + + +
+
+
+ + + + + +
+ + +
+
+ + + + + + +
+ +
+
+
+
+ +
+
+ + + +
+
+ + +
{{form.getRawValue() | json}}
diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.scss b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.scss new file mode 100644 index 0000000..bbdba06 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.scss @@ -0,0 +1,58 @@ +:host ::ng-deep .mat-ink-bar { + display: none !important; +} + +.tab{ + background: #C4C4C4; + border-radius: 6px 6px 0px 0px; + // width: 150px; + // max-width: 160px; + height: 40px; + margin-top: 10px; + margin-left: -5px; + display: flex; + pointer-events: all; +} + +.addtab{ + background: #576071; + border-radius: 6px 6px 0px 0px; + width: 40px; + height: 40px; + margin-top: 10px; + margin-left: -10px; + color:white; + pointer-events: all; + display: flex; + align-items: center; + justify-content: center; +} + +:host ::ng-deep .mat-tab-label { + height: 48px; + padding: 0 5px !important ; + opacity: 1; + min-width: 150px; + pointer-events: none !important; +} + +:host ::ng-deep .mat-tab-label-active .tab { + color: white; + background: #2D9CDB; +} + +.edit{ + @apply z-10 pr-1 text-center flex items-center justify-center; +} + +.inputname{ + @apply bg-transparent border-none focus:ring-opacity-0 cursor-pointer text-white; +} + +:host ::ng-deep .mat-tab-label:focus { + background-color: transparent !important; +} + +:host ::ng-deep .mat-tab-body-content{ + @apply bg-gray-200; +} diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.spec.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.spec.ts new file mode 100644 index 0000000..3e46335 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InvigilateFinanceFormComponent } from './invigilate-finance-form.component'; + +describe('InvigilateFinanceFormComponent', () => { + let component: InvigilateFinanceFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InvigilateFinanceFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InvigilateFinanceFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.ts new file mode 100644 index 0000000..2b22ddc --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/form/invigilate-finance-form/invigilate-finance-form.component.ts @@ -0,0 +1,287 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { BaseForm, sortByProperty } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { UserOpenidService } from 'src/app/core/service/openid/user.service'; +import { ReportInvigilatorCostService } from 'src/app/core/service/report/invigilator-cost/report-invigilator-cost.service'; +import { invigilatorCostService } from 'src/app/core/service/settingPayment/invigilator-cost.service'; +import { AcademicSemesterService } from 'src/app/core/service/settings/academic-semester.service'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-invigilate-finance-form', + templateUrl: './invigilate-finance-form.component.html', + styleUrls: ['./invigilate-finance-form.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceFormComponent extends BaseFormUid implements OnInit { + editName = true; + formArray; + academicSem$ = new Observable(); + academicYear$ = new Observable(); + branch$ = new Observable(); + testingInformationList$ = new Observable() + user; + constructor( + public fb: FormBuilder, + public router: Router, + public location: Location, + public activeroute: ActivatedRoute, + private academicSemSV: AcademicSemesterService, + private academicYearSV: AcademicYearService, + private invigilatorCostSV: invigilatorCostService, + private branchSV: BranchService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private userOpenidSV: UserOpenidService, + private reportInvigilatorCostSV: ReportInvigilatorCostService, + private testingInformationSV: TestingInformationService + ) { + super(router,activeroute,fb,location) + } + + ngOnInit(): void { + this.academicSem$ = this.academicSemSV.getAll() + this.academicYear$ = this.academicYearSV.getAll() + this.testingInformationList$ = this.testingInformationSV.getAll() + this.userOpenidSV.getAll().pipe(tap(x => this.user = x)).subscribe() + this.branch$ = this.branchSV.getAll() + if(this.state == 'edit'){ + this.invigilatorCostSV.get(this.id).pipe( + tap(x => this.setupForm(x)), + ).subscribe() + } + } + + createForm(){ + const index = 0 + return this.fb.group({ + academic_semester_uid: [null,Validators.required], + academic_year_uid: [null,Validators.required], + status_id: null, + created_by: null, + created_datetime: new Date(), + updated_by: null, + updated_datetime: new Date(), + deleted_by: null, + deleted_datetime: null, + invigilator_cost_uid: null, + testing_information_uid : [null,Validators.required], + branch_uid: [null,Validators.required], + from_date: [null,Validators.required], + to_date: [null,Validators.required], + invigilator_cost_groups: this.fb.array([ + this.createArray(index) + ]) + }) + } + + setupForm(x){ + this.form.patchValue(x) + this.form.setControl('invigilator_cost_groups',this.fb.array(x.invigilator_cost_groups.map(x => this.createCostGroup(x)))) + this.cdr.detectChanges() + } + + getDateBetween(startDate:Date,endDate: Date,includeEndDate?: boolean){ + const dates = []; + const currentDate = new Date(startDate); + const end = new Date(endDate); + while (currentDate < end) { + dates.push(new Date(currentDate)); + currentDate.setDate(currentDate.getDate() + 1); + } + if (includeEndDate) dates.push(end); + return dates; + } + + addDate(){ + // const getDatesBetween = ( + // startDate: Date, + // endDate: Date, + // includeEndDate?: boolean, + // ) => { + // const dates = []; + // const currentDate = new Date(startDate); + // const end = new Date(endDate); + // while (currentDate < end) { + // dates.push(new Date(currentDate)); + // currentDate.setDate(currentDate.getDate() + 1); + // } + // if (includeEndDate) dates.push(end); + // return dates; + // }; + if(this.form.get('from_date').value && this.form.get('to_date').value){ + let date_array = this.getDateBetween(this.form.get('from_date').value,this.form.get('to_date').value,true) + const form = this.form.get('invigilator_cost_groups') as FormArray + form.controls.map((x:any) => { + x.controls.invigilator_cost_details.controls.map((cost: any) => { + cost.setControl('invigilator_cost_date_details',this.fb.array(date_array.map((date,index) => this.createCostDateDetails(date,index)))) + this.cdr.detectChanges() + }) + }) + } + } + + addTab(){ + const form = this.form.get('invigilator_cost_groups') as FormArray + const index = form.length + form.push(this.createArray(index)) + } + + removeTab(i){ + const form = this.form.get('invigilator_cost_groups') as FormArray + form.removeAt(i) + } + + createArray(index){ + return this.fb.group({ + invigilator_group_name: 'PAGE '+ (index+1), + status_id: null, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + invigilator_cost_group_uid: null, + invigilator_cost_uid: null, + invigilator_cost_details: this.fb.array([ + this.createsub() + ]) + }) + } + + createCostDateDetails(data?,index?){ + return this.fb.group({ + invigilator_cost_date_detail_uid: null, + invigilator_cost_detail_uid: null, + row: index+1, + invigilator_date: data, + is_check: false + }) + } + + updateCostDateDetails(x){ + return this.fb.group({ + invigilator_cost_date_detail_uid: x.invigilator_cost_date_detail_uid, + invigilator_cost_detail_uid: x.invigilator_cost_detail_uid, + row: x.row, + invigilator_date: x.invigilator_date, + is_check: x.is_check + }) + } + + createsub(){ + return this.fb.group({ + invigilator_cost_detail_uid: null, + invigilator_cost_group_uid: null, + invigilator_code: [null], + invigilator_uid: [null], + invigilator_name: [null,Validators.required], + amount: [null,Validators.required], + total_amount: [null], + other_cost: [null,Validators.required], + invigilator_cost_date_details: this.fb.array([]) + }) + } + + addCostDetail(x){ + return this.fb.group({ + invigilator_cost_detail_uid: null, + invigilator_cost_group_uid: null, + invigilator_code: [null], + invigilator_uid: [null], + invigilator_name: [null,Validators.required], + amount: [null,Validators.required], + total_amount: [null], + other_cost: [null,Validators.required], + invigilator_cost_date_details: this.fb.array(x.map((a,index) => this.createCostDateDetails(a,index))) + }) + } + + createCostDetail(x){ + return this.fb.group({ + invigilator_cost_detail_uid: x.invigilator_cost_detail_uid, + invigilator_cost_group_uid: x.invigilator_cost_group_uid, + invigilator_code: x.invigilator_code, + invigilator_uid: x.invigilator_uid, + invigilator_name: x.invigilator_name, + amount: x.amount, + total_amount: [x.total_amount], + other_cost: [x.other_cost], + invigilator_cost_date_details: this.fb.array(x.invigilator_cost_date_details.sort(sortByProperty('row')).map(a => this.updateCostDateDetails(a))) + }) + } + + createCostGroup(x){ + return this.fb.group({ + invigilator_group_name: x.invigilator_group_name, + status_id: x.status_id, + created_by: x.created_by, + created_datetime: x.e, + updated_by: x.updated_by, + updated_datetime: x.updated_datetime, + deleted_by: x.deleted_by, + deleted_datetime: x.deleted_datetime, + invigilator_cost_group_uid: x.invigilator_cost_group_uid, + invigilator_cost_uid: x.invigilator_cost_uid, + invigilator_cost_details: this.fb.array(x.invigilator_cost_details.map(a => this.createCostDetail(a))) + }) + } + + add(form,index){ + index = 1 + const arr = form.get('invigilator_cost_details') as FormArray + let date_array = this.getDateBetween(this.form.get('from_date').value,this.form.get('to_date').value,true) + arr.push(this.addCostDetail(date_array)) + } + + removeNameArr(index,x){ + const form = x.get('invigilator_cost_details') as FormArray + form.removeAt(index) + } + + export(){ + const form = this.form.getRawValue() + window.open(this.reportInvigilatorCostSV.report(form.invigilator_cost_uid)) + } + + save(){ + const form = this.form.getRawValue() + switch (this.state) { + case 'edit': + this.invigilatorCostSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + break; + + case 'add': + this.invigilatorCostSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + break; + } + } + + cancel(){ + this.location.back() + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.html b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.html new file mode 100644 index 0000000..a57458f --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.html @@ -0,0 +1,58 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ภาคเรียน {{x.academic_semester_uid | getDataId : acdmSem:'academic_semester_uid' : 'academic_semester_name_th':''}} ปีการศึกษา {{x.academic_year_uid | getDataId : acdmYear:'academic_year_uid' : 'academic_year_name_th':''}} วันที่คุมสอบ {{x.from_date | thaidate}} - {{x.to_date | thaidate}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + +
+
+ +
+
+
diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.scss b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.spec.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.spec.ts new file mode 100644 index 0000000..afbab98 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InvigilateFinanceListComponent } from './invigilate-finance-list.component'; + +describe('InvigilateFinanceListComponent', () => { + let component: InvigilateFinanceListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InvigilateFinanceListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InvigilateFinanceListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.ts new file mode 100644 index 0000000..57e4570 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/list/invigilate-finance-list/invigilate-finance-list.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'invigilate-finance-list', + templateUrl: './invigilate-finance-list.component.html', + styleUrls: ['./invigilate-finance-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceListComponent extends BaseList implements OnInit,OnChanges { + @Input() invigilateList: any = []; + @Input() acdmSem: any = []; + @Input() acdmYear: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + column = ['8','1','2','3','4','6','7'] + constructor() { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + // console.log(this.invigilateList) + if(this.invigilateList) this.invigilateList = this.invigilateList.data? this.invigilateList : this.updateMatTable(this.invigilateList) + // this.invigilateList = this.updateMatTable(this.invigilateList? this.invigilateList: []) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(uid){ + this.delete.emit(uid) + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.html b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.html new file mode 100644 index 0000000..42c73ce --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.html @@ -0,0 +1,37 @@ +

ค้นหา

+ +
+
+
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.scss b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.scss new file mode 100644 index 0000000..aa5e791 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.scss @@ -0,0 +1,34 @@ +:host ::ng-deep .mat-ink-bar { + display: none !important; +} + +.tab{ + background: #C4C4C4; + border: 0.5px solid rgba(0, 0, 0, 0.16); + border-radius: 6px 6px 0px 0px; + width: 150px; + height: 40px; + margin-top: 10px; + margin-left: -5px; + place-content: center; + align-items: center; + border: none; + line-height: 20px; + display: flex; + text-align: center; + letter-spacing: 0.5px; + } + +:host ::ng-deep .mat-tab-label { + height: 48px; + padding: 0 5px !important ; + opacity: 1; + min-width: 150px; +} + +:host ::ng-deep .mat-tab-label-active .tab { + color: white; + background: #2D9CDB; + opacity: 1 !important; +} + diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.spec.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.spec.ts new file mode 100644 index 0000000..0d444cd --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InvigilateFinanceSearchComponent } from './invigilate-finance-search.component'; + +describe('InvigilateFinanceSearchComponent', () => { + let component: InvigilateFinanceSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ InvigilateFinanceSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(InvigilateFinanceSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.ts b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.ts new file mode 100644 index 0000000..f2f876f --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/presenter/search/invigilate-finance-search/invigilate-finance-search.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'invigilate-finance-search', + templateUrl: './invigilate-finance-search.component.html', + styleUrls: ['./invigilate-finance-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceSearchComponent implements OnInit { + query = { + calendar_type_name_th: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + get(event){ + + } + + onSearch(){ + + } + + onAdd(){ + this.router.navigate(['setting-invigilate-finance/add']) + } + + clear(){ + this.query = { + calendar_type_name_th: null + } + } + +} diff --git a/src/app/feature/settings-finance/invigilate-finance/router/invigilate-finance-router.ts b/src/app/feature/settings-finance/invigilate-finance/router/invigilate-finance-router.ts new file mode 100644 index 0000000..e07aa72 --- /dev/null +++ b/src/app/feature/settings-finance/invigilate-finance/router/invigilate-finance-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-invigilate-finance-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InvigilateFinanceRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings-finance/routes.ts b/src/app/feature/settings-finance/routes.ts new file mode 100644 index 0000000..e43dd1d --- /dev/null +++ b/src/app/feature/settings-finance/routes.ts @@ -0,0 +1,28 @@ +import { Routes } from "@angular/router"; +export const settingFinanceRoutes: Routes = [ + { + path: "setting-invigilate-finance", + loadChildren: () => import("./invigilate-finance/invigilate-finance.module").then((m) => m.InvigilateFinanceModule), + data: { + menu: "กำหนดค่าใช้จ่าย", + sub_menu: "ค่าคุมสอบ", + }, + }, + { + path: "setting-teacher-finance", + loadChildren: () =>import("./teacher-finance/teacher-finance.module").then((m) => m.TeacherFinanceModule), + data: { + menu: "กำหนดค่าใช้จ่าย", + sub_menu: "บันทึกบัญชีค่าตอบแทนอาจารย์", + }, + }, + { + path: "setting-exam-finance", + loadChildren: () =>import("./exam-finance/exam-finance.module").then((m) => m.ExamFinanceModule), + data: { + menu: "กำหนดค่าใช้จ่าย", + sub_menu: "กำหนดค่าสอบ", + }, + }, +]; +export default settingFinanceRoutes; diff --git a/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.html b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.html new file mode 100644 index 0000000..cc4ab69 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.html @@ -0,0 +1,10 @@ + + diff --git a/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.scss b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.spec.ts b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.spec.ts new file mode 100644 index 0000000..62850c5 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeacherFinanceContainer } from './teacher-finance.container'; + +describe('TeacherFinanceContainer', () => { + let component: TeacherFinanceContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TeacherFinanceContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TeacherFinanceContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.ts b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.ts new file mode 100644 index 0000000..c2bae32 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/container/teacher-finance/teacher-finance.container.ts @@ -0,0 +1,61 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { catchError, filter, switchMap, tap } from 'rxjs/operators'; +import { InsturctorPaymentAccoutService } from 'src/app/core/service/settingPayment/insturctor-payment-accout.service'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-teacher-finance', + templateUrl: './teacher-finance.container.html', + styleUrls: ['./teacher-finance.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherFinanceContainer implements OnInit { + teacherList$ = new Observable() + faculty$ = new Observable() + constructor( + private router: Router, + private instructorPaymentSV: InsturctorPaymentAccoutService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private facultySV: FacultysService + ) { } + + ngOnInit(): void { + this.teacherList$ = this.instructorPaymentSV.getAll() + this.faculty$ = this.facultySV.getAll() + } + + add(){ + this.router.navigate(['setting-teacher-finance/add']) + } + + edit(id){ + this.router.navigate(['setting-teacher-finance/edit',id]) + } + + search(query){ + if(query) return this.teacherList$ = this.instructorPaymentSV.search(`?${query}`) + if(!query) return this.teacherList$ = this.instructorPaymentSV.getAll() + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.instructorPaymentSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.teacherList$ = this.instructorPaymentSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + +} diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.html b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.html new file mode 100644 index 0000000..01076c0 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.html @@ -0,0 +1,73 @@ +
+

บันทึกบัญชีค่าตอบแทนอาจารย์

+
+ + +
+ +
+ +
+ +
+
+ + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.faculty_name_th}} + + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+ +
+
+ +
+ + +
+ +
+ + +
+
+
+
+
+
+ +
+
+ +
+ + +
+ +
+ diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.scss b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.spec.ts b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.spec.ts new file mode 100644 index 0000000..661f036 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeacherFinanceFormComponent } from './teacher-finance-form.component'; + +describe('TeacherFinanceFormComponent', () => { + let component: TeacherFinanceFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TeacherFinanceFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TeacherFinanceFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.ts b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.ts new file mode 100644 index 0000000..005bb1f --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/form/teacher-finance-form/teacher-finance-form.component.ts @@ -0,0 +1,130 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import {FormArray, FormBuilder, Validators} from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { InsturctorPaymentAccoutService } from 'src/app/core/service/settingPayment/insturctor-payment-accout.service'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-teacher-finance-form', + templateUrl: './teacher-finance-form.component.html', + styleUrls: ['./teacher-finance-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherFinanceFormComponent extends BaseFormUid implements OnInit { + public getArray(){ + let x = this.form.get('array') as FormArray + return x.at(0) + } + facultyList: any = []; + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private insturctorPaymentSV: InsturctorPaymentAccoutService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private facultySV: FacultysService + ) { + super( + router, + activeRoute, + fb, + location + ) + } + + ngOnInit(): void { + this.facultySV.getAll().pipe( + tap(x => this.facultyList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + const data = this.form.get('array') as FormArray + switch (this.state) { + case 'add': + data.push(this.createArray()) + break; + + case 'edit': + this.insturctorPaymentSV.get(this.id).pipe( + tap(x => data.push(this.createArray(x))), + tap(x => this.cdr.detectChanges()) + ).subscribe() + break; + } + } + + createForm(){ + return this.fb.group({ + array: this.fb.array([ + // this.createArray() + ]) + }) + } + + createArray(x?){ + return this.fb.group({ + status_id: x?.status_id, + create_by: x?.create_by, + create_datetime: x?.create_datetime, + updated_by: x?.updated_by, + updated_datetime: x?.updated_datetime, + deleted_by: x?.deleted_by, + deleted_datetime: x?.deleted_datetime, + instructor_payment_account_uid: x?.instructor_payment_account_uid, + instructor_code: x?.instructor_code, + instructor_name: x?.instructor_name, + faculty_code: x?.faculty_code, + faculty_name: x?.faculty_name, + account_no: x?.account_no, + email: [x?.email , Validators.pattern('^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$')], + phone_no: x?.phone_no, + remark: x?.remark + }) + } + + save(){ + const data = this.form.get('array') as FormArray + const form = data.getRawValue() + switch (this.state) { + case 'edit': + let form2 = this.getArray() + let data = form2.value + this.insturctorPaymentSV.update2(data).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + break; + + case 'add': + this.insturctorPaymentSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + break; + } + } + + cancel(){ + this.back() + } + + add(){ + const form = this.form.get('array') as FormArray + form.push(this.createArray()) + } +} diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.html b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.html new file mode 100644 index 0000000..a7dbcec --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.html @@ -0,0 +1,53 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} ชื่อ นามสกุล {{x.instructor_name}} คณะ {{x.faculty_name}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +   + +
+
+ +
+
+
diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.scss b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.spec.ts b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.spec.ts new file mode 100644 index 0000000..8d51367 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeacherFinanceListComponent } from './teacher-finance-list.component'; + +describe('TeacherFinanceListComponent', () => { + let component: TeacherFinanceListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TeacherFinanceListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TeacherFinanceListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.ts b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.ts new file mode 100644 index 0000000..c81ea5d --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/list/teacher-finance-list/teacher-finance-list.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'teacher-finance-list', + templateUrl: './teacher-finance-list.component.html', + styleUrls: ['./teacher-finance-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherFinanceListComponent extends BaseList implements OnInit,OnChanges { + @Input() teacherList: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + column = ['1','2','3','4','5','7'] + constructor() { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.teacherList = this.updateMatTable(this.teacherList? this.teacherList: []) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(uid){ + this.delete.emit(uid) + } + +} diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.html b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.html new file mode 100644 index 0000000..eb5055c --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.html @@ -0,0 +1,30 @@ +

ค้นหา

+
+
+
+
+ + +
+ +
+ + + + + --กรุณาเลือก-- + + + {{x.faculty_name_th}} + + +
+
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.scss b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.spec.ts b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.spec.ts new file mode 100644 index 0000000..d56f319 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeacherFinanceSearchComponent } from './teacher-finance-search.component'; + +describe('TeacherFinanceSearchComponent', () => { + let component: TeacherFinanceSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TeacherFinanceSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TeacherFinanceSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.ts b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.ts new file mode 100644 index 0000000..427fbcc --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/presenter/search/teacher-finance-search/teacher-finance-search.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, Input } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'teacher-finance-search', + templateUrl: './teacher-finance-search.component.html', + styleUrls: ['./teacher-finance-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherFinanceSearchComponent implements OnInit { + @Output() add = new EventEmitter() + @Output() search = new EventEmitter() + @Input() facultyList: any = []; + query = { + instructor_name: null, + faculty_name: null + } + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit() + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + instructor_name: null, + faculty_name: null + } + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + +} diff --git a/src/app/feature/settings-finance/teacher-finance/router/teacher-finance-router.ts b/src/app/feature/settings-finance/teacher-finance/router/teacher-finance-router.ts new file mode 100644 index 0000000..d5952fc --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/router/teacher-finance-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-teacher-finance-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TeacherFinanceRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings-finance/teacher-finance/teacher-finance.module.ts b/src/app/feature/settings-finance/teacher-finance/teacher-finance.module.ts new file mode 100644 index 0000000..4f34b43 --- /dev/null +++ b/src/app/feature/settings-finance/teacher-finance/teacher-finance.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { TeacherFinanceContainer } from './container/teacher-finance/teacher-finance.container'; +import { TeacherFinanceRouter } from './router/teacher-finance-router'; +import { TeacherFinanceSearchComponent } from './presenter/search/teacher-finance-search/teacher-finance-search.component'; +import { TeacherFinanceListComponent } from './presenter/list/teacher-finance-list/teacher-finance-list.component'; +import { TeacherFinanceFormComponent } from './presenter/form/teacher-finance-form/teacher-finance-form.component'; + +const routes : Routes =[ + { + path:'', + component: TeacherFinanceRouter, + children:[ + { + path:'', + component: TeacherFinanceContainer + }, + { + path:'add', + component: TeacherFinanceFormComponent + }, + { + path:'edit/:id', + component: TeacherFinanceFormComponent + }, + ] + } +] + +@NgModule({ + declarations: [ + TeacherFinanceRouter, + TeacherFinanceContainer, + TeacherFinanceSearchComponent, + TeacherFinanceListComponent, + TeacherFinanceFormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class TeacherFinanceModule { } diff --git a/src/app/feature/settings/academic-semesters/academic-semesters.module.ts b/src/app/feature/settings/academic-semesters/academic-semesters.module.ts new file mode 100644 index 0000000..7cc844d --- /dev/null +++ b/src/app/feature/settings/academic-semesters/academic-semesters.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { AcademicSemestersRouter } from './router/academic-semesters-router'; +import { AcademicSemestersContainer } from './container/academic-semesters/academic-semesters.container'; +import { AcademicSemestersSearchComponent } from './presenter/search/academic-semesters-search/academic-semesters-search.component'; +import { AcademicSemestersListComponent } from './presenter/list/academic-semesters-list/academic-semesters-list.component'; +import { AcademicSemestersDialogComponent } from './presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component'; + +const routes : Routes =[ + { + path:'', + component: AcademicSemestersRouter, + children:[ + { + path:'', + component: AcademicSemestersContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + AcademicSemestersContainer, + AcademicSemestersRouter, + AcademicSemestersSearchComponent, + AcademicSemestersListComponent, + AcademicSemestersDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class AcademicSemestersModule { } diff --git a/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.html b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.html new file mode 100644 index 0000000..7e36313 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.scss b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.spec.ts b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.spec.ts new file mode 100644 index 0000000..ef19adf --- /dev/null +++ b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicSemestersContainer } from './academic-semesters.container'; + +describe('AcademicSemestersContainer', () => { + let component: AcademicSemestersContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicSemestersContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicSemestersContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.ts b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.ts new file mode 100644 index 0000000..b120e8d --- /dev/null +++ b/src/app/feature/settings/academic-semesters/container/academic-semesters/academic-semesters.container.ts @@ -0,0 +1,69 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable } from 'rxjs'; +import { tap, filter, concatMap } from 'rxjs/operators'; +import { AcademicSemesterService } from 'src/app/core/service/settings/academic-semester.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { AcademicSemestersDialogComponent } from '../../presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component'; + +@Component({ + selector: 'app-academic-semesters', + templateUrl: './academic-semesters.container.html', + styleUrls: ['./academic-semesters.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicSemestersContainer implements OnInit { + acdmSem$ = new Observable() + constructor( + private acdmSemSV: AcademicSemesterService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.acdmSem$ = this.acdmSemSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(AcademicSemestersDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.acdmSem$ = this.acdmSemSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + edit(id){ + const dialogRef = this.dialog.open(AcademicSemestersDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.acdmSem$ = this.acdmSemSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.acdmSemSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.acdmSem$ = this.acdmSemSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.acdmSem$ = this.acdmSemSV.search(`?${query}`) + if(!query) return this.acdmSem$ = this.acdmSemSV.getAll() + } + +} diff --git a/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.html b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.html new file mode 100644 index 0000000..06e837a --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.html @@ -0,0 +1,24 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.scss b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.spec.ts b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.spec.ts new file mode 100644 index 0000000..fd93c11 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicSemestersDialogComponent } from './academic-semesters-dialog.component'; + +describe('AcademicSemestersDialogComponent', () => { + let component: AcademicSemestersDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicSemestersDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicSemestersDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.ts b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.ts new file mode 100644 index 0000000..d1a0865 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/dialog/academic-semesters-dialog/academic-semesters-dialog.component.ts @@ -0,0 +1,80 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { AcademicSemesterService } from 'src/app/core/service/settings/academic-semester.service'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-academic-semesters-dialog', + templateUrl: './academic-semesters-dialog.component.html', + styleUrls: ['./academic-semesters-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicSemestersDialogComponent implements OnInit { + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + constructor( + private fb: FormBuilder, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + private acdmSemSV: AcademicSemesterService, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + academic_semester_uid: null, + academic_semester_code: null, + academic_semester_name_th: null, + academic_semester_name_en: null + }) + } + + ngOnInit(): void { + if(this.data){ + this.acdmSemSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe() + } + } + + save(){ + const form = this.form.getRawValue() + form.academic_semester_name_th = form.academic_semester_code + form.academic_semester_name_en = form.academic_semester_code + if(this.data){ + this.acdmSemSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } else { + this.acdmSemSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.dialogRef.close() + } + +} diff --git a/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.html b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.html new file mode 100644 index 0000000..9e4be79 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ภาคการศึกษา {{x.academic_semester_code}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.scss b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.spec.ts b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.spec.ts new file mode 100644 index 0000000..954d8bc --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicSemestersListComponent } from './academic-semesters-list.component'; + +describe('AcademicSemestersListComponent', () => { + let component: AcademicSemestersListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicSemestersListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicSemestersListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.ts b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.ts new file mode 100644 index 0000000..efa3949 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/list/academic-semesters-list/academic-semesters-list.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, EventEmitter, OnChanges, Output } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'academic-semesters-list', + templateUrl: './academic-semesters-list.component.html', + styleUrls: ['./academic-semesters-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicSemestersListComponent extends BaseList implements OnInit,OnChanges { + column = ['1', '2', '3', '4', '5', '6']; + + @Input() academicSemestersList: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + constructor() { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.academicSemestersList = this.updateMatTable(this.academicSemestersList? this.academicSemestersList:[]) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.html b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.html new file mode 100644 index 0000000..7e66f46 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.scss b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.spec.ts b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.spec.ts new file mode 100644 index 0000000..3f542dc --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicSemestersSearchComponent } from './academic-semesters-search.component'; + +describe('AcademicSemestersSearchComponent', () => { + let component: AcademicSemestersSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicSemestersSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicSemestersSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.ts b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.ts new file mode 100644 index 0000000..5bfdb97 --- /dev/null +++ b/src/app/feature/settings/academic-semesters/presenter/search/academic-semesters-search/academic-semesters-search.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'academic-semesters-search', + templateUrl: './academic-semesters-search.component.html', + styleUrls: ['./academic-semesters-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicSemestersSearchComponent implements OnInit { + query = { + academic_semester_code: null + } + @Output() search = new EventEmitter() + @Output() add = new EventEmitter() + constructor() { + + } + + ngOnInit(): void { + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + academic_semester_code: null + } + } + + onAdd(){ + this.add.emit() + } + +} diff --git a/src/app/feature/settings/academic-semesters/router/academic-semesters-router.ts b/src/app/feature/settings/academic-semesters/router/academic-semesters-router.ts new file mode 100644 index 0000000..0d16dca --- /dev/null +++ b/src/app/feature/settings/academic-semesters/router/academic-semesters-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-academic-years-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicSemestersRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/academic-years/academic-years.module.ts b/src/app/feature/settings/academic-years/academic-years.module.ts new file mode 100644 index 0000000..5337a2e --- /dev/null +++ b/src/app/feature/settings/academic-years/academic-years.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { AcademicYearsContainer } from './container/academic-years/academic-years.container'; +import { AcademicYearsRouter } from './router/academic-years-router'; +import { AcademicYearsListComponent } from './presenter/list/academic-years-list/academic-years-list.component'; +import { AcademicYearsSearchComponent } from './presenter/search/academic-years-search/academic-years-search.component'; +import { AcademicYearsDialogComponent } from './presenter/dialog/academic-years-dialog/academic-years-dialog.component'; + +const routes : Routes =[ + { + path:'', + component: AcademicYearsRouter, + children:[ + { + path:'', + component: AcademicYearsContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + AcademicYearsContainer, + AcademicYearsRouter, + AcademicYearsListComponent, + AcademicYearsSearchComponent, + AcademicYearsDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class AcademicYearsModule { } diff --git a/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.html b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.html new file mode 100644 index 0000000..88a73b1 --- /dev/null +++ b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.scss b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.spec.ts b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.spec.ts new file mode 100644 index 0000000..1f926d6 --- /dev/null +++ b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicYearsContainer } from './academic-years.container'; + +describe('AcademicYearsContainer', () => { + let component: AcademicYearsContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicYearsContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicYearsContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.ts b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.ts new file mode 100644 index 0000000..90ab724 --- /dev/null +++ b/src/app/feature/settings/academic-years/container/academic-years/academic-years.container.ts @@ -0,0 +1,69 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable } from 'rxjs'; +import { tap, filter, concatMap } from 'rxjs/operators'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { AcademicYearsDialogComponent } from '../../presenter/dialog/academic-years-dialog/academic-years-dialog.component'; + +@Component({ + selector: 'app-academic-years', + templateUrl: './academic-years.container.html', + styleUrls: ['./academic-years.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicYearsContainer implements OnInit { + acdmYear$ = new Observable() + constructor( + private acdmYearSV: AcademicYearService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.acdmYear$ = this.acdmYearSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(AcademicYearsDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.acdmYear$ = this.acdmYearSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + edit(id){ + const dialogRef = this.dialog.open(AcademicYearsDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.acdmYear$ = this.acdmYearSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.acdmYearSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.acdmYear$ = this.acdmYearSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.acdmYear$ = this.acdmYearSV.search(`?${query}`) + if(!query) return this.acdmYear$ = this.acdmYearSV.getAll() + } + +} diff --git a/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.html b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.html new file mode 100644 index 0000000..1b9a90d --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.html @@ -0,0 +1,24 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.scss b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.spec.ts b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.spec.ts new file mode 100644 index 0000000..298bb3b --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicYearsDialogComponent } from './academic-years-dialog.component'; + +describe('AcademicYearsDialogComponent', () => { + let component: AcademicYearsDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicYearsDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicYearsDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.ts b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.ts new file mode 100644 index 0000000..95c7500 --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component.ts @@ -0,0 +1,78 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-academic-years-dialog', + templateUrl: './academic-years-dialog.component.html', + styleUrls: ['./academic-years-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicYearsDialogComponent implements OnInit { + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + constructor( + private fb: FormBuilder, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + private acdmYearSV: AcademicYearService, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + academic_year_uid: null, + academic_year_code: null, + academic_year_name_th: null, + academic_year_name_en: null + }) + } + + ngOnInit(): void { + if(this.data){ + this.acdmYearSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe() + } + } + + save(){ + const form = this.form.getRawValue() + form.academic_year_name_en = form.academic_year_code + form.academic_year_name_th = form.academic_year_code + if(this.data){ + this.acdmYearSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } else { + this.acdmYearSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.dialogRef.close() + } +} diff --git a/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.html b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.html new file mode 100644 index 0000000..b851af5 --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ปีการศึกษา {{x.academic_year_code}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.scss b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.spec.ts b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.spec.ts new file mode 100644 index 0000000..6851ade --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicYearsListComponent } from './academic-years-list.component'; + +describe('AcademicYearsListComponent', () => { + let component: AcademicYearsListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicYearsListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicYearsListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.ts b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.ts new file mode 100644 index 0000000..11e5976 --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/list/academic-years-list/academic-years-list.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'academic-years-list', + templateUrl: './academic-years-list.component.html', + styleUrls: ['./academic-years-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicYearsListComponent extends BaseList implements OnInit,OnChanges { + column = ['1', '2', '3', '4', '5', '6']; + @Input() academicYearList: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + constructor() { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.academicYearList = this.updateMatTable(this.academicYearList? this.academicYearList:[]) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.html b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.html new file mode 100644 index 0000000..917172d --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.scss b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.spec.ts b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.spec.ts new file mode 100644 index 0000000..bde5bb4 --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AcademicYearsSearchComponent } from './academic-years-search.component'; + +describe('AcademicYearsSearchComponent', () => { + let component: AcademicYearsSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AcademicYearsSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AcademicYearsSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.ts b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.ts new file mode 100644 index 0000000..eec70a0 --- /dev/null +++ b/src/app/feature/settings/academic-years/presenter/search/academic-years-search/academic-years-search.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'academic-years-search', + templateUrl: './academic-years-search.component.html', + styleUrls: ['./academic-years-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicYearsSearchComponent implements OnInit { + query = { + academic_year_code: null + } + @Output() search = new EventEmitter() + @Output() add = new EventEmitter() + constructor() { + + } + + ngOnInit(): void { + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + academic_year_code: null + } + } + + onAdd(){ + this.add.emit() + } + +} diff --git a/src/app/feature/settings/academic-years/router/academic-years-router.ts b/src/app/feature/settings/academic-years/router/academic-years-router.ts new file mode 100644 index 0000000..30f7c6a --- /dev/null +++ b/src/app/feature/settings/academic-years/router/academic-years-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-academic-years-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AcademicYearsRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/calendars/calendars.module.ts b/src/app/feature/settings/calendars/calendars.module.ts new file mode 100644 index 0000000..4fe4f43 --- /dev/null +++ b/src/app/feature/settings/calendars/calendars.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { CalendarsRouter } from './router/calendars-router'; +import { CalendarsContainer } from './container/calendars/calendars.container'; +import { CalendarSearchComponent } from './presenter/search/calendar-search/calendar-search.component'; +import { CalendarListComponent } from './presenter/list/calendar-list/calendar-list.component'; +import { CalendarDialogComponent } from './presenter/dialog/calendar-dialog/calendar-dialog.component'; + +const routes : Routes =[ + { + path:'', + component: CalendarsRouter, + children:[ + { + path:'', + component: CalendarsContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + CalendarsRouter, + CalendarsContainer, + CalendarSearchComponent, + CalendarListComponent, + CalendarDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class CalendarsModule { } diff --git a/src/app/feature/settings/calendars/container/calendars/calendars.container.html b/src/app/feature/settings/calendars/container/calendars/calendars.container.html new file mode 100644 index 0000000..2102213 --- /dev/null +++ b/src/app/feature/settings/calendars/container/calendars/calendars.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/calendars/container/calendars/calendars.container.scss b/src/app/feature/settings/calendars/container/calendars/calendars.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/calendars/container/calendars/calendars.container.spec.ts b/src/app/feature/settings/calendars/container/calendars/calendars.container.spec.ts new file mode 100644 index 0000000..5b61e4d --- /dev/null +++ b/src/app/feature/settings/calendars/container/calendars/calendars.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CalendarsContainer } from './calendars.container'; + +describe('CalendarsContainer', () => { + let component: CalendarsContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CalendarsContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CalendarsContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/calendars/container/calendars/calendars.container.ts b/src/app/feature/settings/calendars/container/calendars/calendars.container.ts new file mode 100644 index 0000000..d094838 --- /dev/null +++ b/src/app/feature/settings/calendars/container/calendars/calendars.container.ts @@ -0,0 +1,69 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable } from 'rxjs'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { CalendarTypeService } from 'src/app/core/service/settings/calendar-type.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { CalendarDialogComponent } from '../../presenter/dialog/calendar-dialog/calendar-dialog.component'; + +@Component({ + selector: 'app-calendars', + templateUrl: './calendars.container.html', + styleUrls: ['./calendars.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CalendarsContainer implements OnInit { + calendarList$ = new Observable() + constructor( + private dialog: MatDialog, + private calendarSV: CalendarTypeService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.calendarList$ = this.calendarSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(CalendarDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.calendarList$ = this.calendarSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + edit(id){ + const dialogRef = this.dialog.open(CalendarDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.calendarList$ = this.calendarSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.calendarSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.calendarList$ = this.calendarSV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.calendarList$ = this.calendarSV.search(`?${query}`) + if(!query) return this.calendarList$ = this.calendarSV.getAll() + } + +} diff --git a/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.html b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.html new file mode 100644 index 0000000..4290164 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.html @@ -0,0 +1,24 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.scss b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.scss new file mode 100644 index 0000000..9a02cf4 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.scss @@ -0,0 +1,3 @@ +// .mat-dialog-container { +// background-color: rgba(0, 0, 0, 0.25) !important; +// } diff --git a/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.spec.ts b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.spec.ts new file mode 100644 index 0000000..2689b5c --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CalendarDialogComponent } from './calendar-dialog.component'; + +describe('CalendarDialogComponent', () => { + let component: CalendarDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CalendarDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CalendarDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.ts b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.ts new file mode 100644 index 0000000..ef102fa --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/dialog/calendar-dialog/calendar-dialog.component.ts @@ -0,0 +1,77 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {throwError} from 'rxjs'; +import {catchError, tap} from 'rxjs/operators'; +import {CalendarTypeService} from 'src/app/core/service/settings/calendar-type.service'; +import {SweetalertService} from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-calendar-dialog', + templateUrl: './calendar-dialog.component.html', + styleUrls: ['./calendar-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CalendarDialogComponent implements OnInit { + form; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}] + + constructor( + private fb: FormBuilder, + private calendarSV: CalendarTypeService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + create_by: null, + create_date: null, + updated_by: null, + updated_date: null, + owner_agency_uid: null, + calendar_type_uid: null, + calendar_type_code: null, + calendar_type_name_th: null, + calendar_type_name_en: null + }); + } + + ngOnInit(): void { + if (this.data) { + this.calendarSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe() + } + } + + save() { + const form = this.form.getRawValue() + if (this.data) { + this.calendarSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close('err') + return throwError(err) + }) + ).subscribe() + } else { + this.calendarSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + } + + cancel() { + this.dialogRef.close() + } + +} diff --git a/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.html b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.html new file mode 100644 index 0000000..aa32dc0 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อรายการปฎิทิน {{x.calendar_type_name_th}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.scss b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.spec.ts b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.spec.ts new file mode 100644 index 0000000..560a8ac --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CalendarListComponent } from './calendar-list.component'; + +describe('CalendarListComponent', () => { + let component: CalendarListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CalendarListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CalendarListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.ts b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.ts new file mode 100644 index 0000000..a3c23d1 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/list/calendar-list/calendar-list.component.ts @@ -0,0 +1,37 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges, ChangeDetectorRef } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'calendar-list', + templateUrl: './calendar-list.component.html', + styleUrls: ['./calendar-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CalendarListComponent extends BaseList implements OnInit,OnChanges { + @Input() calendarList: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + column = ['1', '2', '3', '4', '5', '6']; + constructor( + private cdr: ChangeDetectorRef + ) { + super() + } + + ngOnInit(): void { + + } + + ngOnChanges(){ + this.calendarList = this.updateMatTable(this.calendarList) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.html b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.html new file mode 100644 index 0000000..6d02950 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.scss b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.spec.ts b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.spec.ts new file mode 100644 index 0000000..427ec29 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CalendarSearchComponent } from './calendar-search.component'; + +describe('CalendarSearchComponent', () => { + let component: CalendarSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CalendarSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CalendarSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.ts b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.ts new file mode 100644 index 0000000..a224c01 --- /dev/null +++ b/src/app/feature/settings/calendars/presenter/search/calendar-search/calendar-search.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'calendar-search', + templateUrl: './calendar-search.component.html', + styleUrls: ['./calendar-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CalendarSearchComponent implements OnInit { + @Output() add = new EventEmitter() + @Output() search = new EventEmitter() + query = { + calendar_type_name_th: null + } + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit() + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + calendar_type_name_th: null + } + } + +} diff --git a/src/app/feature/settings/calendars/router/calendars-router.ts b/src/app/feature/settings/calendars/router/calendars-router.ts new file mode 100644 index 0000000..92f685b --- /dev/null +++ b/src/app/feature/settings/calendars/router/calendars-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-calendars-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CalendarsRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/department/contianer/department/department.container.html b/src/app/feature/settings/department/contianer/department/department.container.html new file mode 100644 index 0000000..a3d75b9 --- /dev/null +++ b/src/app/feature/settings/department/contianer/department/department.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/department/contianer/department/department.container.scss b/src/app/feature/settings/department/contianer/department/department.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/department/contianer/department/department.container.spec.ts b/src/app/feature/settings/department/contianer/department/department.container.spec.ts new file mode 100644 index 0000000..ef6bc26 --- /dev/null +++ b/src/app/feature/settings/department/contianer/department/department.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentContainer } from './department.container'; + +describe('DepartmentContainer', () => { + let component: DepartmentContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DepartmentContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/department/contianer/department/department.container.ts b/src/app/feature/settings/department/contianer/department/department.container.ts new file mode 100644 index 0000000..d5df2e3 --- /dev/null +++ b/src/app/feature/settings/department/contianer/department/department.container.ts @@ -0,0 +1,74 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from 'rxjs'; +import {MatDialog} from '@angular/material/dialog'; +import {CalendarTypeService} from '../../../../../core/service/settings/calendar-type.service'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {DepartmentService} from '../../../../../core/service/settings/department.service'; +import {CalendarDialogComponent} from '../../../calendars/presenter/dialog/calendar-dialog/calendar-dialog.component'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {DepartmentDialogComponent} from '../../presenter/dialog/department-dialog/department-dialog.component'; + +@Component({ + selector: 'app-department', + templateUrl: './department.container.html', + styleUrls: ['./department.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DepartmentContainer implements OnInit { + departmentList$ = new Observable() + + constructor( + private dialog: MatDialog, + private departmentSV: DepartmentService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.departmentList$ = this.departmentSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(DepartmentDialogComponent, { + width: '500px', + height: '455px', + autoFocus: false + }); + dialogRef.afterClosed().pipe( + tap(x => this.departmentList$ = this.departmentSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + edit(id){ + const dialogRef = this.dialog.open(DepartmentDialogComponent, { + width: '500px', + height: '455px', + autoFocus: false, + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.departmentList$ = this.departmentSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.departmentSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.departmentList$ = this.departmentSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + search(query){ + if(query) return this.departmentList$ = this.departmentSV.search(`?${query}`) + if(!query) return this.departmentList$ = this.departmentSV.getAll() + } + +} diff --git a/src/app/feature/settings/department/department.module.ts b/src/app/feature/settings/department/department.module.ts new file mode 100644 index 0000000..0676dd5 --- /dev/null +++ b/src/app/feature/settings/department/department.module.ts @@ -0,0 +1,37 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DepartmentRouter } from './router/department-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { DepartmentContainer } from './contianer/department/department.container'; +import { DepartmentSearchComponent } from './presenter/search/department-search/department-search.component'; +import { DepartmentListComponent } from './presenter/list/department-list/department-list.component'; +import { DepartmentDialogComponent } from './presenter/dialog/department-dialog/department-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: DepartmentRouter, + children: [ + { + path: '', + component: DepartmentContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + DepartmentRouter, + DepartmentContainer, + DepartmentSearchComponent, + DepartmentListComponent, + DepartmentDialogComponent], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class DepartmentModule { } diff --git a/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.html b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.html new file mode 100644 index 0000000..2b3b05b --- /dev/null +++ b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.html @@ -0,0 +1,41 @@ +
+
+
+ + + + + {{x.faculty_name_th}} + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.scss b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.spec.ts b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.spec.ts new file mode 100644 index 0000000..c000891 --- /dev/null +++ b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentDialogComponent } from './department-dialog.component'; + +describe('DepartmentDialogComponent', () => { + let component: DepartmentDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DepartmentDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.ts b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.ts new file mode 100644 index 0000000..f66c4c2 --- /dev/null +++ b/src/app/feature/settings/department/presenter/dialog/department-dialog/department-dialog.component.ts @@ -0,0 +1,92 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {CalendarTypeService} from '../../../../../../core/service/settings/calendar-type.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {catchError, tap} from 'rxjs/operators'; +import {DepartmentService} from '../../../../../../core/service/settings/department.service'; +import {throwError} from 'rxjs'; +import {FacultysService} from '../../../../../../core/service/settings/facultys.service'; + +@Component({ + selector: 'app-department-dialog', + templateUrl: './department-dialog.component.html', + styleUrls: ['./department-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DepartmentDialogComponent implements OnInit { + faculty = []; + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + private curSub: any; + constructor( + private fb: FormBuilder, + private facultySV: FacultysService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + private departmentSV: DepartmentService, + + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + create_by: null, + create_date: null, + updated_by: null, + updated_date: null, + deleted_by: null, + deleted_date: null, + faculty_uid: null, + department_uid: null, + department_code: null, + department_name_th: null, + department_name_en: null + }); + } + + ngOnInit(): void { + this.facultySV.getAll().pipe(tap(x => { + this.faculty = x; + })).subscribe(); + if(this.data){ + this.departmentSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)), + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + if(this.data){ + this.departmentSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close('err'); + return throwError(err) + }) + ).subscribe() + } else { + this.departmentSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.dialogRef.close() + } + + displayFacultyname(uid){ + if (uid && this.faculty) return this.faculty.find(x => x.faculty_uid === uid)?.faculty_name_th + if (uid && !this.faculty) return this.curSub?.faculty_name_th + } + +} diff --git a/src/app/feature/settings/department/presenter/list/department-list/department-list.component.html b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.html new file mode 100644 index 0000000..e367496 --- /dev/null +++ b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.html @@ -0,0 +1,63 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสภาควิชา {{x.department_code}} ชื่อภาควิชา {{x.department_name_th}} คณะที่รับผิดชอบ {{x.faculty_name_th}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/department/presenter/list/department-list/department-list.component.scss b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/department/presenter/list/department-list/department-list.component.spec.ts b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.spec.ts new file mode 100644 index 0000000..ac187cd --- /dev/null +++ b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentListComponent } from './department-list.component'; + +describe('DepartmentListComponent', () => { + let component: DepartmentListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DepartmentListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/department/presenter/list/department-list/department-list.component.ts b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.ts new file mode 100644 index 0000000..8ca6bfd --- /dev/null +++ b/src/app/feature/settings/department/presenter/list/department-list/department-list.component.ts @@ -0,0 +1,39 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; + +@Component({ + selector: 'app-department-list', + templateUrl: './department-list.component.html', + styleUrls: ['./department-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DepartmentListComponent extends BaseList implements OnInit , OnChanges { + @Input() departmentList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = ['0','1', '2', 'faculty_name_th','3', '4', '5', '6']; + constructor( + private swSV: SweetalertService, + private testingfieldSV: TestingFieldService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.departmentList = this.updateMatTable(this.departmentList); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings/department/presenter/search/department-search/department-search.component.html b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.html new file mode 100644 index 0000000..3ce12c5 --- /dev/null +++ b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.html @@ -0,0 +1,35 @@ +

ค้นหา

+
+
+
+ + + + + --กรุณาเลือก-- + + + {{x.faculty_name_th}} + + +
+
+ + +
+
+
+ + + +
+
diff --git a/src/app/feature/settings/department/presenter/search/department-search/department-search.component.scss b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/department/presenter/search/department-search/department-search.component.spec.ts b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.spec.ts new file mode 100644 index 0000000..6da033c --- /dev/null +++ b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentSearchComponent } from './department-search.component'; + +describe('DepartmentSearchComponent', () => { + let component: DepartmentSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DepartmentSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/department/presenter/search/department-search/department-search.component.ts b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.ts new file mode 100644 index 0000000..eed2f0e --- /dev/null +++ b/src/app/feature/settings/department/presenter/search/department-search/department-search.component.ts @@ -0,0 +1,66 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, ChangeDetectorRef} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {FacultysService} from '../../../../../../core/service/settings/facultys.service'; +import {tap} from 'rxjs/operators'; +import {DepartmentService} from '../../../../../../core/service/settings/department.service'; + +@Component({ + selector: 'app-department-search', + templateUrl: './department-search.component.html', + styleUrls: ['./department-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DepartmentSearchComponent implements OnInit { + faculty = []; + filteredDepartmentList: any = []; + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + query = { + faculty_uid : null, + department_uid : null + }; + private curSub: any; + constructor( + private departMentSV: DepartmentService, + private facultySV: FacultysService, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + this.facultySV.getAll().pipe(tap(x => { + this.faculty = x; + })).subscribe(); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.filteredDepartmentList = []; + this.query = { + faculty_uid : null, + department_uid : null + }; + } + + displayFacultyname(uid){ + if (uid && this.faculty) return this.faculty.find(x => x.faculty_uid === uid)?.faculty_name_th + if (uid && !this.faculty) return this.curSub?.faculty_name_th + } + + setDepartment(event){ + if (event != null){ + this.departMentSV.search(`?faculty_uid=${event}`).pipe( + tap(x => this.filteredDepartmentList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + } + +} diff --git a/src/app/feature/settings/department/router/department-router.ts b/src/app/feature/settings/department/router/department-router.ts new file mode 100644 index 0000000..4133850 --- /dev/null +++ b/src/app/feature/settings/department/router/department-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DepartmentRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/education-type/container/education-type/education-type.container.html b/src/app/feature/settings/education-type/container/education-type/education-type.container.html new file mode 100644 index 0000000..6841e95 --- /dev/null +++ b/src/app/feature/settings/education-type/container/education-type/education-type.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/education-type/container/education-type/education-type.container.scss b/src/app/feature/settings/education-type/container/education-type/education-type.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/education-type/container/education-type/education-type.container.spec.ts b/src/app/feature/settings/education-type/container/education-type/education-type.container.spec.ts new file mode 100644 index 0000000..8d6c219 --- /dev/null +++ b/src/app/feature/settings/education-type/container/education-type/education-type.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EducationTypeContainer } from './education-type.container'; + +describe('EducationTypeContainer', () => { + let component: EducationTypeContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EducationTypeContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EducationTypeContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/education-type/container/education-type/education-type.container.ts b/src/app/feature/settings/education-type/container/education-type/education-type.container.ts new file mode 100644 index 0000000..55d7e00 --- /dev/null +++ b/src/app/feature/settings/education-type/container/education-type/education-type.container.ts @@ -0,0 +1,70 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {Observable} from 'rxjs'; +import {EducationTypesService} from '../../../../../core/service/settings/education-types.service'; +import {AcademicYearsDialogComponent} from '../../../academic-years/presenter/dialog/academic-years-dialog/academic-years-dialog.component'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {EducationTypeDialogComponent} from '../../presenter/dialog/education-type-dialog/education-type-dialog.component'; + +@Component({ + selector: 'app-education-type', + templateUrl: './education-type.container.html', + styleUrls: ['./education-type.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EducationTypeContainer implements OnInit { + eductypeList$ = new Observable(); + constructor( + private eductypeSV: EducationTypesService, + private cdr: ChangeDetectorRef, + private dialog: MatDialog, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.eductypeList$ = this.eductypeSV.getAll(); + } + add(){ + const dialogRef = this.dialog.open(EducationTypeDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.eductypeList$ = this.eductypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + edit(id){ + const dialogRef = this.dialog.open(EducationTypeDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.eductypeList$ = this.eductypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.eductypeSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.eductypeList$ = this.eductypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + search(query){ + // console.log(query) + if(query) return this.eductypeList$ = this.eductypeSV.search(`?${query}`); + if(!query) return this.eductypeList$ = this.eductypeSV.getAll(); + } + +} diff --git a/src/app/feature/settings/education-type/education-type.module.ts b/src/app/feature/settings/education-type/education-type.module.ts new file mode 100644 index 0000000..73538dd --- /dev/null +++ b/src/app/feature/settings/education-type/education-type.module.ts @@ -0,0 +1,39 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { EducationTypeRouter } from './router/education-type-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { EducationTypeContainer } from './container/education-type/education-type.container'; +import { EducationTypeListComponent } from './presenter/list/education-type-list/education-type-list.component'; +import { EducationTypeSearchComponent } from './presenter/search/education-type-search/education-type-search.component'; +import { EducationTypeDialogComponent } from './presenter/dialog/education-type-dialog/education-type-dialog.component'; + + +const routes: Routes = [ + { + path: '', + component: EducationTypeRouter, + children: [ + { + path: '', + component: EducationTypeContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + EducationTypeRouter, + EducationTypeContainer, + EducationTypeListComponent, + EducationTypeSearchComponent, + EducationTypeDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class EducationTypeModule { } diff --git a/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.html b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.html new file mode 100644 index 0000000..e62f879 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.html @@ -0,0 +1,24 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.scss b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.spec.ts b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.spec.ts new file mode 100644 index 0000000..36bc573 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EducationTypeDialogComponent } from './education-type-dialog.component'; + +describe('EducationTypeDialogComponent', () => { + let component: EducationTypeDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EducationTypeDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EducationTypeDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.ts b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.ts new file mode 100644 index 0000000..dfe7dc8 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/dialog/education-type-dialog/education-type-dialog.component.ts @@ -0,0 +1,79 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {EducationTypesService} from '../../../../../../core/service/settings/education-types.service'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; + +@Component({ + selector: 'app-education-type-dialog', + templateUrl: './education-type-dialog.component.html', + styleUrls: ['./education-type-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EducationTypeDialogComponent implements OnInit { + form; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + constructor( + private eductypeSV: EducationTypesService, + private fb: FormBuilder, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + education_type_uid: null, + education_type_code: null, + education_type_name_th: null, + education_type_name_en: null + }); + } + + ngOnInit(): void { + if (this.data){ + this.eductypeSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + // form.education_type_name_th = form.education_type_code; + // form.education_type_name_en = form.education_type_code; + if (this.data){ + this.eductypeSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } else { + this.eductypeSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.html b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.html new file mode 100644 index 0000000..8081e33 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ปีการศึกษา {{x.education_type_name_th}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.scss b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.spec.ts b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.spec.ts new file mode 100644 index 0000000..269f889 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EducationTypeListComponent } from './education-type-list.component'; + +describe('EducationTypeListComponent', () => { + let component: EducationTypeListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EducationTypeListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EducationTypeListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.ts b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.ts new file mode 100644 index 0000000..0d484f2 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/list/education-type-list/education-type-list.component.ts @@ -0,0 +1,35 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-education-type-list', + templateUrl: './education-type-list.component.html', + styleUrls: ['./education-type-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EducationTypeListComponent extends BaseList implements OnInit , OnChanges { + column = ['1', '2', '3', '4', '5', '6']; + + @Input() eductypeList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.eductypeList = this.updateMatTable(this.eductypeList ? this.eductypeList : []); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.html b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.html new file mode 100644 index 0000000..8a7b8d5 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.scss b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.spec.ts b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.spec.ts new file mode 100644 index 0000000..0b6a137 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EducationTypeSearchComponent } from './education-type-search.component'; + +describe('EducationTypeSearchComponent', () => { + let component: EducationTypeSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EducationTypeSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EducationTypeSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.ts b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.ts new file mode 100644 index 0000000..31a73d6 --- /dev/null +++ b/src/app/feature/settings/education-type/presenter/search/education-type-search/education-type-search.component.ts @@ -0,0 +1,36 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-education-type-search', + templateUrl: './education-type-search.component.html', + styleUrls: ['./education-type-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EducationTypeSearchComponent implements OnInit { + query = { + education_type_name_th: null + }; + @Output() search = new EventEmitter(); + @Output() add = new EventEmitter(); + constructor( + ) { } + + ngOnInit(): void { + } + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + education_type_name_th: null + }; + } + + onAdd(){ + this.add.emit(); + } + +} diff --git a/src/app/feature/settings/education-type/router/education-type-router.ts b/src/app/feature/settings/education-type/router/education-type-router.ts new file mode 100644 index 0000000..c5d0eff --- /dev/null +++ b/src/app/feature/settings/education-type/router/education-type-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-education-type-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EducationTypeRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/faculties/container/faculties/faculties.container.html b/src/app/feature/settings/faculties/container/faculties/faculties.container.html new file mode 100644 index 0000000..36acd83 --- /dev/null +++ b/src/app/feature/settings/faculties/container/faculties/faculties.container.html @@ -0,0 +1,9 @@ + + diff --git a/src/app/feature/settings/faculties/container/faculties/faculties.container.scss b/src/app/feature/settings/faculties/container/faculties/faculties.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/faculties/container/faculties/faculties.container.spec.ts b/src/app/feature/settings/faculties/container/faculties/faculties.container.spec.ts new file mode 100644 index 0000000..f0b61df --- /dev/null +++ b/src/app/feature/settings/faculties/container/faculties/faculties.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FacultiesContainer } from './faculties.container'; + +describe('FacultiesContainer', () => { + let component: FacultiesContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FacultiesContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FacultiesContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/faculties/container/faculties/faculties.container.ts b/src/app/feature/settings/faculties/container/faculties/faculties.container.ts new file mode 100644 index 0000000..e2b772f --- /dev/null +++ b/src/app/feature/settings/faculties/container/faculties/faculties.container.ts @@ -0,0 +1,69 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable } from 'rxjs'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { FacultyDialogComponent } from '../../presenter/dialog/faculty-dialog/faculty-dialog.component'; + +@Component({ + selector: 'app-faculties', + templateUrl: './faculties.container.html', + styleUrls: ['./faculties.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FacultiesContainer implements OnInit { + facultiesList$ = new Observable() + constructor( + private facultySV: FacultysService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.facultiesList$ = this.facultySV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(FacultyDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.facultiesList$ = this.facultySV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + edit(id){ + const dialogRef = this.dialog.open(FacultyDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.facultiesList$ = this.facultySV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.facultySV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.facultiesList$ = this.facultySV.getAll()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + search(query){ + if(query) return this.facultiesList$ = this.facultySV.search(`?${query}`) + if(!query) return this.facultiesList$ = this.facultySV.getAll() + } + +} diff --git a/src/app/feature/settings/faculties/faculties.module.ts b/src/app/feature/settings/faculties/faculties.module.ts new file mode 100644 index 0000000..f9cc323 --- /dev/null +++ b/src/app/feature/settings/faculties/faculties.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { FacultiesRouter } from './router/faculties-router'; +import { FacultiesContainer } from './container/faculties/faculties.container'; +import { FacultiesListComponent } from './presenter/list/faculties-list/faculties-list.component'; +import { FacultiesSearchComponent } from './presenter/search/faculties-search/faculties-search.component'; +import { FacultyDialogComponent } from './presenter/dialog/faculty-dialog/faculty-dialog.component'; + +const routes : Routes =[ + { + path:'', + component: FacultiesRouter, + children:[ + { + path:'', + component: FacultiesContainer + }, + ] + } +] + +@NgModule({ + declarations: [ + FacultiesRouter, + FacultiesContainer, + FacultiesListComponent, + FacultiesSearchComponent, + FacultyDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class FacultiesModule { } diff --git a/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.html b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.html new file mode 100644 index 0000000..e36e543 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.html @@ -0,0 +1,24 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.scss b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.spec.ts b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.spec.ts new file mode 100644 index 0000000..681b638 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FacultyDialogComponent } from './faculty-dialog.component'; + +describe('FacultyDialogComponent', () => { + let component: FacultyDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FacultyDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FacultyDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.ts b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.ts new file mode 100644 index 0000000..26e63b4 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/dialog/faculty-dialog/faculty-dialog.component.ts @@ -0,0 +1,77 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs/operators'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-faculty-dialog', + templateUrl: './faculty-dialog.component.html', + styleUrls: ['./faculty-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FacultyDialogComponent implements OnInit { + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + constructor( + private fb: FormBuilder, + private facultySV: FacultysService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_date: null, + updated_by: null, + updated_date: null, + deleted_by: null, + deleted_date: null, + faculty_uid: null, + faculty_code: null, + faculty_name_th: null, + faculty_name_en: null, + }) + } + + ngOnInit(): void { + if(this.data){ + this.facultySV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe() + } + } + + save(){ + const form = this.form.getRawValue() + if(this.data){ + this.facultySV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } else { + this.facultySV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err() + this.dialogRef.close() + return throwError(err) + }) + ).subscribe() + } + } + + cancel(){ + this.dialogRef.close() + } + +} diff --git a/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.html b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.html new file mode 100644 index 0000000..261dfeb --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อหน่วยงานคณะ {{x.faculty_name_th}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.scss b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.spec.ts b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.spec.ts new file mode 100644 index 0000000..8dfd0a0 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FacultiesListComponent } from './faculties-list.component'; + +describe('FacultiesListComponent', () => { + let component: FacultiesListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FacultiesListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FacultiesListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.ts b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.ts new file mode 100644 index 0000000..979efc1 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/list/faculties-list/faculties-list.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, Output, OnChanges } from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'faculties-list', + templateUrl: './faculties-list.component.html', + styleUrls: ['./faculties-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FacultiesListComponent extends BaseList implements OnInit,OnChanges { + @Input() facultiesList: any = []; + @Output() edit = new EventEmitter() + @Output() delete = new EventEmitter() + column = ['1', '2', '3', '4', '5', '6']; + constructor() { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.facultiesList = this.updateMatTable(this.facultiesList) + } + + onEdit(id){ + this.edit.emit(id) + } + + onDelete(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.html b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.html new file mode 100644 index 0000000..2acf8ab --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.scss b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.spec.ts b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.spec.ts new file mode 100644 index 0000000..d715a9d --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FacultiesSearchComponent } from './faculties-search.component'; + +describe('FacultiesSearchComponent', () => { + let component: FacultiesSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FacultiesSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FacultiesSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.ts b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.ts new file mode 100644 index 0000000..1302c18 --- /dev/null +++ b/src/app/feature/settings/faculties/presenter/search/faculties-search/faculties-search.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'faculties-search', + templateUrl: './faculties-search.component.html', + styleUrls: ['./faculties-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FacultiesSearchComponent implements OnInit { + @Output() add = new EventEmitter() + @Output() search = new EventEmitter() + query = { + faculty_name_th :null + } + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit() + } + + onSearch(){ + let query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + faculty_name_th :null + } + } + +} diff --git a/src/app/feature/settings/faculties/router/faculties-router.ts b/src/app/feature/settings/faculties/router/faculties-router.ts new file mode 100644 index 0000000..1b9b1ed --- /dev/null +++ b/src/app/feature/settings/faculties/router/faculties-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-faculties-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FacultiesRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.html b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.html new file mode 100644 index 0000000..c69a59d --- /dev/null +++ b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.html @@ -0,0 +1,9 @@ + + + diff --git a/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.scss b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.spec.ts b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.spec.ts new file mode 100644 index 0000000..9bbca4e --- /dev/null +++ b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OnlineCounterContainer } from './online-counter.container'; + +describe('OnlineCounterContainer', () => { + let component: OnlineCounterContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ OnlineCounterContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OnlineCounterContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.ts b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.ts new file mode 100644 index 0000000..3be81bb --- /dev/null +++ b/src/app/feature/settings/online-counter/container/online-counter/online-counter.container.ts @@ -0,0 +1,70 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable, throwError } from 'rxjs'; +import { catchError, concatMap, filter, switchMap, tap } from 'rxjs/operators'; +import { OnlineCountersService } from 'src/app/core/service/settings/online-counters.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { FormDialogComponent } from '../../presenter/dialog/form-dialog/form-dialog.component'; + +@Component({ + selector: 'app-online-counter', + templateUrl: './online-counter.container.html', + styleUrls: ['./online-counter.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class OnlineCounterContainer implements OnInit { + onlineCounter$ = new Observable() + constructor( + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private onlineCounterSV: OnlineCountersService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.onlineCounter$ = this.onlineCounterSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(FormDialogComponent, { + width: '500px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.onlineCounter$ = this.onlineCounterSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.onlineCounterSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.onlineCounter$ = this.onlineCounterSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ) + }) + ).subscribe() + } + + edit(uid){ + const dialogRef = this.dialog.open(FormDialogComponent, { + width: '500px', + data : uid + }); + dialogRef.afterClosed().pipe( + tap(x => this.onlineCounter$ = this.onlineCounterSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + search(query){ + if(query) return this.onlineCounter$ = this.onlineCounterSV.search(`?${query}`) + } + +} diff --git a/src/app/feature/settings/online-counter/online-counter.module.ts b/src/app/feature/settings/online-counter/online-counter.module.ts new file mode 100644 index 0000000..b5c4306 --- /dev/null +++ b/src/app/feature/settings/online-counter/online-counter.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../../shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { OnlineCounterRouter } from './router/router'; +import { OnlineCounterContainer } from './container/online-counter/online-counter.container'; +import { SearchComponent } from './presenter/search/search.component'; +import { ListComponent } from './presenter/list/list.component'; +import { FormDialogComponent } from './presenter/dialog/form-dialog/form-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: OnlineCounterRouter, + children: [ + { + path: '', + component: OnlineCounterContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + OnlineCounterRouter, + OnlineCounterContainer, + SearchComponent, + ListComponent, + FormDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class OnlineCounterModule { } diff --git a/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.html b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.html new file mode 100644 index 0000000..fb232f3 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.html @@ -0,0 +1,25 @@ +
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + + diff --git a/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.scss b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.spec.ts b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.spec.ts new file mode 100644 index 0000000..def7a69 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormDialogComponent } from './form-dialog.component'; + +describe('FormDialogComponent', () => { + let component: FormDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.ts b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.ts new file mode 100644 index 0000000..8e6e5f1 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/dialog/form-dialog/form-dialog.component.ts @@ -0,0 +1,84 @@ +import {Location} from '@angular/common'; +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {FormBuilder, FormGroup} from '@angular/forms'; +import {MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; +import {ActivatedRoute, Router} from '@angular/router'; +import {throwError} from 'rxjs'; +import {catchError, tap} from 'rxjs/operators'; +import {BaseForm} from 'src/app/core/base/base-form'; +import {OnlineCountersService} from 'src/app/core/service/settings/online-counters.service'; +import {SweetalertService} from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-form-dialog', + templateUrl: './form-dialog.component.html', + styleUrls: ['./form-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormDialogComponent extends BaseForm implements OnInit { + + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + private onlineCounterSV: OnlineCountersService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { + super(router, activeRoute, fb, location) + } + + ngOnInit(): void { + if (this.data) { + this.onlineCounterSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + } + + createForm(): FormGroup { + return this.fb.group({ + created_by: null, + created_datetime: null, + deleted_by: null, + deleted_datetime: null, + updated_by: null, + updated_datetime: null, + status_id: null, + online_counter_uid: null, + online_counter_code: null, + online_counter_name_th: null, + online_counter_name_en: null, + is_default: null, + }) + } + + save() { + const form = this.form.getRawValue() + if (this.data) { + this.onlineCounterSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + } else { + this.onlineCounterSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + } + } + + +} diff --git a/src/app/feature/settings/online-counter/presenter/list/list.component.html b/src/app/feature/settings/online-counter/presenter/list/list.component.html new file mode 100644 index 0000000..dcb82fb --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/list/list.component.html @@ -0,0 +1,54 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อเค้าเตอร์รับเงินออนไลน์ + {{x.online_counter_name_th}} Default + + สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/online-counter/presenter/list/list.component.scss b/src/app/feature/settings/online-counter/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/online-counter/presenter/list/list.component.spec.ts b/src/app/feature/settings/online-counter/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..e309620 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/online-counter/presenter/list/list.component.ts b/src/app/feature/settings/online-counter/presenter/list/list.component.ts new file mode 100644 index 0000000..0b97f0a --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/list/list.component.ts @@ -0,0 +1,54 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, EventEmitter, Output, OnChanges, SimpleChanges } from '@angular/core'; +import { forkJoin } from 'rxjs'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { OnlineCountersService } from 'src/app/core/service/settings/online-counters.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit, OnChanges { + @Input() counterOnlineList: any = []; + @Output() onEdit = new EventEmitter() + @Output() onDelete = new EventEmitter() + constructor( + private swSV: SweetalertService, + private counterOnlineSV: OnlineCountersService + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(): void { + this.counterOnlineList = this.updateMatTable(this.counterOnlineList ? this.counterOnlineList : []) + } + + setDefault(event,i,self){ + event.preventDefault(); + this.swSV.confirm('ต้องการเปลี่ยนแปลงค่านี้ใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + tap(x => { + this.counterOnlineList.data.map((data,index) => { + if(index == i){ + data.is_default == true? data.is_default = false : data.is_default = true + self.checked = data.is_default + }else{ + data.is_default = false + } + }) + }), + concatMap(x => { + let updateData$ = this.counterOnlineList.data.map(a => { + return this.counterOnlineSV.update2(a) + }) + return forkJoin(updateData$) + }), + ).subscribe() + } +} diff --git a/src/app/feature/settings/online-counter/presenter/search/search.component.html b/src/app/feature/settings/online-counter/presenter/search/search.component.html new file mode 100644 index 0000000..680b671 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/search/search.component.html @@ -0,0 +1,14 @@ +

ค้นหา

+
+
+
+ + +
+
+
+ + + +
+
diff --git a/src/app/feature/settings/online-counter/presenter/search/search.component.scss b/src/app/feature/settings/online-counter/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/online-counter/presenter/search/search.component.spec.ts b/src/app/feature/settings/online-counter/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..c8ab651 --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/online-counter/presenter/search/search.component.ts b/src/app/feature/settings/online-counter/presenter/search/search.component.ts new file mode 100644 index 0000000..dec4b7e --- /dev/null +++ b/src/app/feature/settings/online-counter/presenter/search/search.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { Router } from '@angular/router'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Output() search = new EventEmitter() + @Output() add = new EventEmitter() + query = { + online_counter_name_th: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const queryString = createQueryStringFromObject(this.query) + this.search.emit(queryString) + } + + clear(){ + this.query.online_counter_name_th = null + const queryString = createQueryStringFromObject(this.query) + this.search.emit(queryString) + } + +} diff --git a/src/app/feature/settings/online-counter/router/router.ts b/src/app/feature/settings/online-counter/router/router.ts new file mode 100644 index 0000000..22fc70c --- /dev/null +++ b/src/app/feature/settings/online-counter/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-online-counter-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class OnlineCounterRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/signature/container/signature/signature.container.html b/src/app/feature/settings/signature/container/signature/signature.container.html new file mode 100644 index 0000000..adfab9e --- /dev/null +++ b/src/app/feature/settings/signature/container/signature/signature.container.html @@ -0,0 +1,9 @@ + + + diff --git a/src/app/feature/settings/signature/container/signature/signature.container.scss b/src/app/feature/settings/signature/container/signature/signature.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/signature/container/signature/signature.container.spec.ts b/src/app/feature/settings/signature/container/signature/signature.container.spec.ts new file mode 100644 index 0000000..02b9c24 --- /dev/null +++ b/src/app/feature/settings/signature/container/signature/signature.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SignatureContainer } from './signature.container'; + +describe('SignatureContainer', () => { + let component: SignatureContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SignatureContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SignatureContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/signature/container/signature/signature.container.ts b/src/app/feature/settings/signature/container/signature/signature.container.ts new file mode 100644 index 0000000..81f3a54 --- /dev/null +++ b/src/app/feature/settings/signature/container/signature/signature.container.ts @@ -0,0 +1,70 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Observable, throwError } from 'rxjs'; +import { tap, filter, concatMap, catchError } from 'rxjs/operators'; +import { RecipientSignatureService } from 'src/app/core/service/settings/recipient-signature.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { FormDialogComponent } from '../../presenter/dialog/form-dialog/form-dialog.component'; + +@Component({ + selector: 'app-signature', + templateUrl: './signature.container.html', + styleUrls: ['./signature.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SignatureContainer implements OnInit { + recipientSignature$ = new Observable() + constructor( + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private recipientSignatureSV: RecipientSignatureService, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.recipientSignature$ = this.recipientSignatureSV.getAll() + } + + add(){ + const dialogRef = this.dialog.open(FormDialogComponent, { + width: '500px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.recipientSignature$ = this.recipientSignatureSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(uid){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.recipientSignatureSV.deleteData(uid).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.recipientSignature$ = this.recipientSignatureSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ) + }) + ).subscribe() + } + + edit(uid){ + const dialogRef = this.dialog.open(FormDialogComponent, { + width: '500px', + data : uid + }); + dialogRef.afterClosed().pipe( + tap(x => this.recipientSignature$ = this.recipientSignatureSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + search(query){ + if(query) return this.recipientSignature$ = this.recipientSignatureSV.search(`?${query}`) + } + +} diff --git a/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.html b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.html new file mode 100644 index 0000000..29eb48a --- /dev/null +++ b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.html @@ -0,0 +1,39 @@ +
+
+ +
+ + +
+ +
+ + + +
+ +
+ +
+ + search +
+
+ +
+ + +
+ +
+ + +
+
+
+ + + diff --git a/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.scss b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.spec.ts b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.spec.ts new file mode 100644 index 0000000..1def5da --- /dev/null +++ b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormDialogComponent } from './form-dialog.component'; + +describe('FormDialogComponent', () => { + let component: FormDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.ts b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.ts new file mode 100644 index 0000000..9a4060d --- /dev/null +++ b/src/app/feature/settings/signature/presenter/dialog/form-dialog/form-dialog.component.ts @@ -0,0 +1,110 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { Router, ActivatedRoute } from '@angular/router'; +import { throwError } from 'rxjs'; +import { tap, catchError, filter } from 'rxjs/operators'; +import { BaseForm } from 'src/app/core/base/base-form'; +import { RecipientSignatureService } from 'src/app/core/service/settings/recipient-signature.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { UploadService } from 'src/app/core/service/upload/upload.service'; + +@Component({ + selector: 'app-form-dialog', + templateUrl: './form-dialog.component.html', + styleUrls: ['./form-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormDialogComponent extends BaseForm implements OnInit { + selectfile; + constructor( + public router: Router, + public fb: FormBuilder, + public activeRoute: ActivatedRoute, + public location: Location, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + private recipientSignatureSV: RecipientSignatureService, + private swSV: SweetalertService, + private uploadSV: UploadService, + private cdr: ChangeDetectorRef + ) { + super(router,activeRoute,fb,location) + } + + ngOnInit(): void { + if(this.data){ + this.recipientSignatureSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + } + + createForm(): FormGroup { + return this.fb.group({ + status_id: null, + recipient_signature_uid: null, + recipient_signature_code: null, + recipient_signature_name_th: null, + recipient_signature_name_en: null, + recipient_signature_file_name: null, + recipient_signature_url: null, + is_default: null, + }) + } + + onSelectFile(event) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.upload() + } + } + + upload(){ + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.uploadSV.uploadDocument(formData).pipe( + filter((x:any) => x.status == 'success'), + tap(x => this.form.get('recipient_signature_file_name').setValue(x.message[0].name)), + tap(x => this.form.get('recipient_signature_url').setValue(x.message[0].file_name)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + open(){ + if(this.form.get('recipient_signature_url').value){ + window.open(this.form.get('recipient_signature_url').value) + } + } + + save(){ + const form = this.form.getRawValue() + if(this.data){ + this.recipientSignatureSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + return + } + this.recipientSignatureSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.errText(err.error.description) + return throwError(err) + }) + ).subscribe() + } + + +} diff --git a/src/app/feature/settings/signature/presenter/list/list.component.html b/src/app/feature/settings/signature/presenter/list/list.component.html new file mode 100644 index 0000000..bf9a66b --- /dev/null +++ b/src/app/feature/settings/signature/presenter/list/list.component.html @@ -0,0 +1,54 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ชื่อผู้รับเงิน + {{x.recipient_signature_name_th}} Default + + สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/signature/presenter/list/list.component.scss b/src/app/feature/settings/signature/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/signature/presenter/list/list.component.spec.ts b/src/app/feature/settings/signature/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..a5d3a5c --- /dev/null +++ b/src/app/feature/settings/signature/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/signature/presenter/list/list.component.ts b/src/app/feature/settings/signature/presenter/list/list.component.ts new file mode 100644 index 0000000..dcf55fc --- /dev/null +++ b/src/app/feature/settings/signature/presenter/list/list.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { forkJoin } from 'rxjs'; +import { filter, tap, concatMap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { OnlineCountersService } from 'src/app/core/service/settings/online-counters.service'; +import { RecipientSignatureService } from 'src/app/core/service/settings/recipient-signature.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit, OnChanges { + @Input() signatureList: any = []; + @Output() onEdit = new EventEmitter() + @Output() onDelete = new EventEmitter() + constructor( + private swSV: SweetalertService, + private recipientSignatureSV: RecipientSignatureService + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(): void { + this.signatureList = this.updateMatTable(this.signatureList ? this.signatureList : []) + } + + setDefault(event,i,self){ + event.preventDefault(); + this.swSV.confirm('ต้องการเปลี่ยนแปลงค่านี้ใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + tap(x => { + this.signatureList.data.map((data,index) => { + if(index == i){ + data.is_default == true? data.is_default = false : data.is_default = true + self.checked = data.is_default + }else{ + data.is_default = false + } + }) + }), + concatMap(x => { + let updateData$ = this.signatureList.data.map(a => { + return this.recipientSignatureSV.update2(a) + }) + return forkJoin(updateData$) + }), + ).subscribe() + } +} diff --git a/src/app/feature/settings/signature/presenter/search/search.component.html b/src/app/feature/settings/signature/presenter/search/search.component.html new file mode 100644 index 0000000..65ef04f --- /dev/null +++ b/src/app/feature/settings/signature/presenter/search/search.component.html @@ -0,0 +1,14 @@ +

ค้นหา

+
+
+
+ + +
+
+
+ + + +
+
diff --git a/src/app/feature/settings/signature/presenter/search/search.component.scss b/src/app/feature/settings/signature/presenter/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/signature/presenter/search/search.component.spec.ts b/src/app/feature/settings/signature/presenter/search/search.component.spec.ts new file mode 100644 index 0000000..918ce70 --- /dev/null +++ b/src/app/feature/settings/signature/presenter/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/signature/presenter/search/search.component.ts b/src/app/feature/settings/signature/presenter/search/search.component.ts new file mode 100644 index 0000000..e190221 --- /dev/null +++ b/src/app/feature/settings/signature/presenter/search/search.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core'; +import { Router } from '@angular/router'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + @Output() search = new EventEmitter() + @Output() add = new EventEmitter() + query = { + recipient_signature_name_th: null + } + constructor( + private router: Router + ) { } + + ngOnInit(): void { + } + + onSearch(){ + const queryString = createQueryStringFromObject(this.query) + this.search.emit(queryString) + } + + clear(){ + this.query.recipient_signature_name_th = null + const queryString = createQueryStringFromObject(this.query) + this.search.emit(queryString) + } + +} diff --git a/src/app/feature/settings/signature/router/router.ts b/src/app/feature/settings/signature/router/router.ts new file mode 100644 index 0000000..4cd13d9 --- /dev/null +++ b/src/app/feature/settings/signature/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-signature-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SignatureRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/signature/signature.module.ts b/src/app/feature/settings/signature/signature.module.ts new file mode 100644 index 0000000..11621d3 --- /dev/null +++ b/src/app/feature/settings/signature/signature.module.ts @@ -0,0 +1,39 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../../../shared/shared.module'; +import { RouterModule, Routes } from '@angular/router'; +import { SignatureRouter } from './router/router'; +import { SignatureContainer } from './container/signature/signature.container'; +import { ListComponent } from './presenter/list/list.component'; +import { SearchComponent } from './presenter/search/search.component'; +import { FormDialogComponent } from './presenter/dialog/form-dialog/form-dialog.component'; + + +const routes: Routes = [ + { + path: '', + component: SignatureRouter, + children: [ + { + path: '', + component: SignatureContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + SignatureRouter, + SignatureContainer, + ListComponent, + SearchComponent, + FormDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class SignatureModule { } diff --git a/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.html b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.html new file mode 100644 index 0000000..c1df283 --- /dev/null +++ b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.html @@ -0,0 +1,10 @@ + + +> diff --git a/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.scss b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.spec.ts b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.spec.ts new file mode 100644 index 0000000..b0874d7 --- /dev/null +++ b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestcenterContainer } from './testcenter.container'; + +describe('TestcenterContainer', () => { + let component: TestcenterContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestcenterContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestcenterContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.ts b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.ts new file mode 100644 index 0000000..5aee4d3 --- /dev/null +++ b/src/app/feature/settings/testcenter/container/testcenter/testcenter.container.ts @@ -0,0 +1,76 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {BranchService} from '../../../../../core/service/settings/branch.service'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {TestcenterDialogComponent} from '../../presenter/dialog/testcenter-dialog/testcenter-dialog.component'; + +@Component({ + selector: 'app-testcenter', + templateUrl: './testcenter.container.html', + styleUrls: ['./testcenter.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestcenterContainer implements OnInit { + branchsList$ = new Observable(); + + constructor( + private branchservice: BranchService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.branchsList$ = this.branchservice.getAll(); + } + + add(){ + const dialogRef = this.dialog.open(TestcenterDialogComponent, { + width: '500px', + // height: '600px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.branchsList$ = this.branchservice.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + edit(id){ + const dialogRef = this.dialog.open(TestcenterDialogComponent, { + width: '500px', + // height: '600px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.branchsList$ = this.branchservice.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.branchservice.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.branchsList$ = this.branchservice.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + console.log(err) + this.swSV.errText(err.error) + return throwError(err) + }) + ); + }) + ).subscribe(); + } + + search(query){ + // console.log(query); + if(query) return this.branchsList$ = this.branchservice.search(`?${query}`); + if(!query) return this.branchsList$ = this.branchservice.getAll(); + } + +} diff --git a/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.html b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.html new file mode 100644 index 0000000..d02c241 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.html @@ -0,0 +1,54 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + + diff --git a/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.scss b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.spec.ts b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.spec.ts new file mode 100644 index 0000000..98e7483 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestcenterDialogComponent } from './testcenter-dialog.component'; + +describe('TestcenterDialogComponent', () => { + let component: TestcenterDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestcenterDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestcenterDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.ts b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.ts new file mode 100644 index 0000000..cc36c13 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component.ts @@ -0,0 +1,116 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {FormBuilder, Validators} from '@angular/forms'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {RegionService} from '../../../../../../core/service/region/region.service'; +import {ProviceService} from '../../../../../../core/service/province/provice.service'; + +@Component({ + selector: 'app-testcenter-dialog', + templateUrl: './testcenter-dialog.component.html', + styleUrls: ['./testcenter-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestcenterDialogComponent implements OnInit { + form; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + + regionMock = []; + + provinceMock = []; + isEdit: boolean = false + selectAlready = false; + provinceMock2 = [{id: 3, name: 'จังหวัด 3 '}, {id: 4, name: 'จังหวัด 4'}]; + constructor( + private fb: FormBuilder, + private branchservice: BranchService, + private regionSV: RegionService, + private provinceSV: ProviceService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + private cdr: ChangeDetectorRef + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + branch_uid: null, + branch_code: [null], + branch_name_th: [null,Validators.required], + branch_name_en: null, + province_uid: [null,Validators.required], + region_uid: [null,Validators.required], + }); + } + + ngOnInit(): void { + this.regionSV.getAll().subscribe( + result => this.regionMock = result, + ); + this.provinceSV.getAll().subscribe( + result => this.provinceMock = result, + ); + if (this.data){ + this.isEdit = true + this.branchservice.get(this.data).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + if (this.data){ + this.branchservice.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } else { + this.branchservice.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } + } + + cancel(){ + this.dialogRef.close(); + } + + setProvince(selectObject){ + if (this.selectAlready === true){ + this.provinceSV.getAll().subscribe( + result => { + this.provinceMock = result; + this.provinceMock = this.provinceMock.filter((x) => { + return x.region_uid === selectObject; + }); + } + ); + }else { + this.provinceMock = this.provinceMock.filter((x) => { + return x.region_uid === selectObject; + }); + this.selectAlready = true; + } + } +} diff --git a/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.html b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.html new file mode 100644 index 0000000..e038b5b --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.html @@ -0,0 +1,58 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} code {{x.branch_code}} ชื่อศูนย์สอบ {{x.branch_name_th}} Default + + สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.scss b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.spec.ts b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.spec.ts new file mode 100644 index 0000000..412d9db --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestcenterListComponent } from './testcenter-list.component'; + +describe('TestcenterListComponent', () => { + let component: TestcenterListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestcenterListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestcenterListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.ts b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.ts new file mode 100644 index 0000000..40c10a2 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/list/testcenter-list/testcenter-list.component.ts @@ -0,0 +1,64 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges} from '@angular/core'; +import { forkJoin } from 'rxjs'; +import { concatMap, filter, tap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { BranchService } from 'src/app/core/service/settings/branch.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-testcenter-list', + templateUrl: './testcenter-list.component.html', + styleUrls: ['./testcenter-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestcenterListComponent extends BaseList implements OnInit , OnChanges{ + @Input() branchsList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = ['0','1', '2','default', '3', '4', '5', '6']; + constructor( + private swSV: SweetalertService, + private branchservice: BranchService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.branchsList = this.updateMatTable(this.branchsList); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + + setDefault(event,i,self){ + event.preventDefault(); + this.swSV.confirm('ต้องการเปลี่ยนแปลงค่านี้ใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + tap(x => { + this.branchsList.data.map((branch,index) => { + if(index == i){ + branch.is_default == true? branch.is_default = false : branch.is_default = true + self.checked = branch.is_default + }else{ + branch.is_default = false + } + }) + }), + concatMap(x => { + let updateData$ = this.branchsList.data.map(a => { + return this.branchservice.update2(a) + }) + return forkJoin(updateData$) + }), + ).subscribe() + } + +} diff --git a/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.html b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.html new file mode 100644 index 0000000..bb88625 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.html @@ -0,0 +1,39 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+
+
+ + +
+
+
+ + + +
+
diff --git a/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.scss b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.spec.ts b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.spec.ts new file mode 100644 index 0000000..33de46f --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestcenterSearchComponent } from './testcenter-search.component'; + +describe('TestcenterSearchComponent', () => { + let component: TestcenterSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestcenterSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestcenterSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.ts b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.ts new file mode 100644 index 0000000..9687d32 --- /dev/null +++ b/src/app/feature/settings/testcenter/presenter/search/testcenter-search/testcenter-search.component.ts @@ -0,0 +1,80 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, ChangeDetectorRef} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {RegionService} from '../../../../../../core/service/region/region.service'; +import {ProviceService} from '../../../../../../core/service/province/provice.service'; + +@Component({ + selector: 'app-testcenter-search', + templateUrl: './testcenter-search.component.html', + styleUrls: ['./testcenter-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestcenterSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + query = { + branch_name_th : null, + region_uid : null, + province_uid : null, + }; + regionMock = []; + provinceMock = []; + selectAlready = false; + datanotReady = true; + constructor( + private regionSV: RegionService, + private provinceSV: ProviceService, + private cdr: ChangeDetectorRef, + ) { } + + ngOnInit(): void { + this.regionSV.getAll().subscribe( + result => { + this.regionMock = result; + this.datanotReady = false; + }, + ); + this.provinceSV.getAll().subscribe( + result => { + this.provinceMock = result; + this.datanotReady = false; + }, + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + branch_name_th : null, + region_uid : null, + province_uid : null, + }; + } + + setProvince(selectObject){ + if (this.selectAlready === true){ + this.provinceSV.getAll().subscribe( + result => { + this.provinceMock = result; + this.provinceMock = this.provinceMock.filter((x) => { + return x.region_uid === selectObject; + }); + } + ); + }else { + this.provinceMock = this.provinceMock.filter((x) => { + return x.region_uid === selectObject; + }); + this.selectAlready = true; + } + } + +} diff --git a/src/app/feature/settings/testcenter/router/testcenter-router.ts b/src/app/feature/settings/testcenter/router/testcenter-router.ts new file mode 100644 index 0000000..4441dfe --- /dev/null +++ b/src/app/feature/settings/testcenter/router/testcenter-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-testcenter-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestcenterRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/testcenter/testcenter.module.ts b/src/app/feature/settings/testcenter/testcenter.module.ts new file mode 100644 index 0000000..747e768 --- /dev/null +++ b/src/app/feature/settings/testcenter/testcenter.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {RouterModule, Routes} from '@angular/router'; +import {SharedModule} from '../../../shared/shared.module'; +import {TestcenterRouter} from './router/testcenter-router'; +import { TestcenterContainer } from './container/testcenter/testcenter.container'; +import { TestcenterSearchComponent } from './presenter/search/testcenter-search/testcenter-search.component'; +import { TestcenterListComponent } from './presenter/list/testcenter-list/testcenter-list.component'; +import { TestcenterDialogComponent } from './presenter/dialog/testcenter-dialog/testcenter-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: TestcenterRouter, + children: [ + { + path: '', + component: TestcenterContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + TestcenterRouter, + TestcenterContainer, + TestcenterSearchComponent, + TestcenterListComponent, + TestcenterDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class TestcenterModule { } diff --git a/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.html b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.html new file mode 100644 index 0000000..eb0319c --- /dev/null +++ b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.html @@ -0,0 +1,10 @@ + + + diff --git a/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.scss b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.spec.ts b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.spec.ts new file mode 100644 index 0000000..1acb16a --- /dev/null +++ b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingFieldContainer } from './testing-field.container'; + +describe('TestingFieldContainer', () => { + let component: TestingFieldContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingFieldContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingFieldContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.ts b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.ts new file mode 100644 index 0000000..4d0cfd8 --- /dev/null +++ b/src/app/feature/settings/testing-field/container/testing-field/testing-field.container.ts @@ -0,0 +1,72 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable} from 'rxjs'; +import {BranchService} from '../../../../../core/service/settings/branch.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestcenterDialogComponent} from '../../../testcenter/presenter/dialog/testcenter-dialog/testcenter-dialog.component'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {TestingFieldDialogComponent} from '../../presenter/dialog/testing-field-dialog/testing-field-dialog.component'; + +@Component({ + selector: 'app-testing-field', + templateUrl: './testing-field.container.html', + styleUrls: ['./testing-field.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingFieldContainer implements OnInit { + branchsList$ = new Observable(); + constructor( + private testingfieldSV: TestingFieldService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.branchsList$ = this.testingfieldSV.getAll(); + } + + add(){ + const dialogRef = this.dialog.open(TestingFieldDialogComponent, { + width: '500px', + // height: '460px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.branchsList$ = this.testingfieldSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + edit(id){ + const dialogRef = this.dialog.open(TestingFieldDialogComponent, { + width: '500px', + // height: '460px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.branchsList$ = this.testingfieldSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.testingfieldSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.branchsList$ = this.testingfieldSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + search(query){ + console.log(query); + if(query) return this.branchsList$ = this.testingfieldSV.search(`?${query}`); + if(!query) return this.branchsList$ = this.testingfieldSV.getAll(); + } + +} diff --git a/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.html b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.html new file mode 100644 index 0000000..86731a4 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.html @@ -0,0 +1,42 @@ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+
+ + diff --git a/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.scss b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.spec.ts b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.spec.ts new file mode 100644 index 0000000..6acd1f6 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingFieldDialogComponent } from './testing-field-dialog.component'; + +describe('TestingFieldDialogComponent', () => { + let component: TestingFieldDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingFieldDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingFieldDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.ts b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.ts new file mode 100644 index 0000000..530c8d4 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/dialog/testing-field-dialog/testing-field-dialog.component.ts @@ -0,0 +1,108 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject, ChangeDetectorRef} from '@angular/core'; +import {FormBuilder, Validators} from '@angular/forms'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {catchError, tap} from 'rxjs/operators'; +import {throwError} from 'rxjs'; +import {TestingFieldService} from '../../../../../../core/service/settings/testing-field.service'; +import { makeRandom } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-testing-field-dialog', + templateUrl: './testing-field-dialog.component.html', + styleUrls: ['./testing-field-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingFieldDialogComponent implements OnInit { + form; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + + regionMock = [{id: 1, name: 'ภาคทดสอบ 1'}, {id: 2, name: 'ภาคทดสอบ 2'}]; + + provinceMock = [{id: 1, name: 'จังหวัด 1 '}, {id: 2, name: 'จังหวัด 2 '}]; + + provinceMock2 = [{id: 3, name: 'จังหวัด 3 '}, {id: 4, name: 'จังหวัด 4'}]; + branchList: any = []; + isEdit: boolean = false + constructor( + private fb: FormBuilder, + private branchservice: BranchService, + private testingfieldSV: TestingFieldService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data, + private cdr: ChangeDetectorRef + ) { + this.form = this.fb.group({ + status_id: 1, + // created_by: null, + // created_datetime: null, + // updated_by: null, + // updated_datetime: null, + // deleted_by: null, + // deleted_datetime: null, + testing_field_uid: null, + testing_field_name_th: [null,Validators.required], + testing_field_name_en: [null,Validators.required], + testing_field_code: [makeRandom()], + branch_uid: [null,Validators.required], + }); + } + + ngOnInit(): void { + this.branchservice.getAllStatus1().pipe( + tap(x => this.branchList = x), + ).subscribe(); + if (this.data){ + this.isEdit = true + this.testingfieldSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + if (this.data){ + this.testingfieldSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } else { + this.testingfieldSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } + } + + cancel(){ + this.dialogRef.close(); + } + + setProvince(selectObject){ + switch (selectObject){ + case 1: { + this.provinceMock = [{id: 1, name: 'จังหวัด 1 ของภาคทดสอบ 1'}, {id: 2, name: 'จังหวัด 2 ของภาคทดสอบ 1'}]; + break; + } + case 2: { + this.provinceMock = [{id: 3, name: 'จังหวัด 1 ของภาคทดสอบ 2'}, {id: 4, name: 'จังหวัด 2 ของภาคทดสอบ 2'}]; + break; + } + } + } + +} diff --git a/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.html b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.html new file mode 100644 index 0000000..9fd3d73 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.html @@ -0,0 +1,58 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} code {{x.testing_field_code}} ชื่อสนามสอบ TH {{x.testing_field_name_th}} Default + + สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.scss b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.spec.ts b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.spec.ts new file mode 100644 index 0000000..2dd940a --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingFieldListComponent } from './testing-field-list.component'; + +describe('TestingFieldListComponent', () => { + let component: TestingFieldListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingFieldListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingFieldListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.ts b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.ts new file mode 100644 index 0000000..3acb629 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/list/testing-field-list/testing-field-list.component.ts @@ -0,0 +1,65 @@ +import {Component, OnInit, ChangeDetectionStrategy, OnChanges, Input, Output, EventEmitter} from '@angular/core'; +import { forkJoin } from 'rxjs'; +import { filter } from 'rxjs/internal/operators/filter'; +import { concatMap, tap } from 'rxjs/operators'; +import { TestingFieldService } from 'src/app/core/service/settings/testing-field.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import {BaseList} from '../../../../../../core/base/base-list'; + +@Component({ + selector: 'app-testing-field-list', + templateUrl: './testing-field-list.component.html', + styleUrls: ['./testing-field-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingFieldListComponent extends BaseList implements OnInit , OnChanges { + @Input() branchsList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + column = ['0','1', '2', 'default', '3', '4', '5', '6']; + constructor( + private swSV: SweetalertService, + private testingfieldSV: TestingFieldService, + ) { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.branchsList = this.updateMatTable(this.branchsList); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + + setDefault(event,i,self){ + event.preventDefault(); + this.swSV.confirm('ต้องการเปลี่ยนแปลงค่านี้ใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + tap(x => { + this.branchsList.data.map((branch,index) => { + if(index == i){ + branch.is_default == true? branch.is_default = false : branch.is_default = true + self.checked = branch.is_default + }else{ + branch.is_default = false + } + }) + }), + concatMap(x => { + let updateData$ = this.branchsList.data.map(a => { + return this.testingfieldSV.update2(a) + }) + return forkJoin(updateData$) + }), + ).subscribe() + } + +} diff --git a/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.html b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.html new file mode 100644 index 0000000..06b768a --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.html @@ -0,0 +1,25 @@ +

ค้นหา

+
+
+
+ + +
+
+ + +
+
+
+ + + +
+
diff --git a/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.scss b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.spec.ts b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.spec.ts new file mode 100644 index 0000000..4262d5c --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingFieldSearchComponent } from './testing-field-search.component'; + +describe('TestingFieldSearchComponent', () => { + let component: TestingFieldSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingFieldSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingFieldSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.ts b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.ts new file mode 100644 index 0000000..3112cd6 --- /dev/null +++ b/src/app/feature/settings/testing-field/presenter/search/testing-field-search/testing-field-search.component.ts @@ -0,0 +1,51 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; +import {BranchService} from '../../../../../../core/service/settings/branch.service'; + +@Component({ + selector: 'app-testing-field-search', + templateUrl: './testing-field-search.component.html', + styleUrls: ['./testing-field-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingFieldSearchComponent implements OnInit { + branchMock = []; + + provinceMock = [{id: 1, name: 'จังหวัด 1 '}, {id: 2, name: 'จังหวัด 2 '}]; + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + query = { + testing_field_name_th : null, + branch_uid : null + }; + constructor( + private branchSV: BranchService, + ) { } + + ngOnInit(): void { + this.branchSV.getAll().subscribe( + result => this.branchMock = result, + ); + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + testing_field_name_th : null, + branch_uid : null + }; + } + + setBranch(id){ + this.query.branch_uid = id; + } + +} diff --git a/src/app/feature/settings/testing-field/router/testing-field-router.ts b/src/app/feature/settings/testing-field/router/testing-field-router.ts new file mode 100644 index 0000000..a46c30d --- /dev/null +++ b/src/app/feature/settings/testing-field/router/testing-field-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-testing-field-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingFieldRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/testing-field/testing-field.module.ts b/src/app/feature/settings/testing-field/testing-field.module.ts new file mode 100644 index 0000000..545263a --- /dev/null +++ b/src/app/feature/settings/testing-field/testing-field.module.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TestingFieldRouter } from './router/testing-field-router'; +import { TestingFieldContainer } from './container/testing-field/testing-field.container'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { TestingFieldListComponent } from './presenter/list/testing-field-list/testing-field-list.component'; +import { TestingFieldSearchComponent } from './presenter/search/testing-field-search/testing-field-search.component'; +import { TestingFieldDialogComponent } from './presenter/dialog/testing-field-dialog/testing-field-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: TestingFieldRouter, + children: [ + { + path: '', + component: TestingFieldContainer + }, + ] + } +]; + +@NgModule({ + declarations: [ + TestingFieldRouter, + TestingFieldContainer, + TestingFieldListComponent, + TestingFieldSearchComponent, + TestingFieldDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class TestingFieldModule { } diff --git a/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.html b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.html new file mode 100644 index 0000000..80e97e0 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.html @@ -0,0 +1,10 @@ + + + diff --git a/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.scss b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.spec.ts b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.spec.ts new file mode 100644 index 0000000..e09fb72 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingVdosContainer } from './testing-vdos.container'; + +describe('TestingVdosContainer', () => { + let component: TestingVdosContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingVdosContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingVdosContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.ts b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.ts new file mode 100644 index 0000000..2b506e6 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/container/testing-vdos/testing-vdos.container.ts @@ -0,0 +1,63 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {Observable, throwError} from 'rxjs'; +import {TestingFieldService} from '../../../../../core/service/settings/testing-field.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {TestingVdosService} from '../../../../../core/service/settings/testing-vdos.service'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-testing-vdos', + templateUrl: './testing-vdos.container.html', + styleUrls: ['./testing-vdos.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingVdosContainer implements OnInit { + vdosList$ = new Observable(); + + constructor( + private router: Router, + private testingVdosSV: TestingVdosService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.vdosList$ = this.testingVdosSV.getAll(); + } + + search(query){ + console.log(query); + if(query) return this.vdosList$ = this.testingVdosSV.search(`?${query}`); + if(!query) return this.vdosList$ = this.testingVdosSV.getAll(); + } + + add(){ + this.router.navigate(['testing-vdos/add']); + } + + edit(id){ + this.router.navigate(['testing-vdos/edit', id]); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.testingVdosSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.vdosList$ = this.testingVdosSV.getAll()), + tap(x => this.cdr.detectChanges()), + catchError(err => { + console.log(err) + this.swSV.errText(err.error.description); + return throwError(err); + }) + ); + }) + ).subscribe(); + } + +} diff --git a/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.html b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.html new file mode 100644 index 0000000..748e7de --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.html @@ -0,0 +1,68 @@ +
+

สร้างวิดีโอ

+ +
+
+
+ + +
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+ + + +
+ +
+ +
+
+ + +
+
+
+

ไฟล์วิดีโอ

+
+
+ + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ +
+
+    {{form.getRawValue() | json}}
+
diff --git a/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.scss b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.spec.ts b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.spec.ts new file mode 100644 index 0000000..cd62377 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingVdosFormComponent } from './testing-vdos-form.component'; + +describe('TestingVdosFormComponent', () => { + let component: TestingVdosFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingVdosFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingVdosFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.ts b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.ts new file mode 100644 index 0000000..26e8ac4 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/form/testing-vdos-form/testing-vdos-form.component.ts @@ -0,0 +1,110 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {BaseForm, sortByProperty} from '../../../../../../core/base/base-form'; +import {FormBuilder, Validators} from '@angular/forms'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {UserCountersService} from '../../../../../../core/service/permission/user-counters.service'; +import {catchError, concatMap, filter, tap} from 'rxjs/operators'; +import {UploadService} from '../../../../../../core/service/upload/upload.service'; +import {throwError} from 'rxjs'; +import {TestingVdosService} from '../../../../../../core/service/settings/testing-vdos.service'; + +@Component({ + selector: 'app-testing-vdos-form', + templateUrl: './testing-vdos-form.component.html', + styleUrls: ['./testing-vdos-form.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingVdosFormComponent extends BaseForm implements OnInit { + imageSrc: string; + selectfile; + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private uploadSV: UploadService, + private testingVdosSV: TestingVdosService, + ) { + super(router,activeRoute,fb,location); + } + + ngOnInit(): void { + if(this.state === 'edit'){ + this.testingVdosSV.get(this.id).pipe( + tap(x => this.setupForm(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + } + + setupForm(x){ + this.form.patchValue(x); + this.imageSrc = x.vdo_url + } + + createForm(){ + return this.fb.group({ + testing_vdo_uid: null, + testing_vdo_code: [null, Validators.required], + testing_vdo_name_th: [null, Validators.required], + testing_vdo_name_en: [null, Validators.required], + vdo_url: [null, Validators.required], + vdo_name: [null, Validators.required], + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + }); + } + + uploadVideo(event){ + const file = event.target.files[0]; + if(file.type.indexOf('image')> -1){ + return this.swSV.errText('กรุณาอัพโหลดไฟล์วิดีโอ') + } else if(file.type.indexOf('video')> -1){ + this.selectfile = event.target.files[0]; + const formData: FormData = new FormData(); + formData.append('filecard', this.selectfile, this.selectfile.name); + this.uploadSV.add(formData).pipe( + tap((x: any) => this.form.get('vdo_url').setValue(x[0].file_name)), + tap((x: any) => this.imageSrc = x[0].file_name), + tap((x: any) => this.form.get('vdo_name').setValue(x[0].name)), + tap(x => this.cdr.detectChanges()), + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + switch (this.state) { + case 'edit': + this.testingVdosSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ).subscribe(); + break; + + case 'add': + this.testingVdosSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error); + return throwError(err); + }) + ).subscribe(); + break; + } + } + +} diff --git a/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.html b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.html new file mode 100644 index 0000000..e7b9ff1 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.html @@ -0,0 +1,73 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสวิดีโอ {{x.testing_vdo_code}} ชื่อวิดีโอ {{x.testing_vdo_name_th}} Default + + ชื่อไฟล์ {{x.vdo_name}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + + + + +
+
+ + + ไม่มีข้อมูล +
+ + + +
+
+
diff --git a/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.scss b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.spec.ts b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.spec.ts new file mode 100644 index 0000000..cf155b6 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingVdosListComponent } from './testing-vdos-list.component'; + +describe('TestingVdosListComponent', () => { + let component: TestingVdosListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingVdosListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingVdosListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.ts b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.ts new file mode 100644 index 0000000..2d740ea --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/list/testing-vdos-list/testing-vdos-list.component.ts @@ -0,0 +1,88 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter, OnChanges, ChangeDetectorRef, Input} from '@angular/core'; +import {BaseList} from '../../../../../../core/base/base-list'; +import {AppTokenService} from '../../../../../../core/service/security/app-token.service'; +import {filter} from 'rxjs/internal/operators/filter'; +import {concatMap, tap} from 'rxjs/operators'; +import {forkJoin} from 'rxjs'; +import {SweetalertService} from '../../../../../../core/service/sweetalert/sweetalert'; +import {TestingVdosService} from '../../../../../../core/service/settings/testing-vdos.service'; + +@Component({ + selector: 'app-testing-vdos-list', + templateUrl: './testing-vdos-list.component.html', + styleUrls: ['./testing-vdos-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingVdosListComponent extends BaseList implements OnInit, OnChanges { + @Input() vdosList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + + column = [ + '1', + 'testing_vdo_code', + 'testing_vdo_name_th', + 'default', + 'vdo_name', + 'created_by', + 'created_datetime', + '7' + ]; + + + reload: boolean; + + constructor( + private appTokenSV: AppTokenService, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private testingVdosSV: TestingVdosService, + + ) { + super(); + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + this.cdr.detectChanges(); + }, 5000); + } + + ngOnChanges(){ + this.vdosList = this.updateMatTable(this.vdosList ? this.vdosList : []); + } + + setDefault(event,i,self){ + event.preventDefault(); + this.swSV.confirm('ต้องการเปลี่ยนแปลงค่านี้ใช่หรือไม่').pipe( + filter(x => x.isConfirmed), + tap(x => { + this.vdosList.data.map((vdo,index) => { + if(index == i){ + vdo.is_default == true? vdo.is_default = false : vdo.is_default = true + self.checked = vdo.is_default + }else{ + vdo.is_default = false + } + }) + }), + concatMap(x => { + let updateData$ = this.vdosList.data.map(a => { + return this.testingVdosSV.update2(a) + }) + return forkJoin(updateData$) + }), + ).subscribe() + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.html b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.html new file mode 100644 index 0000000..306c4d4 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.html @@ -0,0 +1,20 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+
diff --git a/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.scss b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.spec.ts b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.spec.ts new file mode 100644 index 0000000..b2b9624 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingVdosSearchComponent } from './testing-vdos-search.component'; + +describe('TestingVdosSearchComponent', () => { + let component: TestingVdosSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingVdosSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingVdosSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.ts b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.ts new file mode 100644 index 0000000..cfc69b1 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/presenter/search/testing-vdos-search/testing-vdos-search.component.ts @@ -0,0 +1,40 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-testing-vdos-search', + templateUrl: './testing-vdos-search.component.html', + styleUrls: ['./testing-vdos-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingVdosSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList; + statusMock = [{id: 1, name: 'ใช้งาน'}, {id: 2, name: 'ยกเลิก'}]; + query = { + testing_vdo_name_th: null, + testing_vdo_code: null + }; + constructor() { } + + ngOnInit(): void { + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + testing_vdo_name_th: null, + testing_vdo_code: null + }; + } + +} diff --git a/src/app/feature/settings/testing-vdos/router/testing-vdos-router.ts b/src/app/feature/settings/testing-vdos/router/testing-vdos-router.ts new file mode 100644 index 0000000..acde7d2 --- /dev/null +++ b/src/app/feature/settings/testing-vdos/router/testing-vdos-router.ts @@ -0,0 +1,14 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-router', + template: ``, +}) +export class TestingVdosRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/testing-vdos/testing-vdos.module.ts b/src/app/feature/settings/testing-vdos/testing-vdos.module.ts new file mode 100644 index 0000000..22fe98d --- /dev/null +++ b/src/app/feature/settings/testing-vdos/testing-vdos.module.ts @@ -0,0 +1,46 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TestingVdosRouter } from './router/testing-vdos-router'; +import {RouterModule, Routes} from '@angular/router'; +import {SharedModule} from '../../../shared/shared.module'; +import { TestingVdosContainer } from './container/testing-vdos/testing-vdos.container'; +import { TestingVdosListComponent } from './presenter/list/testing-vdos-list/testing-vdos-list.component'; +import { TestingVdosSearchComponent } from './presenter/search/testing-vdos-search/testing-vdos-search.component'; +import { TestingVdosFormComponent } from './presenter/form/testing-vdos-form/testing-vdos-form.component'; + +const routes: Routes = [ + { + path: '', + component: TestingVdosRouter, + children: [ + { + path: '', + component: TestingVdosContainer + }, + { + path: 'add', + component: TestingVdosFormComponent + }, + { + path: 'edit/:id', + component: TestingVdosFormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + TestingVdosRouter, + TestingVdosContainer, + TestingVdosListComponent, + TestingVdosSearchComponent, + TestingVdosFormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class TestingVdosModule { } diff --git a/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.html b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.html new file mode 100644 index 0000000..3bbbbf9 --- /dev/null +++ b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.scss b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.spec.ts b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.spec.ts new file mode 100644 index 0000000..13e7414 --- /dev/null +++ b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TypesubjectContainer } from './typesubject.container'; + +describe('TypesubjectContainer', () => { + let component: TypesubjectContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TypesubjectContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TypesubjectContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.ts b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.ts new file mode 100644 index 0000000..cd1b22b --- /dev/null +++ b/src/app/feature/settings/typesubject/container/typesubject/typesubject.container.ts @@ -0,0 +1,71 @@ +import {Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef} from '@angular/core'; +import {FacultysService} from '../../../../../core/service/settings/facultys.service'; +import {MatDialog} from '@angular/material/dialog'; +import {SweetalertService} from '../../../../../core/service/sweetalert/sweetalert'; +import {SubjectTypesService} from '../../../../../core/service/settings/subject-types.service'; +import {Observable} from 'rxjs'; +import {FacultyDialogComponent} from '../../../faculties/presenter/dialog/faculty-dialog/faculty-dialog.component'; +import {concatMap, filter, tap} from 'rxjs/operators'; +import {TypesubjectDialogComponent} from "../../presenter/dialog/typesubject-dialog/typesubject-dialog.component"; + +@Component({ + selector: 'app-typesubject', + templateUrl: './typesubject.container.html', + styleUrls: ['./typesubject.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TypesubjectContainer implements OnInit { + subjecttypeList$ = new Observable(); + constructor( + private subjecttypeSV: SubjectTypesService, + private dialog: MatDialog, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService + ) { } + + ngOnInit(): void { + this.subjecttypeList$ = this.subjecttypeSV.getAll(); + } + + add(){ + const dialogRef = this.dialog.open(TypesubjectDialogComponent, { + width: '500px', + height: '300px', + }); + dialogRef.afterClosed().pipe( + tap(x => this.subjecttypeList$ = this.subjecttypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + edit(id){ + const dialogRef = this.dialog.open(TypesubjectDialogComponent, { + width: '500px', + height: '300px', + data: id + }); + dialogRef.afterClosed().pipe( + tap(x => this.subjecttypeList$ = this.subjecttypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ).subscribe(); + } + + delete(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + concatMap(x => { + return this.subjecttypeSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.subjecttypeList$ = this.subjecttypeSV.getAll()), + tap(x => this.cdr.detectChanges()) + ); + }) + ).subscribe(); + } + + search(query){ + if(query) return this.subjecttypeList$ = this.subjecttypeSV.search(`?${query}`); + if(!query) return this.subjecttypeList$ = this.subjecttypeSV.getAll(); + } + +} diff --git a/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.html b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.html new file mode 100644 index 0000000..8743aad --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.html @@ -0,0 +1,22 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
diff --git a/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.scss b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.spec.ts b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.spec.ts new file mode 100644 index 0000000..194bb07 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TypesubjectDialogComponent } from './typesubject-dialog.component'; + +describe('TypesubjectDialogComponent', () => { + let component: TypesubjectDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TypesubjectDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TypesubjectDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.ts b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.ts new file mode 100644 index 0000000..b369d54 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/dialog/typesubject-dialog/typesubject-dialog.component.ts @@ -0,0 +1,78 @@ +import {Component, OnInit, ChangeDetectionStrategy, Inject} from '@angular/core'; +import {FormBuilder} from "@angular/forms"; +import {FacultysService} from "../../../../../../core/service/settings/facultys.service"; +import {SweetalertService} from "../../../../../../core/service/sweetalert/sweetalert"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {SubjectTypesService} from "../../../../../../core/service/settings/subject-types.service"; +import {catchError, tap} from "rxjs/operators"; +import {throwError} from "rxjs"; + +@Component({ + selector: 'app-typesubject-dialog', + templateUrl: './typesubject-dialog.component.html', + styleUrls: ['./typesubject-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TypesubjectDialogComponent implements OnInit { + form; + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}] + constructor( + private fb: FormBuilder, + private subjecttypeSV: SubjectTypesService, + private swSV: SweetalertService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data + ) { + this.form = this.fb.group({ + status_id: 1, + created_by: null, + created_datetime: null, + updated_by: null, + updated_datetime: null, + deleted_by: null, + deleted_datetime: null, + subject_type_uid: null, + subject_type_code: null, + subject_type_name_th: null, + subject_type_name_en: null, + }); + } + + ngOnInit(): void { + if (this.data){ + this.subjecttypeSV.get(this.data).pipe( + tap(x => this.form.patchValue(x)) + ).subscribe(); + } + } + + save(){ + const form = this.form.getRawValue(); + if(this.data){ + this.subjecttypeSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } else { + this.subjecttypeSV.add(form).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => this.dialogRef.close()), + catchError(err => { + this.swSV.err(); + this.dialogRef.close(); + return throwError(err); + }) + ).subscribe(); + } + } + + cancel(){ + this.dialogRef.close(); + } + +} diff --git a/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.html b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.html new file mode 100644 index 0000000..814a250 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.html @@ -0,0 +1,48 @@ +
+
+

แสดงผลรายการค้นหา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} ประเภทวิชา {{x.subject_type_name_th}} สถานะ + ใช้งาน + ยกเลิก + ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ + +
+
+ +
+
+
diff --git a/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.scss b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.spec.ts b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.spec.ts new file mode 100644 index 0000000..70b2ae4 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TypesubjectListComponent } from './typesubject-list.component'; + +describe('TypesubjectListComponent', () => { + let component: TypesubjectListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TypesubjectListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TypesubjectListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.ts b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.ts new file mode 100644 index 0000000..79e47bf --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/list/typesubject-list/typesubject-list.component.ts @@ -0,0 +1,37 @@ +import {Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, Output, EventEmitter} from '@angular/core'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-typesubject-list', + templateUrl: './typesubject-list.component.html', + styleUrls: ['./typesubject-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TypesubjectListComponent extends BaseList implements OnInit , OnChanges { + @Input() subjecttypeList: any = []; + @Output() edit = new EventEmitter(); + @Output() delete = new EventEmitter(); + + column = ['1', '2', '3', '4', '5', '6']; + + + constructor() { + super(); + } + + ngOnInit(): void { + } + + ngOnChanges(){ + this.subjecttypeList = this.updateMatTable(this.subjecttypeList); + } + + onEdit(id){ + this.edit.emit(id); + } + + onDelete(id){ + this.delete.emit(id); + } + +} diff --git a/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.html b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.html new file mode 100644 index 0000000..d1d99cd --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.html @@ -0,0 +1,15 @@ +

ค้นหา

+
+
+
+ + +
+ +
+ + + +
+
+
diff --git a/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.scss b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.spec.ts b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.spec.ts new file mode 100644 index 0000000..6bc5b11 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TypesubjectSearchComponent } from './typesubject-search.component'; + +describe('TypesubjectSearchComponent', () => { + let component: TypesubjectSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TypesubjectSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TypesubjectSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.ts b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.ts new file mode 100644 index 0000000..aacad10 --- /dev/null +++ b/src/app/feature/settings/typesubject/presenter/search/typesubject-search/typesubject-search.component.ts @@ -0,0 +1,35 @@ +import {Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter} from '@angular/core'; +import {createQueryStringFromObject} from '../../../../../../shared/util/func'; + +@Component({ + selector: 'app-typesubject-search', + templateUrl: './typesubject-search.component.html', + styleUrls: ['./typesubject-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TypesubjectSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + query = { + subject_type_name_th : null + }; + constructor() { } + + ngOnInit(): void { + } + onAdd(){ + this.add.emit(); + } + + onSearch(){ + const query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + subject_type_name_th : null + }; + } + +} diff --git a/src/app/feature/settings/typesubject/router/typesubject-router.ts b/src/app/feature/settings/typesubject/router/typesubject-router.ts new file mode 100644 index 0000000..7d5609a --- /dev/null +++ b/src/app/feature/settings/typesubject/router/typesubject-router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-typesubject-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TypesubjectRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/settings/typesubject/typesubject.module.ts b/src/app/feature/settings/typesubject/typesubject.module.ts new file mode 100644 index 0000000..b2e5548 --- /dev/null +++ b/src/app/feature/settings/typesubject/typesubject.module.ts @@ -0,0 +1,40 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TypesubjectRouter } from './router/typesubject-router'; +import {SharedModule} from '../../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { TypesubjectContainer } from './container/typesubject/typesubject.container'; +import { TypesubjectListComponent } from './presenter/list/typesubject-list/typesubject-list.component'; +import { TypesubjectSearchComponent } from './presenter/search/typesubject-search/typesubject-search.component'; +import { TypesubjectDialogComponent } from './presenter/dialog/typesubject-dialog/typesubject-dialog.component'; + + +const routes: Routes = [ + { + path: '', + component: TypesubjectRouter, + children: [ + { + path: '', + component: TypesubjectContainer + }, + ] + } +]; + + +@NgModule({ + declarations: [ + TypesubjectRouter, + TypesubjectContainer, + TypesubjectListComponent, + TypesubjectSearchComponent, + TypesubjectDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes) + ] +}) +export class TypesubjectModule { } diff --git a/src/app/feature/student-info/container/student-info/student-info.container.html b/src/app/feature/student-info/container/student-info/student-info.container.html new file mode 100644 index 0000000..7325566 --- /dev/null +++ b/src/app/feature/student-info/container/student-info/student-info.container.html @@ -0,0 +1,6 @@ + diff --git a/src/app/feature/student-info/container/student-info/student-info.container.scss b/src/app/feature/student-info/container/student-info/student-info.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/student-info/container/student-info/student-info.container.ts b/src/app/feature/student-info/container/student-info/student-info.container.ts new file mode 100644 index 0000000..1a506b9 --- /dev/null +++ b/src/app/feature/student-info/container/student-info/student-info.container.ts @@ -0,0 +1,47 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; +import { Observable } from 'rxjs'; +import { filter, switchMap, tap } from 'rxjs/operators'; +import { CandidateTypeService } from 'src/app/core/service/enrollment-api/candidate-type.service'; +import { StudentService } from 'src/app/core/service/student/student.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { UserService } from 'src/app/core/service/user/user.service'; + +@Component({ + selector: 'app-student-info', + templateUrl: './student-info.container.html', + styleUrls: ['./student-info.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class StudentInfoContainer implements OnInit { + studentList$ = new Observable() + candidateType$ = new Observable() + constructor( + private userSV: UserService, + private candidateTypeSV: CandidateTypeService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.candidateType$ = this.candidateTypeSV.getAll() + } + + search(query){ + if(query) this.studentList$ = this.userSV.search('?'+query) + } + + deleteUser(id){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.userSV.deleteData(id).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.studentList$ = this.userSV.search('?examinee_card=-')), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + +} diff --git a/src/app/feature/student-info/presenter/form/form/form.component.html b/src/app/feature/student-info/presenter/form/form/form.component.html new file mode 100644 index 0000000..dd02e6c --- /dev/null +++ b/src/app/feature/student-info/presenter/form/form/form.component.html @@ -0,0 +1,145 @@ +
+

ข้อมูลผู้สอบ

+
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+ + + +
+ + +
+
{{form.getRawValue() | json}}
+ + diff --git a/src/app/feature/student-info/presenter/form/form/form.component.scss b/src/app/feature/student-info/presenter/form/form/form.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/student-info/presenter/form/form/form.component.spec.ts b/src/app/feature/student-info/presenter/form/form/form.component.spec.ts new file mode 100644 index 0000000..2549983 --- /dev/null +++ b/src/app/feature/student-info/presenter/form/form/form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FormComponent } from './form.component'; + +describe('FormComponent', () => { + let component: FormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/student-info/presenter/form/form/form.component.ts b/src/app/feature/student-info/presenter/form/form/form.component.ts new file mode 100644 index 0000000..0fa7653 --- /dev/null +++ b/src/app/feature/student-info/presenter/form/form/form.component.ts @@ -0,0 +1,130 @@ +import { Location } from '@angular/common'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable, throwError } from 'rxjs'; +import { tap, catchError } from 'rxjs/operators'; +import { BaseFormUid } from 'src/app/core/base/base-form-uid'; +import { CandidateTypeService } from 'src/app/core/service/enrollment-api/candidate-type.service'; +import { DepartmentService } from 'src/app/core/service/settings/department.service'; +import { FacultysService } from 'src/app/core/service/settings/facultys.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { UserService } from 'src/app/core/service/user/user.service'; + +@Component({ + selector: 'app-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.scss'], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FormComponent extends BaseFormUid implements OnInit { + @Input() UsersData: any = []; + form; + passwordShowHide = 'password'; + checkPassword; + userData; + faculty$ = new Observable() + candidateType$ = new Observable() + department$ = new Observable() + constructor( + public fb: FormBuilder, + public router: Router, + public activeRoute: ActivatedRoute, + public location: Location, + private cdr: ChangeDetectorRef, + private swSV: SweetalertService, + private userSV: UserService, + private candidateTypeSV: CandidateTypeService, + private facultySV: FacultysService, + private departmentSV: DepartmentService + ) { + super(router,activeRoute,fb,location); + this.form = this.fb.group({ + user_uid: null, + candidate_type_uid: null, + examinee_type_uid: null, + examinee_card: null, + student_code: null, + full_name: null, + faculty_uid: null, + department_uid: null, + mobile_phone: null, + email: null, + password: null, + faculty_name_th: null, + department_name_th: null, + candidate_type_name_th: null + }); + // this.checkPassword = this.fb.group({ + // password: null, + // passwordNew: null, + // passwordNewCon: null, + // }); + } + + ngOnInit(): void { + // this.candidateTypeSV.getAll().pipe(tap(x => this.candidateType = x)).subscribe() + // this.facultySV.getAll().pipe(tap(x => this.faculty = x)).subscribe() + // this.departmentSV.getAll().pipe(tap(x => this.department = x)).subscribe() + this.faculty$ = this.facultySV.getAll() + this.candidateType$ = this.candidateTypeSV.getAll() + this.department$ = this.departmentSV.getAll() + this.userSV.get(this.id).pipe( + tap(x => this.form.patchValue(x)), + tap(x => this.cdr.detectChanges()) + ).subscribe() + this.cdr.detectChanges() + } + + save(){ + const form = this.form.getRawValue() + this.userSV.update2(form).pipe( + tap(x => this.swSV.updateSuccess()), + tap(x => this.location.back()), + catchError(err => { + this.swSV.err() + return throwError(err) + }) + ).subscribe() + } + + // save(){ + // const form = this.form.getRawValue() + // const pass = this.checkPassword.getRawValue() + // if(pass.password != null && pass.passwordNew != null && pass.passwordNewCon != null){ + // if((form.password == pass.password)&&(pass.passwordNew == pass.passwordNewCon)){ + // form.password = pass.passwordNew + // this.userSV.update2(form).pipe( + // tap(x => this.swSV.updateSuccess('บันทึกข้อมูลผู้สอบเสร็จสิ้น')), + // catchError(err => { + // this.swSV.err() + // return throwError(err) + // }) + // ).subscribe() + // }else{ + // this.swSV.errText('รหัสผ่านเก่าหรือรหัสผ่านใหม่ไม่ตรงกัน'); + // } + // }else{ + // this.userSV.update2(form).pipe( + // tap(x => this.swSV.updateSuccess('บันทึกข้อมูลผู้สอบเสร็จสิ้น')), + // catchError(err => { + // this.swSV.err() + // return throwError(err) + // }) + // ).subscribe() + // } + // } + + cancel(){ + this.location.back() + } + + onShowHidepass(e) { + if(e.target.checked){ + this.passwordShowHide = 'text'; + }else { + this.passwordShowHide = 'password'; + } + } + +} diff --git a/src/app/feature/student-info/presenter/list/list.component.html b/src/app/feature/student-info/presenter/list/list.component.html new file mode 100644 index 0000000..b347534 --- /dev/null +++ b/src/app/feature/student-info/presenter/list/list.component.html @@ -0,0 +1,71 @@ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+
+
+

รายชื่อข้อมูลนักศึกษา

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{this.getIndex(i)}} รหัสนักศึกษา {{x.student_code}} ชื่อ-นามสกุล (TH) {{x.full_name}} รหัสบัตรประชาชน {{x.examinee_card}} ประเภทผู้สมัคร {{x.candidate_type_uid | getDataId : candidateType:'candidate_type_uid' : 'candidate_type_name_th':''}} +
+ +   + +
+
+ +
+ +
diff --git a/src/app/feature/student-info/presenter/list/list.component.scss b/src/app/feature/student-info/presenter/list/list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/student-info/presenter/list/list.component.spec.ts b/src/app/feature/student-info/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..e309620 --- /dev/null +++ b/src/app/feature/student-info/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/student-info/presenter/list/list.component.ts b/src/app/feature/student-info/presenter/list/list.component.ts new file mode 100644 index 0000000..6d5f3af --- /dev/null +++ b/src/app/feature/student-info/presenter/list/list.component.ts @@ -0,0 +1,115 @@ +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Input, Output, EventEmitter, OnChanges } from '@angular/core'; +import { Router } from '@angular/router'; +import { throwError } from 'rxjs'; +import { tap, catchError, filter, concatMap, switchMap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { StudentUploadService } from 'src/app/core/service/student/student-upload.service'; +import { StudentService } from 'src/app/core/service/student/student.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { UploadService } from 'src/app/core/service/upload/upload.service'; +import { UserService } from 'src/app/core/service/user/user.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() studentList: any = []; + @Input() candidateType: any = []; + @Output() search = new EventEmitter() + @Output() delete = new EventEmitter() + query = { + student_code: null, + full_name: null, + examinee_card: null + } + selectfile; + data; + confirmData; + constructor( + private studentUploadSV: StudentUploadService, + private uploadSV: UploadService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private studentSV: StudentService, + private router: Router, + private userSV: UserService + ) { + super() + } + + ngOnInit(): void { + } + + ngOnChanges(){ + if(this.studentList) this.studentList = this.updateMatTable(this.studentList? this.studentList:[]) + } + + onSearch(){ + const query = createQueryStringFromObject(this.query) + this.search.emit(query) + } + + clear(){ + this.query = { + student_code: null, + full_name: null, + examinee_card: null + } + this.studentList = this.updateMatTable([]) + } + onSelectFile(event) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.upload() + } + } + + uploadFile(event,x){ + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.uploadPicture(x) + } + } + + upload(){ + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.studentUploadSV.uploadDocument(formData).pipe( + filter((x:any) => x.status == 'success'), + tap(x => this.swSV.saveSuccess('นำเข้าสำเร็จ')), + tap(x => this.studentList = this.updateMatTable(x.message)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText('มีข้อผิดพลาดในการนำเข้า') + return throwError(err) + }) + ).subscribe() + } + + uploadPicture(form){ + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.uploadSV.add(formData).pipe( + tap((x:any) => form.photo_url = x[0].file_name), + concatMap(x => this.studentSV.update2(form)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText('มีข้อผิดพลาดในการอัปโหลด') + return throwError(err) + }) + ).subscribe() + } + + edit(x){ + this.router.navigate(['check-student-info/edit',x]) + } + + remove(id){ + this.delete.emit(id) + } + +} diff --git a/src/app/feature/student-info/presenter/search/search/search.component.html b/src/app/feature/student-info/presenter/search/search/search.component.html new file mode 100644 index 0000000..c99423e --- /dev/null +++ b/src/app/feature/student-info/presenter/search/search/search.component.html @@ -0,0 +1 @@ +

search works!

diff --git a/src/app/feature/student-info/presenter/search/search/search.component.scss b/src/app/feature/student-info/presenter/search/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/student-info/presenter/search/search/search.component.spec.ts b/src/app/feature/student-info/presenter/search/search/search.component.spec.ts new file mode 100644 index 0000000..c8ab651 --- /dev/null +++ b/src/app/feature/student-info/presenter/search/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/student-info/presenter/search/search/search.component.ts b/src/app/feature/student-info/presenter/search/search/search.component.ts new file mode 100644 index 0000000..b8a17e1 --- /dev/null +++ b/src/app/feature/student-info/presenter/search/search/search.component.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/student-info/router/router.ts b/src/app/feature/student-info/router/router.ts new file mode 100644 index 0000000..858e5ac --- /dev/null +++ b/src/app/feature/student-info/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-student-info-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class StudentInfoRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/student-info/student-info.module.ts b/src/app/feature/student-info/student-info.module.ts new file mode 100644 index 0000000..b4ca1ae --- /dev/null +++ b/src/app/feature/student-info/student-info.module.ts @@ -0,0 +1,42 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { StudentInfoRouter } from './router/router'; +import { ListComponent } from './presenter/list/list.component'; +import { SearchComponent } from './presenter/search/search/search.component'; +import { StudentInfoContainer } from './container/student-info/student-info.container'; +import { FormComponent } from './presenter/form/form/form.component'; + +const routes: Routes = [ + { + path: '', + component: StudentInfoRouter, + children: [ + { + path: '', + component: StudentInfoContainer + }, + { + path: 'edit/:id', + component: FormComponent + }, + ] + } +]; + +@NgModule({ + declarations: [ + StudentInfoContainer, + StudentInfoRouter, + ListComponent, + SearchComponent, + FormComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class StudentInfoModule { } diff --git a/src/app/feature/upload-student/container/testing-info/testing-info.container.html b/src/app/feature/upload-student/container/testing-info/testing-info.container.html new file mode 100644 index 0000000..9865ac8 --- /dev/null +++ b/src/app/feature/upload-student/container/testing-info/testing-info.container.html @@ -0,0 +1,2 @@ + + diff --git a/src/app/feature/upload-student/container/testing-info/testing-info.container.scss b/src/app/feature/upload-student/container/testing-info/testing-info.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/container/testing-info/testing-info.container.spec.ts b/src/app/feature/upload-student/container/testing-info/testing-info.container.spec.ts new file mode 100644 index 0000000..a270ce7 --- /dev/null +++ b/src/app/feature/upload-student/container/testing-info/testing-info.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoContainer } from './testing-info.container'; + +describe('TestingInfoContainer', () => { + let component: TestingInfoContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/container/testing-info/testing-info.container.ts b/src/app/feature/upload-student/container/testing-info/testing-info.container.ts new file mode 100644 index 0000000..6ac6662 --- /dev/null +++ b/src/app/feature/upload-student/container/testing-info/testing-info.container.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; + +@Component({ + selector: 'app-testing-info', + templateUrl: './testing-info.container.html', + styleUrls: ['./testing-info.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoContainer implements OnInit { + testingInfo$ = new Observable() + constructor( + private testingInfomationSV: TestingInformationService, + ) { } + + ngOnInit(): void { + this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?is_open=true`).pipe( + map((x:any) => x.filter(a => a.type_of_examinee != 'บุคคลทั่วไป')) + ) + } + + search(query){ + if(query) return this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?is_open=true&${query}`).pipe( + map((x:any) => x.filter(a => a.type_of_examinee != 'บุคคลทั่วไป')) + ); + if(!query) return this.testingInfo$ = this.testingInfomationSV.searchForSeat(`?is_open=true&${query}`).pipe( + map((x:any) => x.filter(a => a.type_of_examinee != 'บุคคลทั่วไป')) + ); + } + +} diff --git a/src/app/feature/upload-student/container/upload-student/upload-student.container.html b/src/app/feature/upload-student/container/upload-student/upload-student.container.html new file mode 100644 index 0000000..9a96d85 --- /dev/null +++ b/src/app/feature/upload-student/container/upload-student/upload-student.container.html @@ -0,0 +1,6 @@ + diff --git a/src/app/feature/upload-student/container/upload-student/upload-student.container.scss b/src/app/feature/upload-student/container/upload-student/upload-student.container.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/container/upload-student/upload-student.container.spec.ts b/src/app/feature/upload-student/container/upload-student/upload-student.container.spec.ts new file mode 100644 index 0000000..72052f2 --- /dev/null +++ b/src/app/feature/upload-student/container/upload-student/upload-student.container.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UploadStudentContainer } from './upload-student.container'; + +describe('UploadStudentContainer', () => { + let component: UploadStudentContainer; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UploadStudentContainer ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UploadStudentContainer); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/container/upload-student/upload-student.container.ts b/src/app/feature/upload-student/container/upload-student/upload-student.container.ts new file mode 100644 index 0000000..3b526f0 --- /dev/null +++ b/src/app/feature/upload-student/container/upload-student/upload-student.container.ts @@ -0,0 +1,43 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; +import { concatMap, tap } from 'rxjs/operators'; +import { RuStudentRegistersService } from 'src/app/core/service/ru-student/ru-student-registers.service'; +import { StudentService } from 'src/app/core/service/student/student.service'; +import { TestingInformationService } from 'src/app/core/service/testing-information/testing-information.service'; +import { TestingInfoContainer } from '../testing-info/testing-info.container'; + +@Component({ + selector: 'app-upload-student', + templateUrl: './upload-student.container.html', + styleUrls: ['./upload-student.container.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UploadStudentContainer implements OnInit { + studentList$ = new Observable() + testing$ = new Observable() + testingInfomationData; + constructor( + private studentSV: StudentService, + private activeRoute: ActivatedRoute, + private testingInfomationSV: TestingInformationService, + private studentRuSV: RuStudentRegistersService + ) { } + + ngOnInit(): void { + this.testing$ = this.activeRoute.params.pipe( + concatMap(x => this.testingInfomationSV.get(x.id)), + tap(x => this.testingInfomationData = x) + ) + } + + search(query){ + if(query) this.studentList$ = this.studentSV.search('?'+query) + } + + searchRu(query){ + if(query) this.studentList$ = this.studentRuSV.search('?'+query) + } + + +} diff --git a/src/app/feature/upload-student/presenter/list/list.component.html b/src/app/feature/upload-student/presenter/list/list.component.html new file mode 100644 index 0000000..4f19943 --- /dev/null +++ b/src/app/feature/upload-student/presenter/list/list.component.html @@ -0,0 +1,193 @@ +

ประเภทผู้เข้าสอบ : {{infoData?.type_of_examinee}} / รอบสอบ : {{infoData?.testing_information_name}}

+
+
+
+ + +
+ +
+ + +
+ + + +
+ + + + +
+
+ +
+ + + +
+ +
+
+
+
+

รายชื่อข้อมูลนักศึกษา

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + ลำดับ {{this.getIndex(i)}} รหัสนักศึกษา {{x.student_code? x.student_code : '-'}} ชื่อ-นามสกุล (TH) {{x.student_name_th}} ชื่อ-นามสกุล (EN) {{x.student_name_en}} รหัสวิชา {{x.subject_code}} วันสอบ + {{x.testing_datetime | thaidate}} + {{getDate(x.exam_day,x.exam_month,x.exam_year) | thaidate}} + คาบสอบ {{x.period_id? x.period_id : x.exam_period}} ห้องสอบ {{x.testing_room_code? x.testing_room_code : x.room_no}} ที่นั่งสอบ {{x.testing_seat? x.testing_seat : x.seat_no}} +
+ + +
+
+ +   + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + ลำดับ {{this.getIndex(i)}} รหัสผู้เข้าสอบ {{x.student_code? x.student_code : '-'}} ชื่อ-นามสกุล (TH) {{x.student_name_th}} ชื่อ-นามสกุล (EN) {{x.student_name_en}} วิชาลงทะเบียน {{x.subject_registers? x.subject_registers : x.register_subject_code}} +
+ + +
+
+ +   + +
+
+ +
+
+ +
+
+ + + +
+ + + + diff --git a/src/app/feature/upload-student/presenter/list/list.component.scss b/src/app/feature/upload-student/presenter/list/list.component.scss new file mode 100644 index 0000000..da52f1a --- /dev/null +++ b/src/app/feature/upload-student/presenter/list/list.component.scss @@ -0,0 +1,5 @@ +.ru-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #62bccc; + min-width: 100px !important; +} diff --git a/src/app/feature/upload-student/presenter/list/list.component.spec.ts b/src/app/feature/upload-student/presenter/list/list.component.spec.ts new file mode 100644 index 0000000..e309620 --- /dev/null +++ b/src/app/feature/upload-student/presenter/list/list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/list/list.component.ts b/src/app/feature/upload-student/presenter/list/list.component.ts new file mode 100644 index 0000000..412919e --- /dev/null +++ b/src/app/feature/upload-student/presenter/list/list.component.ts @@ -0,0 +1,291 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { I } from '@angular/cdk/keycodes'; +import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, Input, Output, EventEmitter, OnChanges, ViewChild, ElementRef } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { of, throwError } from 'rxjs'; +import { tap, catchError, filter, concatMap, switchMap } from 'rxjs/operators'; +import { BaseList } from 'src/app/core/base/base-list'; +import { RuStudentService } from 'src/app/core/service/ru-student/ru-student.service'; +import { DeleteImportStudentService } from 'src/app/core/service/student/delete-import-student.service'; +import { StudentGenerateRegisterService } from 'src/app/core/service/student/student-generate-register.service'; +import { StudentUploadService } from 'src/app/core/service/student/student-upload.service'; +import { StudentService } from 'src/app/core/service/student/student.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; +import { UploadService } from 'src/app/core/service/upload/upload.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; +import { TemplateDialogComponent } from '../template-dialog/template-dialog.component'; +import { UploadDialogComponent } from '../upload-dialog/upload-dialog.component'; + +@Component({ + selector: 'app-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ListComponent extends BaseList implements OnInit,OnChanges { + @Input() studentList: any = []; + @Input() infoData; + @ViewChild('et') et: ElementRef + @Output() search = new EventEmitter() + @Output() searchRu = new EventEmitter() + selection = new SelectionModel(true, []); + query = { + student_code: null, + student_name_th: null, + testing_information_uid: null + } + studentType; + selectfile; + data; + confirmData; + isEt : boolean = false + isEtUploaded: boolean = false + isRuStudent: boolean = false + constructor( + private studentUploadSV: StudentUploadService, + private uploadSV: UploadService, + private swSV: SweetalertService, + private cdr: ChangeDetectorRef, + private studentSV: StudentService, + private dialog: MatDialog, + private ruStudentUploadSV: RuStudentService, + private studentGenerateRegisterSV: StudentGenerateRegisterService, + private deleteImportStudentSV: DeleteImportStudentService + ) { + super() + } + + ngOnInit(): void { + + } + + ngOnChanges(){ + if(this.studentList){ + this.studentList = this.updateMatTable(this.studentList? this.studentList:[]) + } + if(this.infoData){ + if(this.infoData.type_of_examinee.includes('โครงการพิเศษ')){ + this.studentType = 3 + } else if (this.infoData.type_of_examinee.includes('บุคคลทั่วไป')){ + this.studentType = 2 + } else { + this.studentType = 1 + } + if(this.infoData.registration_type == 1) this.isRuStudent = true + } + } + + onSearch(){ + this.query.testing_information_uid = this.infoData.testing_information_uid + const query = createQueryStringFromObject(this.query) + if(this.studentType == 1){ + this.searchRu.emit(query) + }else{ + this.search.emit(query) + } + } + + clear(){ + this.query = { + student_code: null, + student_name_th: null, + testing_information_uid: null + } + this.studentList = this.updateMatTable([]) + } + onSelectFile(event) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.uploadEtdc() + } + } + + uploadEtdc(){ + this.swSV.loadingStart('กำลังอัปโหลดไฟล์') + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.ruStudentUploadSV.registerUpload(this.infoData.testing_information_code,formData).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess('นำเข้าสำเร็จ')), + tap(x => this.isEtUploaded = true), + tap(x => this.studentList = this.updateMatTable(x)), + catchError(err => { + this.swSV.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + save(){ + this.studentGenerateRegisterSV.register(this.infoData.testing_information_uid,this.studentList.data).pipe( + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + saveRuStudent(isGenerateSeat){ + this.swSV.loadingStart() + this.studentGenerateRegisterSV.registerSeat(this.infoData.testing_information_uid,isGenerateSeat,this.studentList.data).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess()), + tap(x => window.history.back()), + catchError(err => { + this.swSV.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + uploadFile(event,x){ + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + this.uploadPicture(x) + } + } + + uploadDialog(){ + const obj = { + testing_information : this.infoData, + student_type : this.studentType + } + const dialogRef = this.dialog.open(UploadDialogComponent, { + width: '500px', + data: obj, + }); + + dialogRef.afterClosed().pipe( + filter(x => x), + tap(x => this.isEt = true), + concatMap(x => { + if(x.data && this.studentType != 1){ + this.swSV.saveSuccess('นำเข้าสำเร็จ') + this.studentList = this.updateMatTable(x.data) + return of() + } + if(this.studentType == 1){ + return this.swSV.save('นำเข้าสำเร็จแล้ว','อัปโหลดไฟล์ ET_STDC').pipe( + filter(x => x.isConfirmed), + tap(x => this.et.nativeElement.click()) + ) + } + }), + tap(x => this.cdr.detectChanges()), + ).subscribe() + } + + uploadPicture(form){ + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.uploadSV.add(formData).pipe( + tap((x:any) => form.photo_url = x[0].file_name), + concatMap(x => this.studentSV.update2(form)), + tap(x => this.cdr.detectChanges()), + catchError(err => { + this.swSV.errText('มีข้อผิดพลาดในการอัปโหลด') + return throwError(err) + }) + ).subscribe() + } + + view(x){ + window.open(x) + } + + deletePicture(form){ + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + tap(x => form.photo_url = null), + switchMap(x => { + return this.studentSV.update2(form).pipe( + tap(x => this.swSV.removeSuccess()), + tap(x => this.cdr.detectChanges()) + ) + }) + ).subscribe() + } + + template(){ + if(this.studentType == 1){ + + }else{ + const obj = { + testing_information : this.infoData, + student_type : this.studentType + } + const dialogRef = this.dialog.open(TemplateDialogComponent, { + width: '600px', + data: obj, + }); + } + } + + getDate(day,month,year){ + const new_year = +year+2500 + return new Date(new_year-543, month-1, day) + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.studentList?.data.length; + return numSelected === numRows; + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + if (this.isAllSelected()) { + this.selection.clear(); + return; + } + + this.selection.select(...this.studentList?.data); + } + + /** The label for the checkbox on the passed row */ + checkboxLabel(row?): string { + if (!row) { + return `${this.isAllSelected() ? 'deselect' : 'select'} all`; + } + return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`; + } + + remove(){ + if(this.infoData.registration_type == 1){ + const studentLists = [...this.selection.selected].map(x => x.student_code) + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.deleteImportStudentSV.deleteImportType1(this.infoData.testing_information_uid,studentLists).pipe( + tap(x => this.swSV.removeSuccess('ลบข้อมูลสำเร็จ')), + tap(x => this.onSearch()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + if(this.infoData.registration_type == 2){ + const studentLists = [...this.selection.selected].map(x => x.student_uid) + this.swSV.confirm().pipe( + filter(x => x.isConfirmed), + switchMap(x => { + return this.deleteImportStudentSV.deleteImportType2(studentLists).pipe( + tap(x => this.swSV.removeSuccess('ลบข้อมูลสำเร็จ')), + tap(x => this.onSearch()), + catchError(err => { + this.swSV.errText(err.error) + return throwError(err) + }) + ) + }) + ).subscribe() + } + } +} diff --git a/src/app/feature/upload-student/presenter/search/search/search.component.html b/src/app/feature/upload-student/presenter/search/search/search.component.html new file mode 100644 index 0000000..c99423e --- /dev/null +++ b/src/app/feature/upload-student/presenter/search/search/search.component.html @@ -0,0 +1 @@ +

search works!

diff --git a/src/app/feature/upload-student/presenter/search/search/search.component.scss b/src/app/feature/upload-student/presenter/search/search/search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/presenter/search/search/search.component.spec.ts b/src/app/feature/upload-student/presenter/search/search/search.component.spec.ts new file mode 100644 index 0000000..c8ab651 --- /dev/null +++ b/src/app/feature/upload-student/presenter/search/search/search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SearchComponent } from './search.component'; + +describe('SearchComponent', () => { + let component: SearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/search/search/search.component.ts b/src/app/feature/upload-student/presenter/search/search/search.component.ts new file mode 100644 index 0000000..b8a17e1 --- /dev/null +++ b/src/app/feature/upload-student/presenter/search/search/search.component.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-search', + templateUrl: './search.component.html', + styleUrls: ['./search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SearchComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.html b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.html new file mode 100644 index 0000000..c625e7c --- /dev/null +++ b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.html @@ -0,0 +1,26 @@ +
+ +
+
+
+ +
+ ผู้สมัครแบบชำระเงินค่าสมัครแล้ว + +
+
+
+ ผู้สมัครแบบยังไม่ชำระเงิน + +
+
+
+ +
+ +
+ โครงการพิเศษ / บุคคลทั่วไป + +
+
+
diff --git a/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.scss b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.scss new file mode 100644 index 0000000..15c0d46 --- /dev/null +++ b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.scss @@ -0,0 +1,4 @@ +.vl { + border-left: 3px solid black; + margin-top: 15px; +} diff --git a/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.spec.ts b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.spec.ts new file mode 100644 index 0000000..b0e3c9d --- /dev/null +++ b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TemplateDialogComponent } from './template-dialog.component'; + +describe('TemplateDialogComponent', () => { + let component: TemplateDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TemplateDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TemplateDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.ts b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.ts new file mode 100644 index 0000000..7c057d3 --- /dev/null +++ b/src/app/feature/upload-student/presenter/template-dialog/template-dialog.component.ts @@ -0,0 +1,47 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +@Component({ + selector: 'app-template-dialog', + templateUrl: './template-dialog.component.html', + styleUrls: ['./template-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TemplateDialogComponent implements OnInit { + + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + ) { } + + ngOnInit(): void { + + } + + word(){ + + } + + excel(){ + let link = document.createElement("a") + link.download = "ru_student_template" + link.href = "assets/templates/student_import.xlsx" + link.click() + } + + paid_excel(){ + let link = document.createElement("a") + link.download = "ru_student_template_paid" + link.href = "assets/templates/ru_student_template_paid.xlsx" + link.click() + } + + wait_excel(){ + let link = document.createElement("a") + link.download = "ru_student_template_wait" + link.href = "assets/templates/ru_student_template_wait.xlsx" + link.click() + } + +} diff --git a/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.html b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.html new file mode 100644 index 0000000..12d58b7 --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.html @@ -0,0 +1,73 @@ +
+
+
+

แสดงผลรายการค้นหา

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ลำดับ {{i+1}} รหัสรอบสอบ {{x.testing_information_code}} ชื่อรอบการสอบ {{x.testing_information_name}} ประเภทผู้สมัคร {{x.type_of_examinee}} เก้าอี้ทั้งหมด {{x.total_seat}} จำนวนที่นำเข้าแล้ว {{x.no_imported}} ภาคเรียน {{x.academic_semester_code}} ปีการศึกษา {{x.academic_year_code}} ผู้สร้าง {{x.created_by}} วันที่สร้างข้อมูล {{x.created_datetime | thaidate}} เครื่องมือ +
+ +
+
+ + + ไม่มีข้อมูล +
+ +
+
+
diff --git a/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.scss b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.spec.ts b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.spec.ts new file mode 100644 index 0000000..3fd41ba --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoListComponent } from './testing-info-list.component'; + +describe('TestingInfoListComponent', () => { + let component: TestingInfoListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoListComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.ts b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.ts new file mode 100644 index 0000000..b59f7af --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-list/testing-info-list.component.ts @@ -0,0 +1,48 @@ +import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Router } from '@angular/router'; +import { BaseList } from 'src/app/core/base/base-list'; + +@Component({ + selector: 'app-testing-info-list', + templateUrl: './testing-info-list.component.html', + styleUrls: ['./testing-info-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoListComponent extends BaseList implements OnInit,OnChanges { + @Input() testingInfomationList : any = []; + column = [ + '1', + 'testing_information_code', + 'testing_information_name', + 'type_of_examinee', + 'total_seat', + 'no_imported', + 'academic_semester_code', + 'academic_year_code', + 'created_by', + 'created_datetime', + '11' + ]; + reload: boolean; + constructor( + private router: Router + ) { + super() + } + + ngOnInit(): void { + this.reload = false; + setTimeout(() => { + this.reload = true; + }, 2000); + } + + ngOnChanges(changes: SimpleChanges): void { + this.testingInfomationList = this.updateMatTable(this.testingInfomationList? this.testingInfomationList:[]) + } + + onView(uid){ + this.router.navigate(['student-info/view',uid]) + } + +} diff --git a/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.html b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.html new file mode 100644 index 0000000..e7db067 --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.html @@ -0,0 +1,29 @@ + +

ค้นหา

+
+
+
+ + + + +
+ +
+ + + + +
+
+ +
+ + +
+
+ diff --git a/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.scss b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.spec.ts b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.spec.ts new file mode 100644 index 0000000..a82a897 --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TestingInfoSearchComponent } from './testing-info-search.component'; + +describe('TestingInfoSearchComponent', () => { + let component: TestingInfoSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TestingInfoSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestingInfoSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.ts b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.ts new file mode 100644 index 0000000..36a97bd --- /dev/null +++ b/src/app/feature/upload-student/presenter/testing-info-search/testing-info-search.component.ts @@ -0,0 +1,54 @@ +import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ChangeDetectorRef } from '@angular/core'; +import { tap } from 'rxjs/operators'; +import { AcademicYearService } from 'src/app/core/service/settings/academic-year.service'; +import { createQueryStringFromObject } from 'src/app/shared/util/func'; + +@Component({ + selector: 'app-testing-info-search', + templateUrl: './testing-info-search.component.html', + styleUrls: ['./testing-info-search.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TestingInfoSearchComponent implements OnInit { + @Output() add = new EventEmitter(); + @Output() search = new EventEmitter(); + academicYearList + statusMock = [{id:1, name:'ใช้งาน'},{id:2, name:'ยกเลิก'}]; + query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + // registration_type: 1 + }; + constructor( + private acdmYearSV: AcademicYearService, + private cdr: ChangeDetectorRef + ) { } + + ngOnInit(): void { + this.acdmYearSV.getAll().pipe( + tap(x => this.academicYearList = x), + tap(x => this.cdr.detectChanges()) + ).subscribe() + } + + onAdd(){ + this.add.emit(); + } + + onSearch(){ + let query = createQueryStringFromObject(this.query); + this.search.emit(query); + } + + clear(){ + this.query = { + academic_year_code: null, + testing_information_code: null, + testing_information_name: null, + academic_semester_code: null, + // registration_type: 1 + }; + } +} diff --git a/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.html b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.html new file mode 100644 index 0000000..a9a709f --- /dev/null +++ b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.html @@ -0,0 +1,18 @@ +
+ +
+ +
+
+ + + + + +
+ +
+ + +
+ diff --git a/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.scss b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.spec.ts b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.spec.ts new file mode 100644 index 0000000..441b3e5 --- /dev/null +++ b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UploadDialogComponent } from './upload-dialog.component'; + +describe('UploadDialogComponent', () => { + let component: UploadDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UploadDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UploadDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.ts b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.ts new file mode 100644 index 0000000..27e01e2 --- /dev/null +++ b/src/app/feature/upload-student/presenter/upload-dialog/upload-dialog.component.ts @@ -0,0 +1,85 @@ +import { Component, OnInit, ChangeDetectionStrategy, Inject } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { throwError } from 'rxjs'; +import { catchError, filter, tap } from 'rxjs/operators'; +import { RuStudentService } from 'src/app/core/service/ru-student/ru-student.service'; +import { StudentUploadService } from 'src/app/core/service/student/student-upload.service'; +import { SweetalertService } from 'src/app/core/service/sweetalert/sweetalert'; + +@Component({ + selector: 'app-upload-dialog', + templateUrl: './upload-dialog.component.html', + styleUrls: ['./upload-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UploadDialogComponent implements OnInit { + selectfile; + constructor( + public dialog: MatDialog, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private studentUploadSV: StudentUploadService, + private swSV: SweetalertService, + private ruStudentUploadSV: RuStudentService + ) { } + + ngOnInit(): void { + + } + + onSelectFile(event,isWord?) { + if (event.target.files && event.target.files[0]) { + this.selectfile = event.target.files[0]; + if(isWord){ + return this.uploadWord() + } + this.uploadExcel() + } + } + + uploadWord(){ + this.swSV.loadingStart('กำลังอัปโหลดไฟล์') + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + this.studentUploadSV.uploadStudentWord(formData,this.data.testing_information.testing_information_uid).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess('นำเข้าสำเร็จ')), + tap(x => this.dialogRef.close({data : x})), + catchError(err => { + this.swSV.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + + + uploadExcel(){ + this.swSV.loadingStart('กำลังอัปโหลดไฟล์') + const formData: FormData = new FormData(); + formData.append('file', this.selectfile, this.selectfile.name); + if(this.data.student_type == 1){ + this.ruStudentUploadSV.uploadStudent(formData).pipe( + tap(x => this.swSV.close()), + tap(x => this.dialogRef.close({data : x})), + catchError(err => { + this.swSV.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + }else{ + this.studentUploadSV.uploadStudent(formData,this.data.testing_information.testing_information_uid).pipe( + tap(x => this.swSV.close()), + tap(x => this.swSV.saveSuccess('นำเข้าสำเร็จ')), + tap(x => this.dialogRef.close({data : x})), + catchError(err => { + this.swSV.close() + this.swSV.errText(err.error) + return throwError(err) + }) + ).subscribe() + } + } + +} diff --git a/src/app/feature/upload-student/router/router.ts b/src/app/feature/upload-student/router/router.ts new file mode 100644 index 0000000..58f5c8b --- /dev/null +++ b/src/app/feature/upload-student/router/router.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-upload-student-router', + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class UploadStudentRouter implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/feature/upload-student/upload-student.module.ts b/src/app/feature/upload-student/upload-student.module.ts new file mode 100644 index 0000000..e43f72c --- /dev/null +++ b/src/app/feature/upload-student/upload-student.module.ts @@ -0,0 +1,51 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import {SharedModule} from '../../shared/shared.module'; +import {RouterModule, Routes} from '@angular/router'; +import { UploadStudentRouter } from './router/router'; +import { UploadStudentContainer } from './container/upload-student/upload-student.container'; +import { ListComponent } from './presenter/list/list.component'; +import { SearchComponent } from './presenter/search/search/search.component'; +import { TestingInfoContainer } from './container/testing-info/testing-info.container'; +import { TestingInfoSearchComponent } from './presenter/testing-info-search/testing-info-search.component'; +import { TestingInfoListComponent } from './presenter/testing-info-list/testing-info-list.component'; +import { UploadDialogComponent } from './presenter/upload-dialog/upload-dialog.component'; +import { TemplateDialogComponent } from './presenter/template-dialog/template-dialog.component'; + +const routes: Routes = [ + { + path: '', + component: UploadStudentRouter, + children: [ + { + path: '', + component: TestingInfoContainer + }, + { + path: 'view/:id', + component: UploadStudentContainer + }, + + ] + } +]; + +@NgModule({ + declarations: [ + UploadStudentContainer, + UploadStudentRouter, + ListComponent, + SearchComponent, + TestingInfoContainer, + TestingInfoSearchComponent, + TestingInfoListComponent, + UploadDialogComponent, + TemplateDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + RouterModule.forChild(routes), + ] +}) +export class UploadStudentModule { } diff --git a/src/app/layout/main-layout/main-layout.component.html b/src/app/layout/main-layout/main-layout.component.html new file mode 100644 index 0000000..501a561 --- /dev/null +++ b/src/app/layout/main-layout/main-layout.component.html @@ -0,0 +1,13 @@ +
+
+
+ +
+
+
+ +
+ +
+
+
diff --git a/src/app/layout/main-layout/main-layout.component.scss b/src/app/layout/main-layout/main-layout.component.scss new file mode 100644 index 0000000..7f0d52c --- /dev/null +++ b/src/app/layout/main-layout/main-layout.component.scss @@ -0,0 +1,20 @@ +.expandMenu { + width: 50px; + height: 100%; + min-height: 100vh; + transition: width 300ms cubic-bezier(0.2, 0, 0, 1) 0s; + will-change: width; +} + +.content{ + @apply p-6; +} + +.container_menu{ + height: 100%; + min-height: 100vh; + width: 250px; + transition: width 300ms cubic-bezier(0.2, 0, 0, 1) 0s; + will-change: width; +} + diff --git a/src/app/layout/main-layout/main-layout.component.spec.ts b/src/app/layout/main-layout/main-layout.component.spec.ts new file mode 100644 index 0000000..1b61612 --- /dev/null +++ b/src/app/layout/main-layout/main-layout.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { MainLayoutComponent } from './main-layout.component'; + +describe('MainLayoutComponent', () => { + let component: MainLayoutComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ MainLayoutComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MainLayoutComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/layout/main-layout/main-layout.component.ts b/src/app/layout/main-layout/main-layout.component.ts new file mode 100644 index 0000000..8819234 --- /dev/null +++ b/src/app/layout/main-layout/main-layout.component.ts @@ -0,0 +1,16 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-main-layout', + templateUrl: './main-layout.component.html', + styleUrls: ['./main-layout.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class MainLayoutComponent implements OnInit { + isExpandMenu: boolean = true + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/layout/menu/menu/menu.component.html b/src/app/layout/menu/menu/menu.component.html new file mode 100644 index 0000000..aa29fd5 --- /dev/null +++ b/src/app/layout/menu/menu/menu.component.html @@ -0,0 +1,491 @@ +
+
+
+ +
+
+ +
+
+ add_box + กำหนดรายวิชาสอบ +
+ +
+ insert_invitation +
+
+ + + + + +
+ + quiz + + +
+
+
+ +
+
    +
    +
  • ข้อมูลพื้นฐาน
  • +
    +
    +
  • กำหนดเงื่อนไข
  • +
    +
    +
  • กำหนดปฏิทิน
  • +
    +
    +
  • กำหนดวิชาสอบ
  • +
    +
    +
  • กำหนดห้องสอบ
  • +
    +
    +
  • กำหนดกรรมการคุมสอบ
  • +
    +
    +
  • สร้างเงื่อนไขการสุ่มคำถาม
  • +
    +
    +
  • กำหนดเกณฑ์คะแนน
  • +
    +
    +
  • กำหนดวันสอบของวิชา
  • +
    +
+
+
+
+
+
+ + + + + +
+ + insert_invitation + + +
+
+
+ +
+
    +
    +
  • ตรวจสอบข้อมูลรอบสอบ
  • +
    +
    +
  • เปิดรอบสอบ
  • +
    + + + +
    +
  • อัปโหลดข้อมูลผู้เข้าสอบ
  • +
    +
    +
  • สร้างเลขที่นั่งสอบ
  • +
    +
    +
  • ปิดรอบสอบ
  • +
    +
    +
  • เพิ่มวันสอบ
  • +
    +
    +
  • เพิ่มห้องสอบ
  • +
    +
+
+
+
+
+
+ +
+ download_done + การจัดการศูนย์สอบ +
+ +
+ ballot +
+
+ + + + + + +
+ + ballot + + +
+
+
+ +
+
    +
    +
  • สมัครสอบ On Counter
  • +
    +
    +
  • จัดการใบเสร็จ
  • +
    +
    +
  • สรุปยอดประจำคาบ
  • +
    +
    +
  • รายงานรับเงิน
  • +
    +
    +
  • รายงานรับเงิน TTB
  • +
    +
    +
  • รายงานรับเงินออนไลน์
  • +
    +
    +
  • ยกเลิกรายการสมัคร
  • +
    +
+
+
+
+
+
+ + + +
+ how_to_reg +
+
+ + + + + + +
+ + how_to_reg + + +
+
+
+ +
+
    +
    +
  • ข้อมูลผู้สอบ
  • +
    +
    +
  • ตรวจสอบข้อมูลผู้สมัคร
  • +
    +
    +
  • สร้างข้อสอบ
  • +
    +
    +
  • สถานะการชำระค่าสมัคร
  • +
    +
+
+
+
+
+
+ + +
+ living +
+
+ + + + + + +
+ + living + + +
+
+
+ +
+
    +
    +
  • ย้ายวันสอบ
  • +
    + + + +
    +
  • ย้ายห้องสอบ
  • +
    +
+
+
+
+
+
+ + + +
+ payment +
+
+ + + + + + +
+ + payment + + +
+
+
+ +
+
    +
    +
  • นำเข้ารายการชำระเงิน
  • +
    +
    +
  • ยืนยันรายการชำระเงิน
  • +
    +
+
+
+
+
+
+ + +
+ account_box +
+
+ + + + + + +
+ + account_box + + +
+
+
+ +
+
    + +
    +
  • กลุ่มสิทธิ์
  • +
    +
    +
  • สร้าง User
  • +
    +
    +
  • User ผู้ใช้งาน
  • +
    +
    +
  • User Counter รับสมัคร
  • +
    +
+
+
+
+
+
+
+ assessment + รายงาน +
+ +
+ settings +
+
+ + + + + + +
+ + settings + + +
+
+
+ +
+
    +
    +
  • รายการปฎิทิน
  • +
    +
    +
  • สร้างศูนย์สอบ
  • +
    +
    +
  • สร้างภาควิชา
  • +
    +
    +
  • จัดการสนามสอบ
  • +
    +
    +
  • ข้อมูลหน่วยงานคณะ
  • +
    +
    +
  • ข้อมูลระดับการศึกษา
  • +
    +
    +
  • ปีการศึกษา
  • +
    +
    +
  • ชื่อภาคการศึกษา
  • +
    +
    +
  • ประเภทวิชา
  • +
    +
    +
  • ชื่อเค้าเตอร์รับเงินออนไลน์
  • +
    +
    +
  • ลายเซ็นผู้รับเงิน
  • +
    +
    +
  • เวลายกเลิกรายการ
  • +
    +
    +
  • จัดการวิดีโอ
  • +
    +
+
+
+
+
+
+ + +
+ paid +
+
+ + + + + + +
+ + paid + + +
+
+
+ +
+
    +
    +
  • กำหนดค่าสอบ
  • +
    +
    +
  • บันทึกบัญชีค่าตอบแทนอาจารย์
  • +
    +
    +
  • ค่าคุมสอบ
  • +
    +
+
+
+
+
+
+ +
+ contact_mail + พิมพ์บัตรเข้าห้องสอบ +
+
+ schedule + ตั้งค่าเวลาพิมพ์บัตร +
+
+ ballot + พิมพ์ผลสอบ +
+ + + +
+ notifications + แจ้งเตือนการตรวจสอบ +
+ +
+
diff --git a/src/app/layout/menu/menu/menu.component.scss b/src/app/layout/menu/menu/menu.component.scss new file mode 100644 index 0000000..d19efe7 --- /dev/null +++ b/src/app/layout/menu/menu/menu.component.scss @@ -0,0 +1,76 @@ +.item { + @apply flex items-center justify-start border-b-2 text-2xl pl-3 cursor-pointer; + min-height: 60px; + mat-icon{ + @apply text-white mr-3; + } + span{ + @apply text-white; + } +} + +.logo_item{ + @apply h-20 flex items-center justify-center text-2xl cursor-pointer bg-gray-900; //relative + min-height: 60px; +} + +.menu_item{ + @apply flex items-center justify-start border-b-2 text-2xl pl-3 cursor-pointer; + min-height: 60px; + background: rgba(25, 195, 249, 0.8802); +} + +.dropdown{ + @apply flex items-center justify-start text-2xl cursor-pointer; + min-height: 46px; + background: rgba(25, 195, 249, 0.8802); +} + +*:focus { + outline: 0; +} + +.main_container{ + @apply min-h-screen flex flex-col; + box-shadow: 4px 0px 4px rgba(0, 0, 0, 0.25); + background: #576071; + height:100%; + min-height:100vh; +} + +.iconMenuName { + display: flex; + padding-top: 5px; + padding-bottom: 5px; + box-sizing: border-box; + align-items: center; + position: relative; + width: 100%; + color: white; +} + +.iconSize{ + padding-right: 12px; + margin-left: 12px +} + +.list_menu { + list-style: none; + padding: 0; + & > div > li { + outline: none; + padding: 10px; + padding-left: 10px; + margin-left: 20px; + cursor: pointer; + color: white; + } + & > div:hover:not(.menu_item) { + // background: rgba(0,0,0,.04); + width: 100%; + } +} + +.dropdown_menu{ + @apply border-b-2; +} diff --git a/src/app/layout/menu/menu/menu.component.spec.ts b/src/app/layout/menu/menu/menu.component.spec.ts new file mode 100644 index 0000000..b6ba4e5 --- /dev/null +++ b/src/app/layout/menu/menu/menu.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MenuComponent } from './menu.component'; + +describe('MenuComponent', () => { + let component: MenuComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MenuComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/layout/menu/menu/menu.component.ts b/src/app/layout/menu/menu/menu.component.ts new file mode 100644 index 0000000..679e00b --- /dev/null +++ b/src/app/layout/menu/menu/menu.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; +import { OBJECT } from 'src/app/core/enum/role'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; + +@Component({ + selector: 'app-menu', + templateUrl: './menu.component.html', + styleUrls: ['./menu.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class MenuComponent implements OnInit { + @Output() onToggleMenu = new EventEmitter() + isExpandMenu: boolean = true + role = [] + roleConfig = OBJECT + constructor( + private appTokenSV: AppTokenService + ) { } + + ngOnInit(): void { + this.handleResize() + this.role = this.appTokenSV.user.rights + } + + + handleResize() { + const current = window.innerWidth + if(current < 1024){ + this.isExpandMenu = false + this.onToggleMenu.emit(this.isExpandMenu) + } + const match = window.matchMedia('(min-width: 1024px)'); + match.addEventListener('change', (e) => { + this.isExpandMenu = e.matches; + this.onToggleMenu.emit(this.isExpandMenu) + }); + } + + toggleMenu(){ + this.isExpandMenu = !this.isExpandMenu + this.onToggleMenu.emit(this.isExpandMenu) + } + +} diff --git a/src/app/layout/toolbar/toolbar/toolbar.component.html b/src/app/layout/toolbar/toolbar/toolbar.component.html new file mode 100644 index 0000000..3037d09 --- /dev/null +++ b/src/app/layout/toolbar/toolbar/toolbar.component.html @@ -0,0 +1,22 @@ +
+
+
+   + {{name.menu}} + / {{name.sub_menu}} +
+
+
+ + person + + v. 15.4.5 +   + {{user?.display}} +   + + logout + +
+
+ diff --git a/src/app/layout/toolbar/toolbar/toolbar.component.scss b/src/app/layout/toolbar/toolbar/toolbar.component.scss new file mode 100644 index 0000000..0a37d19 --- /dev/null +++ b/src/app/layout/toolbar/toolbar/toolbar.component.scss @@ -0,0 +1,4 @@ +.toolbar{ + @apply h-20 bg-white border-b-2 justify-between items-center flex pr-3; + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.25); +} diff --git a/src/app/layout/toolbar/toolbar/toolbar.component.spec.ts b/src/app/layout/toolbar/toolbar/toolbar.component.spec.ts new file mode 100644 index 0000000..3acf866 --- /dev/null +++ b/src/app/layout/toolbar/toolbar/toolbar.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToolbarComponent } from './toolbar.component'; + +describe('ToolbarComponent', () => { + let component: ToolbarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ToolbarComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ToolbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/layout/toolbar/toolbar/toolbar.component.ts b/src/app/layout/toolbar/toolbar/toolbar.component.ts new file mode 100644 index 0000000..8a29793 --- /dev/null +++ b/src/app/layout/toolbar/toolbar/toolbar.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { filter, startWith, switchMap, tap } from 'rxjs/operators'; +import { OidcAuthService } from 'src/app/core/service/oidc/oidc.service'; +import { AppTokenService } from 'src/app/core/service/security/app-token.service'; + +@Component({ + selector: 'app-toolbar', + templateUrl: './toolbar.component.html', + styleUrls: ['./toolbar.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ToolbarComponent implements OnInit { + user; + name; + navigator$ = new Observable() + constructor( + private oidc: OidcAuthService, + private appTokenSV: AppTokenService, + private router: Router, + private activeRoute: ActivatedRoute, + ) { } + + ngOnInit(): void { + this.user = this.appTokenSV.user + this.navigator$ = this.router.events.pipe( + filter(r => r instanceof NavigationEnd), + startWith(this.router), + switchMap(r => this.activeRoute.firstChild.data), + ) + } + + logout(){ + this.oidc.logout() + } + + changePassword(){ + this.router.navigate(['change-password']) + } + +} diff --git a/src/app/shared/animations/animation.ts b/src/app/shared/animations/animation.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/components/README.md b/src/app/shared/components/README.md new file mode 100644 index 0000000..4b36b17 --- /dev/null +++ b/src/app/shared/components/README.md @@ -0,0 +1 @@ +create component \ No newline at end of file diff --git a/src/app/shared/directives/demo.directive.spec.ts b/src/app/shared/directives/demo.directive.spec.ts new file mode 100644 index 0000000..0bf8757 --- /dev/null +++ b/src/app/shared/directives/demo.directive.spec.ts @@ -0,0 +1,8 @@ +import { DemoDirective } from './demo.directive'; + +describe('DemoDirective', () => { + it('should create an instance', () => { + const directive = new DemoDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/src/app/shared/directives/demo.directive.ts b/src/app/shared/directives/demo.directive.ts new file mode 100644 index 0000000..8e6c57f --- /dev/null +++ b/src/app/shared/directives/demo.directive.ts @@ -0,0 +1,10 @@ +import { Directive } from '@angular/core'; + +@Directive({ + selector: '[appDemo]' +}) +export class DemoDirective { + + constructor() { } + +} diff --git a/src/app/shared/directives/email-input.directive.ts b/src/app/shared/directives/email-input.directive.ts new file mode 100644 index 0000000..630d14a --- /dev/null +++ b/src/app/shared/directives/email-input.directive.ts @@ -0,0 +1,29 @@ +import {Directive, ElementRef, HostListener, Input} from '@angular/core'; + +@Directive({ + selector: '[EmailInput]' +}) +export class EmailInputDirective { + regexStr = '^[a-zA-Z0-9@._%-]*$'; + @Input() isAlphaNumeric: boolean; + + constructor(private el: ElementRef) { } + + + @HostListener('keypress', ['$event']) onKeyPress(event) { + return new RegExp(this.regexStr).test(event.key); + } + + @HostListener('paste', ['$event']) blockPaste(event: KeyboardEvent) { + this.validateFields(event); + } + + validateFields(event) { + setTimeout(() => { + this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^A-Za-z ]/g, '').replace(/\s/g, ''); + event.preventDefault(); + + }, 100) + } + +} diff --git a/src/app/shared/directives/input.directive.ts b/src/app/shared/directives/input.directive.ts new file mode 100644 index 0000000..f02893f --- /dev/null +++ b/src/app/shared/directives/input.directive.ts @@ -0,0 +1,29 @@ +import { Directive, HostListener, ElementRef, Input } from '@angular/core'; +@Directive({ + selector: '[nospec]' +}) +export class SpecialCharacterDirective { + + regexStr = '^[a-zA-Z0-9_]*$'; + @Input() isAlphaNumeric: boolean; + + constructor(private el: ElementRef) { } + + + @HostListener('keypress', ['$event']) onKeyPress(event) { + return new RegExp(this.regexStr).test(event.key); + } + + @HostListener('paste', ['$event']) blockPaste(event: KeyboardEvent) { + this.validateFields(event); + } + + validateFields(event) { + setTimeout(() => { + this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^A-Za-z ]/g, '').replace(/\s/g, ''); + event.preventDefault(); + + }, 100) + } + +} diff --git a/src/app/shared/directives/limit-length.directive.ts b/src/app/shared/directives/limit-length.directive.ts new file mode 100644 index 0000000..d9f060d --- /dev/null +++ b/src/app/shared/directives/limit-length.directive.ts @@ -0,0 +1,22 @@ +import { Directive, Input, ElementRef, HostListener } from '@angular/core'; + +@Directive({ + selector: '[LimitLength]' +}) +export class LimitLengthDirective { + @Input() limitLength:number = 0 + private el:HTMLInputElement + constructor( + private elementRef :ElementRef, + // private controls:NgControl + ){ + this.el = this.elementRef.nativeElement; + } + + @HostListener('keypress',['$event']) type(value){ + if(value.target.value.length >= this.limitLength) { + // this.elementRef.nativeElement.value = '' + return false + } + } +} diff --git a/src/app/shared/directives/only-number.directive.ts b/src/app/shared/directives/only-number.directive.ts new file mode 100644 index 0000000..04c1ffc --- /dev/null +++ b/src/app/shared/directives/only-number.directive.ts @@ -0,0 +1,24 @@ + +import { Directive, HostListener, ElementRef } from '@angular/core'; + +@Directive({ + selector: '[OnlyNumber]' +}) +export class OnlyNumberDirective { + private el: HTMLInputElement; + constructor( + private elementRef: ElementRef + ) { + this.el = this.elementRef.nativeElement + } + + @HostListener('keypress',['$event']) + onTyping(event){ + // console.log(event) + if (event.charCode > 31 && (event.charCode < 48 || event.charCode > 57)) { + return false; + } + return true; + } + +} diff --git a/src/app/shared/models/user.ts b/src/app/shared/models/user.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/app/shared/pipes/checkFormcustom/check-form-exam-information-section.pipe.ts b/src/app/shared/pipes/checkFormcustom/check-form-exam-information-section.pipe.ts new file mode 100644 index 0000000..85c068b --- /dev/null +++ b/src/app/shared/pipes/checkFormcustom/check-form-exam-information-section.pipe.ts @@ -0,0 +1,19 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkFormExamInformationSection' +}) +export class CheckFormExamInformationSectionPipe implements PipeTransform { + + transform(array: any): unknown { + let isOK:any = false + // console.log(array) + // Some Method + const someResult = array.some((member) => { + return member.is_check === true + }) + isOK = !someResult; + return isOK + } + +} diff --git a/src/app/shared/pipes/checkseat/cheakseatall.pipe.ts b/src/app/shared/pipes/checkseat/cheakseatall.pipe.ts new file mode 100644 index 0000000..ccae5a6 --- /dev/null +++ b/src/app/shared/pipes/checkseat/cheakseatall.pipe.ts @@ -0,0 +1,39 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import {of} from 'rxjs'; + +@Pipe({ + name: 'cheakseatall' +}) +export class CheakseatallPipe implements PipeTransform { + + transform(array: any): unknown { + // if(!array) return false + let isOK:any = false; + let maxSeat = 0; + let Totalseat = 0; + const ArrayAllStartSeat = []; + const ArrayAllEndSeat = []; + for (let i = 0; i < array.length; i++) { + maxSeat = array[i].no_of_seats + if (array[i].testing_seat_subjects.length !== 0){ + const ArraySeat = array[i].testing_seat_subjects; + for (let j = 0; j < ArraySeat.length; j++) { + if (ArraySeat[j].start_seat_no !== null){ + ArrayAllStartSeat.push(ArraySeat[j].start_seat_no) + } + if (ArraySeat[j].end_seat_no !== null){ + ArrayAllEndSeat.push(ArraySeat[j].end_seat_no) + } + } + } + if (typeof (ArrayAllEndSeat[ArrayAllEndSeat.length - 1]) === 'number' && typeof (ArrayAllStartSeat[0]) === 'number'){ + Totalseat = ArrayAllEndSeat[ArrayAllEndSeat.length - 1] - ArrayAllStartSeat[0] + 1; + } + if (maxSeat < Totalseat) { + return isOK = true + } + } + return isOK + } + +} diff --git a/src/app/shared/pipes/checkseat/checkdupicateallseat.pipe.ts b/src/app/shared/pipes/checkseat/checkdupicateallseat.pipe.ts new file mode 100644 index 0000000..ca869e5 --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkdupicateallseat.pipe.ts @@ -0,0 +1,58 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkdupicateallseat' +}) +export class CheckdupicateallseatPipe implements PipeTransform { + + transform(arrs: any): unknown { + if(!arrs) return false + let isDucp = false + console.log('------START------') + console.log(arrs); + for (let i = 0; i < arrs.length; i++ ){ + console.log('INDEX: ',i); + const arr = arrs[i].testing_seat_subjects; + const ArrayStart = []; + const ArrayEnd = []; + const ArrayAllseat = []; + for (let j = 0; j < arr.length; j++ ){ + // console.log('arr: ',arr[j]); + + if (arr[j].start_seat_no !== null){ + ArrayStart.push(arr[j].start_seat_no); + ArrayAllseat.push(arr[j].start_seat_no); + } + if (arr[j].end_seat_no !== null){ + ArrayEnd.push(arr[j].end_seat_no); + ArrayAllseat.push(arr[j].end_seat_no); + } + + } + const checkUniqueArraystart = [...new Set(ArrayStart)]; + const checkUniqueArrayend = [...new Set(ArrayEnd)]; + const checkUniqueArrayAll = [...new Set(ArrayAllseat)]; + console.log('ArrayAllseat: ',ArrayAllseat) + console.log('checkUniqueArraystart: ',checkUniqueArraystart) + console.log('checkUniqueArrayend: ',checkUniqueArrayend) + console.log('checkUniqueArrayAll: ',checkUniqueArrayAll) + if (ArrayAllseat.length !== 0){ + if (checkUniqueArraystart.length !== 0 && checkUniqueArrayend.length !== 0 && checkUniqueArrayAll.length !== 0) { + if (ArrayAllseat.length !== 1){ + if (ArrayAllseat.length !== checkUniqueArrayAll.length){ + isDucp = true; + } + }else { + if(ArrayAllseat[0] === checkUniqueArraystart[0] || ArrayAllseat[0] === checkUniqueArrayend[0]){ + isDucp = true; + } + } + } + } + } + console.log('------END------') + return isDucp + + } + +} diff --git a/src/app/shared/pipes/checkseat/checkdupicateseat.pipe.ts b/src/app/shared/pipes/checkseat/checkdupicateseat.pipe.ts new file mode 100644 index 0000000..5569bda --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkdupicateseat.pipe.ts @@ -0,0 +1,48 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import {unwrapFirst} from 'codelyzer/util/function'; + +@Pipe({ + name: 'checkdupicateseat' +}) +export class CheckdupicateseatPipe implements PipeTransform { + + transform(arr: any): unknown { + if(!arr) return false + let isDucp = false + const ArrayStart = []; + const ArrayEnd = []; + const ArrayAllseat = []; + for (let i = 0; i < arr.length; i++ ){ + if (arr[i].start_seat_no !== null){ + ArrayStart.push(arr[i].start_seat_no); + ArrayAllseat.push(arr[i].start_seat_no); + } + if (arr[i].end_seat_no !== null){ + ArrayEnd.push(arr[i].end_seat_no); + ArrayAllseat.push(arr[i].end_seat_no); + } + } + // console.log(ArrayStart, 'ArrayStart'); + // console.log(ArrayEnd, 'ArrayEnd'); + // console.log(ArrayAllseat, 'ArrayAllseat'); + const checkUniqueArraystart = [...new Set(ArrayStart)]; + const checkUniqueArrayend = [...new Set(ArrayEnd)]; + const checkUniqueArrayAll = [...new Set(ArrayAllseat)]; + if (ArrayAllseat.length !== 0){ + + if (ArrayAllseat.length !== 1){ + if (ArrayAllseat.length !== checkUniqueArrayAll.length){ + isDucp = true; + } + }else { + // console.log(ArrayAllseat[0]) + // console.log(checkUniqueArrayAll[0]) + if(ArrayAllseat[0] === checkUniqueArrayend[0] || ArrayAllseat[0] === checkUniqueArrayend[0]){ + isDucp = true; + } + } + } + return isDucp + } + +} diff --git a/src/app/shared/pipes/checkseat/checkfield.pipe.ts b/src/app/shared/pipes/checkseat/checkfield.pipe.ts new file mode 100644 index 0000000..a78328b --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkfield.pipe.ts @@ -0,0 +1,25 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkfield' +}) +export class CheckfieldPipe implements PipeTransform { + + transform(arr: any): unknown { + const ArraySeat = arr.testing_seat_subjects; + if (!ArraySeat) return false; + let isField = false; + if (ArraySeat){ + for (let i = 0; i < ArraySeat.length; i++ ){ + if (ArraySeat[i].start_seat_no == null && ArraySeat[i].end_seat_no != null ){ + isField = true; + } + if (ArraySeat[i].start_seat_no != null && ArraySeat[i].end_seat_no == null ){ + isField = true; + } + } + } + return isField; + } + +} diff --git a/src/app/shared/pipes/checkseat/checkinrange.pipe.ts b/src/app/shared/pipes/checkseat/checkinrange.pipe.ts new file mode 100644 index 0000000..b89cc03 --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkinrange.pipe.ts @@ -0,0 +1,23 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkinrange' +}) +export class CheckinrangePipe implements PipeTransform { + + transform(AllSeat: any , StartSeatNo: any , EndSeatNo: any): any { + const ArrayAllSeat = AllSeat.testing_seat_subjects; + const StartNo = StartSeatNo; + const EndNo = EndSeatNo; + let isInRange = false; + for (let i = 0; i < ArrayAllSeat.length; i++ ){ + if (StartNo != null && ArrayAllSeat[i].start_seat_no !== null && ArrayAllSeat[i].end_seat_no != null){ + if (StartNo > ArrayAllSeat[i].start_seat_no && StartNo <= ArrayAllSeat[i].end_seat_no || EndNo >= ArrayAllSeat[i].start_seat_no && EndNo < ArrayAllSeat[i].start_seat_no) { + isInRange = true; + } + } + } + return isInRange; + } + +} diff --git a/src/app/shared/pipes/checkseat/checkinrangeallseat.pipe.ts b/src/app/shared/pipes/checkseat/checkinrangeallseat.pipe.ts new file mode 100644 index 0000000..9a0c942 --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkinrangeallseat.pipe.ts @@ -0,0 +1,56 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkinrangeallseat' +}) +export class CheckinrangeallseatPipe implements PipeTransform { + + transform(AllSeat: any): any { + const ArrayAllSeat = AllSeat; + if (!ArrayAllSeat) return false; + let isInRange = false; + if (ArrayAllSeat){ + for (let i = 0; i < ArrayAllSeat.length; i++ ){ + const ArraySeatlist = ArrayAllSeat[i].testing_seat_subjects + for (let j = 0; j < ArraySeatlist.length; j++ ){ + if (isInRange === false){ + isInRange = this.checkInrange(ArraySeatlist , ArraySeatlist[j].start_seat_no , ArraySeatlist[j].end_seat_no) + } + } + } + } + return isInRange; + } + + checkInrange(Array , Start , End ){ + const ArrayStart = Array.map(x => { + return x.start_seat_no; + }); + const ArrayEnd = Array.map(x => { + return x.end_seat_no; + }); + let isInRange = false; + // console.log(ArrayStart) + // console.log(ArrayEnd) + for (let i = 0; i < Array.length; i++ ){ + const StartNo = ArrayStart[i]; + const EndNo = ArrayEnd[i]; + for (let j = 0; j < Array.length; j++ ){ + // console.log('Start No: ', StartNo) + // console.log('End No: ', EndNo) + // console.log('start_seat_no: ', Array[j].start_seat_no) + // console.log('end_seat_no: ', Array[j].end_seat_no) + // console.log(StartNo > Array[i].start_seat_no && StartNo < Array[i].end_seat_no , 'Start Range') + // console.log(EndNo > Array[i].start_seat_no && EndNo < Array[i].start_seat_no , 'End Range') + if (isInRange === false){ + if (StartNo > Array[j].start_seat_no && StartNo <= Array[j].end_seat_no || EndNo > Array[j].start_seat_no && EndNo < Array[j].end_seat_no) { + isInRange = true; + } + } + } + } + // console.log(isInRange); + return isInRange + } + +} diff --git a/src/app/shared/pipes/checkseat/checklessmoreallseat.pipe.ts b/src/app/shared/pipes/checkseat/checklessmoreallseat.pipe.ts new file mode 100644 index 0000000..1a7dfcb --- /dev/null +++ b/src/app/shared/pipes/checkseat/checklessmoreallseat.pipe.ts @@ -0,0 +1,26 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checklessmoreallseat' +}) +export class ChecklessmoreallseatPipe implements PipeTransform { + + transform(array: any): unknown { + let isOK:any = false + if(array){ + for (let i = 0; i < array.length; i++) { + if (array[i].testing_seat_subjects.length !== 0){ + for (let j = 0; j < array[i].testing_seat_subjects.length; j++) { + if (array[i].testing_seat_subjects[j].start_seat_no !== null && array[i].testing_seat_subjects[j].end_seat_no !== null){ + if (array[i].testing_seat_subjects[j].start_seat_no > array[i].testing_seat_subjects[j].end_seat_no){ + isOK = true; + } + } + } + } + } + } + return isOK + } + +} diff --git a/src/app/shared/pipes/checkseat/checklessmoreseat.pipe.ts b/src/app/shared/pipes/checkseat/checklessmoreseat.pipe.ts new file mode 100644 index 0000000..96ed8cd --- /dev/null +++ b/src/app/shared/pipes/checkseat/checklessmoreseat.pipe.ts @@ -0,0 +1,19 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import {ignoreElements} from 'rxjs/operators'; + +@Pipe({ + name: 'checklessmoreseat' +}) +export class ChecklessmoreseatPipe implements PipeTransform { + + transform(array: any): unknown { + let isOK:any = false + if(array.start_seat_no != null && array.end_seat_no != null && array.start_seat_no !== 0 && array.end_seat_no !== 0){ + if (array.start_seat_no > array.end_seat_no){ + isOK = true + } + } + return isOK + } + +} diff --git a/src/app/shared/pipes/checkseat/checkmaxseat.pipe.ts b/src/app/shared/pipes/checkseat/checkmaxseat.pipe.ts new file mode 100644 index 0000000..673b229 --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkmaxseat.pipe.ts @@ -0,0 +1,30 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'checkmaxseat' +}) +export class CheckmaxseatPipe implements PipeTransform { + + transform(arr: any): unknown { + const ArraySeat = arr.testing_seat_subjects; + let maxSeat = null; + for (let i = 0; i < ArraySeat.length; i++ ){ + if(ArraySeat[i].start_seat_no > ArraySeat[i].end_seat_no){ + if (maxSeat < ArraySeat[i].start_seat_no){ + maxSeat = ArraySeat[i].start_seat_no; + } + }else if(ArraySeat[i].start_seat_no < ArraySeat[i].end_seat_no){ + if (maxSeat < ArraySeat[i].end_seat_no){ + maxSeat = ArraySeat[i].end_seat_no; + } + }else if(ArraySeat[i].start_seat_no === ArraySeat[i].end_seat_no){ + if (maxSeat < ArraySeat[i].start_seat_no ){ + maxSeat = ArraySeat[i].start_seat_no; + } + } + } + return maxSeat; + } + + +} diff --git a/src/app/shared/pipes/checkseat/checkseat.pipe.ts b/src/app/shared/pipes/checkseat/checkseat.pipe.ts new file mode 100644 index 0000000..8d42523 --- /dev/null +++ b/src/app/shared/pipes/checkseat/checkseat.pipe.ts @@ -0,0 +1,20 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import {data} from "autoprefixer"; + +@Pipe({ + name: 'checkseat' +}) +export class CheckseatPipe implements PipeTransform { + + transform(array: any): unknown { + if(!array) return 'ข้อมูลไม่ถูกต้อง ' + let sumSeat:any = 0 + for (let i = 0; i < array.length; i++) { + if(array[i].start_seat_no != null && array[i].end_seat_no != null && array[i].start_seat_no !== 0 && array[i].end_seat_no !== 0){ + sumSeat += array[i].end_seat_no - array[i].start_seat_no + 1; + } + } + return sumSeat + } + +} diff --git a/src/app/shared/pipes/demo.pipe.spec.ts b/src/app/shared/pipes/demo.pipe.spec.ts new file mode 100644 index 0000000..2257c99 --- /dev/null +++ b/src/app/shared/pipes/demo.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DemoPipe } from './demo.pipe'; + +describe('DemoPipe', () => { + it('create an instance', () => { + const pipe = new DemoPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/app/shared/pipes/demo.pipe.ts b/src/app/shared/pipes/demo.pipe.ts new file mode 100644 index 0000000..c78c2f1 --- /dev/null +++ b/src/app/shared/pipes/demo.pipe.ts @@ -0,0 +1,12 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'demo' +}) +export class DemoPipe implements PipeTransform { + + transform(value: unknown, ...args: unknown[]): unknown { + return null; + } + +} diff --git a/src/app/shared/pipes/getdata/get-data-id.pipe.ts b/src/app/shared/pipes/getdata/get-data-id.pipe.ts new file mode 100644 index 0000000..328b7cd --- /dev/null +++ b/src/app/shared/pipes/getdata/get-data-id.pipe.ts @@ -0,0 +1,31 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'getDataId', + pure: false +}) +export class GetDataIdPipe implements PipeTransform { + + defaultUID = null + transform(id: any, items: Array, keyArray: string, key: string, msg: any, defaultMsg?: string): any{ + // console.log(id) + // console.log(items) + if (id == this.defaultUID && defaultMsg != undefined) { + return msg + } else if (id != undefined) { + // console.log(items != undefined) + if(items != undefined){ + let index = items.findIndex(x => x[keyArray] == id) + if(index == -1){ + return msg + } else { + // console.log(index != -1 ? items[index][key] : msg) + return index != -1 ? items[index][key] : msg + } + } + } else { + return msg + } + } + +} diff --git a/src/app/shared/pipes/previewfile/preview-file.pipe.spec.ts b/src/app/shared/pipes/previewfile/preview-file.pipe.spec.ts new file mode 100644 index 0000000..2d63bea --- /dev/null +++ b/src/app/shared/pipes/previewfile/preview-file.pipe.spec.ts @@ -0,0 +1,9 @@ +import { PreviewFilePipe } from './preview-file.pipe'; + +describe('PreviewFilePipe', () => { + it('create an instance', () => { + // @ts-ignore + const pipe = new PreviewFilePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/app/shared/pipes/previewfile/preview-file.pipe.ts b/src/app/shared/pipes/previewfile/preview-file.pipe.ts new file mode 100644 index 0000000..3a3dabf --- /dev/null +++ b/src/app/shared/pipes/previewfile/preview-file.pipe.ts @@ -0,0 +1,15 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Pipe({ + name: 'safeUrl' +}) +export class PreviewFilePipe implements PipeTransform { + + constructor(private sanitizer: DomSanitizer){} + + transform(url: string) { + return this.sanitizer.bypassSecurityTrustResourceUrl(url); + } + +} diff --git a/src/app/shared/pipes/role/role.pipe.ts b/src/app/shared/pipes/role/role.pipe.ts new file mode 100644 index 0000000..30ba070 --- /dev/null +++ b/src/app/shared/pipes/role/role.pipe.ts @@ -0,0 +1,30 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Right } from 'src/app/core/service/security/app-token.service'; + +@Pipe({ + name: 'role', + pure: true +}) +export class RolePipePipe implements PipeTransform { + + transform(userPermission: Right[], actionveRouteRole: string): boolean { + + // return true + // if(DISABLED_ROLE.some(x => actionveRouteRole.toLowerCase().includes(x))) return true + // if(userPermission.length && actionveRouteRole) return userPermission.some(x => x.obj.includes(actionveRouteRole)) + if(!userPermission?.length && !actionveRouteRole) return false + if(userPermission?.length && actionveRouteRole) { + // console.log(actionveRouteRole) + // console.log(userPermission.some(x => x.obj.includes(actionveRouteRole))) + // console.log(userPermission.some(x => x.obj == actionveRouteRole)) + // return userPermission.some(x => x.obj.includes(actionveRouteRole)) + return userPermission.some(x => x.obj == actionveRouteRole) + } + // if(!actionveRouteRole.includes('-')) { + // let canAccess = userPermission.some(role => actionveRouteRole == role.obj.slice(0,2)) + // return canAccess + // } else { + // return userPermission.some(x => x.obj.includes(actionveRouteRole)) + // } + } +} diff --git a/src/app/shared/pipes/search-auto/search-auto.pipe.ts b/src/app/shared/pipes/search-auto/search-auto.pipe.ts new file mode 100644 index 0000000..b5307db --- /dev/null +++ b/src/app/shared/pipes/search-auto/search-auto.pipe.ts @@ -0,0 +1,23 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'searchAuto' +}) +export class SearchAutoPipe implements PipeTransform { + + transform(items: any[], searchText: string , text: any): any[] { + if (!items) return []; + if (!searchText) return items; + if (!text) return text; + text = text.toLowerCase() + searchText = searchText.toLowerCase(); + var menu = items.filter(it => { + // console.log(it); + return it[text].toLowerCase().includes(searchText); + }); + if (menu.length != 0) { + return menu + } + } + +} diff --git a/src/app/shared/pipes/search-auto/search-autov2.pipe.ts b/src/app/shared/pipes/search-auto/search-autov2.pipe.ts new file mode 100644 index 0000000..2958c41 --- /dev/null +++ b/src/app/shared/pipes/search-auto/search-autov2.pipe.ts @@ -0,0 +1,13 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'autocom' +}) +export class SearchAutoPipeV2 implements PipeTransform { + + transform(items: any[], searchText: string,key = 'display'): any[] { + if(!items) return + if (!searchText) return items; + return items.filter((item) => item[key].includes(searchText.toLowerCase()) || item[key].includes(searchText.toUpperCase())) +  } +} diff --git a/src/app/shared/pipes/thaidate/thaidate..ts b/src/app/shared/pipes/thaidate/thaidate..ts new file mode 100644 index 0000000..5caa701 --- /dev/null +++ b/src/app/shared/pipes/thaidate/thaidate..ts @@ -0,0 +1,28 @@ +import { Pipe, PipeTransform } from "@angular/core" + +// const config = { +// year: 'numberic', +// month: 'long', +// day: 'numeric', +// } + +@Pipe({ + name: 'thaidate', + pure: true +}) + +export class ThaidatePipe implements PipeTransform { + + transform(value: Date): unknown { + if(!value) return '-' + let date = new Date(value).toLocaleDateString('th-TH',{ + year: 'numeric', + month: 'short', + day: 'numeric', + }) + return date + } + + +} + diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts new file mode 100644 index 0000000..03311f3 --- /dev/null +++ b/src/app/shared/shared.module.ts @@ -0,0 +1,194 @@ +import { Injectable, LOCALE_ID, NgModule } from '@angular/core'; +import { CommonModule, registerLocaleData } from '@angular/common'; +import { DemoDirective } from './directives/demo.directive'; +import { DemoPipe } from './pipes/demo.pipe'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; +import { DateAdapter, MatNativeDateModule, MAT_DATE_FORMATS, NativeDateAdapter } from '@angular/material/core'; +import { MatButtonModule } from '@angular/material/button'; +import {MatSortModule} from '@angular/material/sort'; +import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; +import { MatCardModule } from '@angular/material/card'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatTableModule } from '@angular/material/table'; +import { MatIconModule } from '@angular/material/icon'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatCheckboxModule } from '@angular/material/checkbox' +import { MatStepperModule } from '@angular/material/stepper' +import { MatRadioModule } from '@angular/material/radio'; +import { MatSelectModule } from '@angular/material/select'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { MatMenuModule } from '@angular/material/menu' +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { EditorModule } from '@tinymce/tinymce-angular'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatTabsModule } from '@angular/material/tabs'; +import { SearchAutoPipe } from './pipes/search-auto/search-auto.pipe'; +import { ThaidatePipe } from './pipes/thaidate/thaidate.'; +import { SearchAutoPipeV2 } from './pipes/search-auto/search-autov2.pipe'; +import { SpecialCharacterDirective } from './directives/input.directive'; +import { RolePipePipe } from './pipes/role/role.pipe'; +import { PreviewFilePipe } from './pipes/previewfile/preview-file.pipe'; +import localeTh from '@angular/common/locales/th'; +import { GetDataIdPipe } from './pipes/getdata/get-data-id.pipe'; +import { CheckseatPipe } from './pipes/checkseat/checkseat.pipe'; +import {MatSlideToggleModule} from '@angular/material/slide-toggle'; +import { OnlyNumberDirective } from './directives/only-number.directive'; +import { LimitLengthDirective } from './directives/limit-length.directive'; +import { CheckdupicateseatPipe } from './pipes/checkseat/checkdupicateseat.pipe'; +import { ChecklessmoreseatPipe } from './pipes/checkseat/checklessmoreseat.pipe'; +import { ChecklessmoreallseatPipe } from './pipes/checkseat/checklessmoreallseat.pipe'; +import { CheakseatallPipe } from './pipes/checkseat/cheakseatall.pipe'; +import { CheckFormExamInformationSectionPipe } from './pipes/checkFormcustom/check-form-exam-information-section.pipe'; +import { CheckfieldPipe } from './pipes/checkseat/checkfield.pipe'; +import { CheckmaxseatPipe } from './pipes/checkseat/checkmaxseat.pipe'; +import { CheckinrangePipe } from './pipes/checkseat/checkinrange.pipe'; +import { CheckinrangeallseatPipe } from './pipes/checkseat/checkinrangeallseat.pipe'; +import { EmailInputDirective } from './directives/email-input.directive'; +import { CheckdupicateallseatPipe } from './pipes/checkseat/checkdupicateallseat.pipe'; + +registerLocaleData(localeTh) +@Injectable() +export class AppDateAdapter extends NativeDateAdapter { + format(date: Date, displayFormat: Object): string { + let monthNamesThai = ["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.", + "ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค"]; + date.setHours(7); + let day: string = date.getDate().toLocaleString(); + day = +day < 10 ? '0' + day : day; + let year = date.getFullYear(); + let thaidate = `${day}/${monthNamesThai[date.getMonth()]}/${year + 543}`; + return thaidate; + } +} + +export const PICK_FORMATS = { + parse: { + dateInput: { + month: 'short', + year: 'numeric', + day: 'numeric' + } + }, + display: { + dateInput: 'input', + monthYearLabel: {day: 'numeric', year: 'numeric', month: 'long'}, + dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric'}, + monthYearA11yLabel: {year: 'numeric', month: 'long'} + } +}; + +export const MY_FORMATS = { + parse: { + dateInput: 'DD-MMM-YYYY', + }, + display: { + dateInput: 'DD-MMM-YYYY', + monthYearLabel: 'DD-MMM-YYYY', + dateA11yLabel: 'DD-MMM-YYYY', + monthYearA11yLabel: 'DD-MMM-YYYY', + }, +}; + + +const ext = [ + EditorModule +] +const mat = [ + MatSortModule, + CommonModule, + ReactiveFormsModule, + FormsModule, + MatButtonModule, + MatToolbarModule, + MatCardModule, + MatFormFieldModule, + MatInputModule, + MatGridListModule, + MatTableModule, + MatIconModule, + MatChipsModule, + MatCheckboxModule, + MatStepperModule, + MatRadioModule, + MatSelectModule, + MatDatepickerModule, + MatAutocompleteModule, + MatSnackBarModule, + MatMenuModule, + MatSlideToggleModule, + MatNativeDateModule, + MatProgressBarModule, + MatExpansionModule, + MatPaginatorModule, + MatTabsModule, + MatProgressSpinnerModule +] + +const pipe = [ + ThaidatePipe, + SearchAutoPipe, + SearchAutoPipeV2, + RolePipePipe, + PreviewFilePipe, + GetDataIdPipe +] + +const directive = [ + SpecialCharacterDirective, + OnlyNumberDirective, + LimitLengthDirective +] + +@NgModule({ + declarations: [ + DemoDirective, + DemoPipe, + ...pipe, + ...directive, + CheckseatPipe, + CheckdupicateseatPipe, + ChecklessmoreseatPipe, + ChecklessmoreallseatPipe, + CheakseatallPipe, + CheckFormExamInformationSectionPipe, + CheckfieldPipe, + CheckmaxseatPipe, + CheckinrangePipe, + CheckinrangeallseatPipe, + EmailInputDirective, + CheckdupicateallseatPipe, + ], + imports: [ + ...mat, + ...ext + ], + exports: [ + ...mat, + ...ext, + ...pipe, + ...directive, + CheckseatPipe, + CheckdupicateseatPipe, + ChecklessmoreseatPipe, + ChecklessmoreallseatPipe, + CheakseatallPipe, + CheckFormExamInformationSectionPipe, + CheckfieldPipe, + CheckmaxseatPipe, + CheckinrangePipe, + CheckinrangeallseatPipe, + CheckdupicateallseatPipe, + ], + providers: [ + { provide: LOCALE_ID, useValue: 'th-TH'}, + { provide: DateAdapter, useClass: AppDateAdapter}, + { provide: MAT_DATE_FORMATS, useValue: PICK_FORMATS}, + ] +}) +export class SharedModule { } diff --git a/src/app/shared/util/func.ts b/src/app/shared/util/func.ts new file mode 100644 index 0000000..15433ca --- /dev/null +++ b/src/app/shared/util/func.ts @@ -0,0 +1,31 @@ +export const createQueryStringFromObject = (object: any):string => { + let queryStr: string = '' + + for (const key in object) { + if (object[key] != null) { + queryStr += `${key}=${object[key]}&` + } + } + let lastIndex = queryStr.lastIndexOf('&') + queryStr = queryStr.slice(0,lastIndex) + return queryStr +} + +// export const makeRandom(lengthOfCode: number) => { +// let text = ""; +// let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890,./;'[]\=-)(*&^%$#@!~`" +// for (let i = 0; i < lengthOfCode; i++) { +// text += possible.charAt(Math.floor(Math.random() * possible.length)); +// } +// return text; +// } + +export function makeRandom(){ + let text = ""; + let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + for (let i = 0; i < 5; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} + diff --git a/src/app/shared/validator/real-citizen-id.validator.ts b/src/app/shared/validator/real-citizen-id.validator.ts new file mode 100644 index 0000000..7c1c1e4 --- /dev/null +++ b/src/app/shared/validator/real-citizen-id.validator.ts @@ -0,0 +1,43 @@ +import { AbstractControl } from '@angular/forms'; + +export function realCitizenIdValidator(control: AbstractControl): { [key: string]: boolean } | null { + console.log(control.value); + if (control.value !== null){ + if (control.value.length < 13 ) { + return { 'minLength': true }; + } + + // if (control.value.length == 10) { + // return null + // } + + if (control.value.length > 13) { + return { 'maxLength': true }; + } + + if (control.value.length == 13) { + let citizenId = control.value as string + let reOrderIndex = citizenId.split('').map((value, index) => { return [13 - index,(13 - index) * +value]}).map(vale => vale[1]) + let index13 = reOrderIndex.splice(12,1) + let totalCal = reOrderIndex.reduce((acc,cur) => acc + cur,0) + let fraction = totalCal % 11 + let conditionNumber = 11 - fraction + if (conditionNumber > 9) { + let firstDigi = conditionNumber.toString().split('')[1] + if (+firstDigi == index13[0]) { + return null; + } + } + + if (conditionNumber === index13[0]) { + // console.log('1digi') + return null; + } + + if (conditionNumber !== index13[0]) { + return { 'notReal': true } + } + } + } + return null +} diff --git a/src/app/state/app-reducer.ts b/src/app/state/app-reducer.ts new file mode 100644 index 0000000..44116d5 --- /dev/null +++ b/src/app/state/app-reducer.ts @@ -0,0 +1,9 @@ +import { ActionReducerMap } from '@ngrx/store'; + +export interface AppState { + // new state +} + +export const appReducers: ActionReducerMap = { + // handle new state +} diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/images/preview.png b/src/assets/images/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..36ac46ed7f8f17041cffc9129cc259964aff7d45 GIT binary patch literal 7276 zcmc(DXHXPfwCykqI7k|T12l;5Tr+%weqLX~5ZoRl;U&Q~UACtz(? zCdgNSCGpNcpTqO}(qX#0(Iv}s3Y2^;yq`9WK}NcL=2ZPZsR?<%wis$sri!xQm<4YH z9tV5>?zA7hE?&q8JitNJM)AE{&oc(C#~c@Wu5^z);wgRcT?d6rtDM6bBX7RUS%BY@E(+BD&W@djHiY3eaL zvq)#*LYFj^kTkx%#`5Y@L{9dQ_E9If%sf1n^rpY`MAgd{_vmG2B&&Me{ev+IPI>O*@a%QZ ztDC4A%MW-j^;bcO2oX*vI8_InU6)q!%oMI3XK-|){3mQJ#o054olCzc(FE$%^T3NR zdeQdcsI1;!n`t3SCFGf0GIeI&3B|*q)r2^`%kYP|S}0;9h+@b})Ru_ z@q%U<%rgW5FBc{gVU+iC$$Fiiaf3o-*+HMXeYO6K8j(4PnHcliCJqO+L%h4x8jS%gQs;!za)Bzx6|2!~l*m08}-2S!%6T{nr)jzBtIsn3M896RsB zhx}wJr#!|FX>7FCFR!k-gVmTvL<2p3DP8Rzd>)IkUQhfugWLuA;Y%iD_tMo!boC`z zoz5uiMuSQBE4gl3ox6-pJ7s2*luq8aqq)k53P+0Oih4I{y#zIco@#g=&b()zEd2Ds zis?OGCkdESX~di9tBXEM(Ys6oJE>= zH|hR(zTog_K55sic8=-Cs+5%&LYxkcCo9i|BbFYiTHagp#LMX-g`hQs$oo)`Brqr9 zAkrgOwVP51cLc9LkCGp^yj!B0zy(jTo2i<43a#kDkcCg(W$VGX5ZPMH*ak6MmfBQ+ zMMR9lBwj|RvtXmyR%86xaFn^pBl}o*l62cS&q@&X z^NE~N-`3JG5Z3Y5Bh*pVqbPq+mRh=}Em`KLu$N){&?weL?TlkE>0;e+y=dKa9sdu9 zmt^yYPii$q=Q`xvMk&oHUMj>Jlp9PN6)i0-ku8ar4!-X$8BV=UgSYK}FqefEZfi1@ zxNM7+Wwk`KgwM&hs|BkTOt?76*6A8Exe`>w_=TOJum!Ty9@u4v!>4x6x(-uLrW5`} z&#`q_8%OnV{&D`vXL+xm*XqP#Yzz9at4`m(myJtce09oAGApG_B^4zN0&C6$_q^xE ze3d0cB=RMKvRSh$B)EK-CLgtMWUKw2_&w1$p)oP<`?jT_g<+9@QF~FUMWDqjKq6p2 z;CX<~Depr~LEl9u?6(L{sJEs!Ehg?Ph5Fz_2usbE)zix@ z-CT12Sd~~cta$ZG^j;}8y$hdkDBw|~k5{MlC7EDc6^#%rv>Cc(c@?K+eQ!-{ZEL_J z{vq9~%=C{DnaVG)AG3tEp4g`2XV_&_K9+Ktvr-f#6r#wecr0mm7FIfF^T<1WW90pa zpttog)VukD>X_=-oX{jzJ{B3bX!^SHLFM#VNM1(^&Zm^Y`UJtu!RpGIv%wUYa>rD)>0)@73+z z@AVIRjl%~Q(0Q^jvU$a4XN`xyFWrya2`%vp@mxq82%nIy+sh;8}Q3V() zD_fenVaH5hJV0y-?`b*0Yw-^8s~yqooWh~2$v&gylR=s zWfDVj8*8)cNcAJ(K~v>NDr7}d#mU<5wHu555{VgG16;1e5Lb=JW~?WXTC&IXHr5fAkK;Wg<+8tdCPyZZk93ofq?#ML{{6HQUqIEr-RopBB`mEpCNm;GL|U_A1{~aCPd7V~WkQ zehIlw)Y;=%;dQDH79am3Iwq9+=+!`P1}4MAj-~dy{nN3AEVC!A!RqH(+1@QZtXhk&Zo2RBniQ%-X~>(|SFvia%^C^7zRUQ=J^^hWeJ%70em zG+mlz1kV2RH09}^r>+}X8>h|{SV5Dk*V!J6r!mVh?K|<)4~_4va6@}j<7MfcMKWA? z7f&2(9gZsmR!p4uTzQ8Z$QysT2e$|~&SzM(hgQtF)wTOvePCQ=bd_B5%fb99E1R=z zb9Q`cEKs#SBjxsYLy9GE+d0drVb^w7VDaABm%r`j0(*`0S8RVpnGdBky~i(?FXc|; zIO>)6>gFmXtjtV;Rf2a`-bH27U(=D?>|b9cC>{^QumvckF%>ZgNX)&$EE~RhUs!tV z|LbV*8%5?p4vqKf+?NS16Lp0gi9m_nlefYc;la_%T-Rs61NRSK9~}EqKYKW3e$wQ> zNt!4_Qt#g|W&Wo{H+1&5m)uS?w!i>f#n4ITb$ar2w4QLfpsMkwa+~MQucl1b#`DIU zrP1b_OZD6ApRL~eWc#TL(=8TfUFWhJxo4sKuE#Ete}vXo`jw6n_oaVHg7AP}klb9q@^f1JHV3vK#A zs=*^=%T7e9QP_1@{x!_7TTdT$upILMQU&@PCdSugB)j_{oiXWIlh7eZbv(E$q^nD6 zFWEHalZ4vLmeCe;W4p_baWZ+iGf#umjJcr7E4;8k{T#6hJtkU`SYJj@Bda zV;r!o;&2!AoB|HJK8=eZOCo?l9~{we8_>8=6@4Po}SZ}>FMe0*4Ebj-ripQ*2UYJDG7t>%GENqYI=Qr!VzA1Bcb9c8mI5_xQ9@lAZTcA5{YG&rk%*-6x z@YjF}KU=6OQnqX>qxfT2yepLy%w@L=}pbGxrgRDk%a?b%xUL6Oc}1P!G79iFUc z*Q|TYAzBmyQ|3=Pg|1v*x79W@_&p{H>$@8Dfx?A2llJ_t|NQy$;q>%WxV%_WpTdF_ zh2TWjTdzVL*y~wIKqh%NWRXR@XCVF z8Q|}T>dxoOn4T9Q`|^4GI7aXY8T)!+LKE9P!5?r`*S|BAhmCu+XPJPvWf~4Y4njULB#OUYXWCTse+(aQkGq6v-K1c$vGFPV?x{Z|*p-TZ{ zbunRfsj$~QFqD!H{`#oraPURL;EG1JbtmHt-)%>{6!#hn46=K5rUgI3cG#0b)>Pi4 zFt8}|+G;{zNrW({*Go=BS0cdqVgub6lqtY@3Sk^@2tZqz_D|Z7b%66(=>)JtHh}Y6 z4^mm-)Nt5(-wPCq8Q{D|RS6|dGr)N+J22!L3WJ6OC=@}5@SqU!M-=d7C4lpje7p(> zL4fmbGe9^pK(t(QEgrBJu>I6WAkcF%VEdiKsF3|HLP7gp5CQ9(9q`<3NTdx`-B)qU)I&ZQrN8%AyU3XTNiAo6L17i@?J0bif8cZ1vqq~pFbbOWBG zgF+0Ijx9hb0b!uT!oJGFi$Ullo!n+JZa{&!F)S(J2z4AVOR=;!n`Sx)t!XI7eGi=l zyj4B;mtvj}4miL1jV1|L91j}te+IOypzpmc{7MT>xg~Lpl-sT4t|lKHQO=(#RDt!RRIAkfZLar9>*T|l(lcP1i>o6 zrz{rq`bEer~%>y!((h?Vs0=U<0)XPncQv^ciP1(9YvVhc$(kV7WxdB%FKSB{7mXeV< zFf}*NS;wH8>j4nhSEY&;CMH*tekJz#hx6KdG?K?=D8#vXH&-pBva&K^_qM%TB+9RD zJiA`%?*)J|=uE)zhoAg-?VXnYGYLmAW2gp;qWhZn9T4q~N#!s6dVKzlE9->P%K4BI zDIpVH`~VL79?<%6Z+DmfdOWncAiRPn@}MS1NMT^>8zgLUpolxr+M11l*5}uVufv_< z&5tbCrunx(?h3U^hZ*=;&&o!eHF(qwHA-0ZZbcx-3n>-zd@14?dJFk19mo!WH>zzx z4er0C`$^(n=T`42zV8z7ET8`J83c(|`(pHcc|^9@iWtN7B!X|l3WDUx=FUr~iA|)_ z>kB}#HN0e!hqF54TS2`K6`VJN2>)FxN0+Drx66)kxTOMXu2ncc{>TjOY{rUe%?6`cT9t(s*zXy8ZV*bd>;V6FYQ_uf|URBkc4gv9swsagKx^U40EtvHh`cN%x-4#2hm<-`g_%S zz>&jBcH5B9=c_{FM`wD%7~O#L#?uJ$ss)Vh4Y|8KoPT^_h|p&xYF%!3DT{bogi5pY zdc1IlE4AGCh?pSa%@XJnUW>au6J6R#Rg^$e!%@`{M6@~wjxe)P2Ir%5{LzA6Rf6K` zQIV_3=vepyphJx3_sY4BxF4{@z;pR z@qVd26EfcK;uvYqVKIekuZnVO?rw zwe*&4HAWNpwubmtJ?3S9Nh}4qNFsu!S3US>V&){ZvreI};w!!6QqpOJ4>3DT5hFm< zau)9Q%!?v7jioC9`AHfE#oeq%*jsrd4`n-U6ISPFE@95tpb#9bDWl5t|e>UB9 zn*iejClZvFs8kxj0%9+7em}Ie+r$Q)N*vMiP&#JeR}n+PDMZ%9Km^8M8pQ7K*NgZ| z0P;Gd(gyC|e9j%x`oT>eOTpUcvjIlOCbEX!+h9&Ojfj>qEJZA@7DO+J+Y{XpB6vZ z7$^ig!<*11ayZPiKK3QqI8X?TEfkfyQUNh5Goy?}>7x+imyadDl|Ugd*!yG%sry%h zKTME$a3J7KPSpLZd4O8hb;Kp0_<%y7*UC+WQvno$Q(GU1DNqP1=M-w74nQHOcv!&p zKSFVT`1z9g$|BB~Oi{@)60Z#pITrBX=W96-4jQ%2BUk>Tg>33;610iJ-{1c{xA+qW z`tWpTnqC7s6@yag3K2ikv*sH}g&@zPxPQVao8sPf-Q3(*edeEM)%mx}}xy!wRDkd@SR48dpKru32Z|~`@ZQgPaM1X8Q z2)C+z(-M+avit~yyS`oRk6m;88`#vI`gtfeHr85FTTDfq%bO)hdAVwDZ|_Fl`^!Ji zy&{A#(uMY7g>)g`lptxcT_IoETie@j9C?7hvg$MMddmG;gI}&xr&@>nl82`u{6AU} z{*I~{7?x81UQARV85k1svqtmWa%+yZJ$sDIgLS;o!r`9Z)Ya(o_SCNCm+W$S!!FkzU?Zpm`|@5z{Bmso-b zt9&XVGf88pGm*@k>*C5@kUYE|b#oX+eJNg_cpwvc8`Kh~1X=s1AFszBea1T+=w~&V zhS!(I@gz2B4H3j>vTWz-TH$U_?558Gdb#$92@Hj!K>zg_d3L*g_002Odln_w_0AOJO0EiWM@EtIAaRCAV zkS)!Hh2d7|iXv`g@k zWO@Cm=*q`oUw^KMV$-$J<{xMRG?e>waR=7%kZ4ES)a9|0ILIM%ymvkKAND4ECo}Kl zTHoKSLkQM~(#7xOY65m5E(`59d%m;0E0vj1@&i!hLKyw**&U&(SXz1uFv)!>`PKzd znWycnX!peXtS1`E6n72~92Cl&NI7>Pw}AxcO(sZO0?258Co5f0A@af*>byfn-%>%$ zEbZsP;nWEye6YscT0+-@6^tI;m3j{`)dF|*-Anh)&h#yEZDcAFCR8pL_7)&JZY)$C z<6&xbRT5DfwU)RcMG$!#V*PN#-t;+8z&kEyY@Dcn^xM5Cg9uf^j$O%9PSM@QmkdhM zUj|TwDsQ91ly=Z8-RL|O3n7)rPq9nHhu&JC*vE!dSMUJdioT7NP+ln*n`9AZHKZl*z;*E}AL%9M;Q;-Zvlc31`Ol=e7&&v~EwB<{QZKwR0D(25jj&F$AuX>kXXcqQ?%q7`mNW9ES3>$uV8j4-f zJ(I$RE^Hfm>z6*YKynT_N~F?q%FZb4#Q-~!Xr>v?dJc_DnEV19&&c-m5Sn8TBT|1w zKLm-tmCT$VqnD7xS60{KR>4eQ_10nh4$RQI{Vi9^FEynAnBzX>{WTi1Ev#;Phbg0fa$-H*tN*sBiq~$t(^lKtZmf@yy*Yig5_g z-I7K4sqw1<6d{Xl@_^?634n3nWx#_t3>oQB7qUf?8cp1^K>CINB_VGxC!R5PD`-VVLQvhOvR-;`^n) zN?Ipun(0pnL9t9J0~%lLBso!P6UKQ)V#b^#Blmz(_lW4BY^t<3I3|dfsr0wb=*(P( z*_ZOg<&oudfC$^@i>s^T=@%3s;C|O3;s(Ue$ukhh^07EF!1L*+SIbk5&+IZua5aKA zU?TZqXU3}tRZScI7egL`YdSeIOma8s-ZmnyKPfz9o<3C=1Oge1jGqc_uQMZzQa3U) z9(JH&4RQr6sQXO~&M~xSw~ss=L65y1fi@te$Jq|AD%<53rj!3oE}jrN=11X!Fml5X zb;_79x~*tvvOEcF%+NwIbBQ+;Vmrgg#w3an6@m-oT5+^H96QVoL|mZ_6wUFW5^xu= zcR_}4appy3u5N^?|vzdpy82|MT3m2Q7^IKn(a zwZOV!zha0MtIva(Ry22Spl+aDL0Ey(jD^+d(+Di+Sxl`|$Wth{7u`;JqcN+QP{buv zFIX>g>9s8`@C`V!cK9!Lh|FBIOR8wi5UK~4+F3t0{s zLjfV55pIg1iWNi`1FhM(P3E{nT*Efd*WATUlhX&e3h)jSk`jlNsPxM}n_bs4FcBw^sYLGpV!*7onwm3t>Z4`uAV2S2aI+b2R>tgr!1pJ{^IpRcydf~ zrJtieho&T{r7wC^XRNoa*RDr)Ox~k=1$di2u-$w8zWP0Wxpwx@oRgr}w87Z5PiZ9% zFJ?t}zO>Ps1L_*+V(`O{!>!@UWtifPBUHz~eLKt=M%uu4fIpUZ9gI=Z{#zi^2Tx_3&fJ<)|RU8~7ZOb!?%quqbsB`vjxjP5UxV z9m)=|2_kpaF9i6ct&A56iNc9&Wd_*X7CT>)3Qk3}#3KtphJwg6rY7H?)PF3E)ON+b ziHRZBVYxS7{ndhR|9R{19BbQkpi2(^lX|)x$26lt_EKhH8XIFN?V+%P#6`qT6HDLV zcOpmffw!WGiaAnJvQlf=D}3xu$49j%+q{D~vF$ADE{}8P`)`1*=bZSSAk4~B2KkUu9k96R<^SbMM^m~kW%zh`Sgeo(iO`GjupWfFXI-89Xg!9Nv zoHLQJ&fDiTxQdVVxz5xkE%>`s&OGlA2bbyNYpzX4mx-e9wJrYLc-azc9Sm zkR+b8Sly`EZgsNn-0QqZ7eIGi#i83}_7sZph@!?0YhAHyTvzHeTQZ(M-rN*qTUyyr zO8-M@HNETVu&L1cv(MFYqec7l^~{N$OPFiJNz@Pby3z77iiqg9?>W7_l_$Xa%sIEUtmrucQhYMW z8AGY0)Qr_d_~!6vF+4xJ$hpX<9oxC?L3ut{nXzrtw6?Y3;ls0k4dS_T^*Ebo6>m{< z&;$7_Lv6z)`L4XQHjmez4EM!_;*kyrv^}KW-0os6CrqA*%9+cJWvB6#dz{{XtEH^i zzKE=4TG5lzy>`KUDSBGGS97UGeJ1{WGf>5%b5dPY{jg5&V|nW`#B<|1zE-=2w!Yta z_9Q=Jv{Zjta5MBi=ZgRzDC;8ack5&1Q%Xp6yx!T>?)8;qi=xd-H2{_{JszSvgBUQS z2*~YoBs8hGpkHDNyLeoQ?e^^*y)^7{gOrEj8L;JTNAUBmS^n<7Dg=1zvxyY|IND=h zQl=QQb5wCq*pv*Lnq9nEfCeZ+0rU#Jy*mi+?>nsmd)8rd&Fe0Z%g`x!-&>)|=Yn9( z1+qGl_Gix=9&6zu;8%NMpSl3Qd}CQN+&$yKvyTW9bxBiMSpY3K4-bHbAOOICa}eN* zAA<1Tc`=B$0H}X_hXepZ%>mH=g82k~zW!b@z1I2X6Y5I{01o_y3BKHNA^!^+7B&~^ zzw!_(;4*-alCY#C_^D*%U}9q9XlCowu7@%L{(xX7q2UMs;8MR{5R!^izrgqx&6U-i z)MaJ3jclzM4UBCKO&Hy*?OyQ!c-^?cS!)v~12Q*jD;q~{H$IAgKyZWeub-JH$o>K1 zWXVUNE-OzaZ0le`#?Hvh$V|bHNJd7+>tJlkttcY)uj=48J_<7@Cp&H?CRbNiM%VX@ zwho_}Sh%>jn3!3aSXmjs5Dbp)Hckd^3^tCG|3va%ctlJbjU3GFoXl-)$X@Xp7}`2J z@ljB`68iV=pY1epGye}I8^?cj3*14b*AgZcMrNje;|5pdef`QUZ|-Jdr6FQ&4dxk` z20t4I8}C2h|34-Fq4i?<9@_~)@k5&Ir^xvzhIGQ*J+ggKZI`RKUUjM56$HISA zASu@E#=69ZOmC63Dw`V_@ac62I0uP794Dq+gUsfpBps&05?dQ)k&@$bB zm%jL+KvluN(TDuIR1*%r#9R}O_(S8v-xG!)gw=-odxA3hSQs@1`dBzk^%j3iR3DNZ zxdk=V58>}p_ZtfRzV0`)R-fnpu9x5@Spn^c|5vt&bcguMDlbix{Vh>HgeB&m+<(t9 zeaMV3Fl#fu)?}&tt*juhY7Dxa|5ire*0W=PS<9|qz*GKra(Zo2pC9P&S>}geMFD25 zRerCFs_g$lHw0qwe-Sv=k_ec!OCrH173u#AU9h4-{V%QmKSld*%Km?f_U|$Ke~R|s z4D0_{w0{ql|GzDosxc54EtUZv{ZAj25h_?Py~La5{OPX^rhWq0i0db)0X}cMdLghE zfmnq4YpcJ+`)V$EO-?dj&1JU<*p=96u&w_O&V(=q>_Z5vB(lg~v8i)`oq+1ZckzGs z`%jr}4{ES4^kCpB`SIF{DoQYP6{U>0$zQu!%S~;m zdHa9xgqso!%}vKlv-sE0x=`Sb=|b_6{v&=M41Q%%5mgr2UpKsk`;`q7!=C?WcL)s_ zcLQuTj%2VD<`<*^(sj(lT)Hs9(0So@((^-?N1{4 zH*>l}UKtX?p!xaxE8%20aGyDeXP>eIk#b`_uv=nQt(w+T@_wu`5wvRptPhdv&DzX;|uSzXq7wNu`d)ubNNyrlu_f0wKV=Sg6=C2$|l#<_nfa zi3tLWNput>i-j1JGnZ&4uLX?nQCLboJ@@4Ng5D7}U9^$c3kYMQXbY&v;nTTGA4{sm z#I)aX?tQe)_?|TX;zlj^H{B7tud3a!$;9zIM|Sty5U48as>N?Hgx}vu$+^HUW4{Yxiv3#By-{zU6?Q&7V9avNAC8CPH&&N^|r@?7pX6bvfvjPWU1Te zhElY~xXRa3So#2SRtiz26AVVaXLYLZQOwsUV)azwjTHlhto>hyu5_Ny-v>5X&O{NE zkMz8%kH|~eGXsB!6bIyy$vVS(mF;4X*;kwPiS@*-3&}qUMm6bGF(Ve^|1nrr z(N?j_eYFZ7;>;7V76GwK-R6ZyQouIL9|pEM&#Q&wG1*M~r-h@exexKbBrwX}r+7V4;;=$P8ZcD}G~U&L;a`5jFQ$+=D}=b)08^?50gG4QR$ zFE^s?vF&{!JLx_@&0X#a8c1Pe$V-+;FYeqfLCOc@L?0-33?rhM>N?XPGP>mtd}eyL-cHb3q}txT#kbaS6_OB&8i0iojKHro3N0LfuH-%oh%;WfS_V@9xOVHfoVCgT9&g!^M6OKZt4>;NG# z(HtY$&0+`46QR;A)?o5h_!bw&(qltCIu@dt79XOjwGJJKhi<)!?4!=~hTeCcHqz_G z-X3ud?vF`gJxD(iGhbBf?f0ocQ_o3jtUQ`g66~K|p=MVjLAF)xm-kw+q$uQ;ZnPDf z0Od;+oA7A^y8&AMn%0)(fe5Q+kmCmih^exHf>1XmTqxz8P%25XYA!%HV-b0?5N(9k zA;I2Xq!G!0PML0-Jiw58Zbw@qVNjheVtWkFw4MJG2(;_L|Js-8f!hVabTJ?dEOrhesJ9bJ zbBz@Fkh~kvNRLKMMTyy5zQHY(N0MOJ2r}Wyc+sVUP-*7(HQpwyo3eIvzHyShDVR6- z9%e`_aYMhH5cH9htX>hS>MD_c0vha4JsOy4#T>&7{B))K&)tKH%E&jn@>o7G%PW4U z|BR$+brrUWw-?CjF=)wIi}t5Q0RIn?;GTZap#PNk+S65a$a046QHHqZk+)MK1an01 zFofb88|ZD=e}u7|VB?1-X@%laY)P%)lye01X_DmzBpmzNPif*KVT%Fbu?gUv#*;O7 zl8r111Z~=7cvtpnaN(m2P4~2&+N`TKQDKR{)i3hF6h7_iW9@3n-Oy_nMjMzHb>J$V zv03p$nx_tu@$D=ZXeqP@3;7Me;zG#QAtSe*4KwP1bre^}$cXb#KD2xAHP#rUQ`#SX z9Zsq;`i&@1!^~#P+aVArN9uHU7DB7N+TB5N7yfOiWMu5KUG>+~%1GlWS`)&_t!KMn z?;xj)Ke(s^x@aURfsP{8QgnK5J3pb*&>iW-D>iyux|}Uk+!~8W-oJpg?43_OO8gHB-4uQ!k$IA%0 zntDG_kJicY7W$BU=?Fp_MRH@iJs9s3?`66OC%YVIC&*hS^nYfMj_@Hh3SEGf!{cZpnEy>*4XdVQ$z7CjXX!~VhIqSN`?qFONgjLymC!hI!sRm37TZaR~#=et;iDQZXlvI@>a| z)#JOmx#byw14~InDkF{9nZ+PI0tfft9*a2vtmyUfT1!i&=M3Lp({7hg?M7P7@!pHZ zEf!I8mAP{Y%gsdpaSLEWs!xfz1RkFEftLS2NHXrlEaPN~C|LKI4vDVMzX$LM2;-!cbtYLG z>dgx?D4UIHR+1U(%)u6OuM@bO)?~kArp$gBqBAampK4TdJaIG7(TtGOLOe&hX`Qpz zY_{(mMS+rDWi<6*Nm;RvgZANNSN6|_pdZh}?sD)#mwWs@;I?I(9qH)UK%brZDNtz8 zTfsi@3vGN2eGyk53-LP7*Mn5b&~|Bxtr*eve#I;cKk0_g zor#V$fn2^53cArrd3Q3RJ6_K3`g)|6Q?mikSv$k?$aZyX78Zj$ZoYGs_5^ml{Qc9! zc1j}GfSzH+Hbd>h**H0KVd&&?umSH=@AB=&%Wlf{vKsTA?5gZ!j=2ZKw5!Nu0r``^ z7~kG+=D2k!x|23+6{bPZ@Qg!N&X~2{$bHgr`K7MS3n;CayNWLB%;6BI_g@Za@>W-x zdoZ?x#Jp_#XJu|PdIA=5;F^EmU2TNba$@!@^W482W%rfij+$&S}~=SDu!=f?g7NuM+@_+e$mo?EKOdqh()z5LS@$Fb zKwP9>TUe`!A1qm97YX|t_u{vYJX@;jXO8voboeQcz9=8FLRy(m4hr1wbexx>ora$% zMW-Iw!Ni!h%#Uxsc&4{e42h(djnynqK4>dVl7wb_((e}D`~8tJ+r1Po=dP<0i|HFT zj$?F(cApY<%{m(M1@jUeQW2^=1i>nu~fM`xKu2tFSYVewOS` za8!O3w(U`J=rL5{Iw90R==g1rB=%$+>wNP0AnW{qvUyOs({emT*P@RBSbJq7_++gV z3p)C`^WU5qEP2g23Y4?ZE>Z`-8+Ku09dEJzyjJp_W|^pJxXyfG-!heuOWemw)whXE zA+Q047Gx?S`|V2VFM2o>igjhNk0c4|`PU;Ub_B3TypRBX%(7ht?Yx?)dm%=SNSs`& z_=7UpbOR@RrVL(n-@*Q&0cS!J|HnnhXSd}30w)8t-~i_ZE*2(%fp;&|{0y~7FUoJE zL;P3Ok)av|aEZGZg~tu(&oz_s=IZO{VG+yxMdN0^93+yx307Mcx1_5=@V4qY3Nr+@ zkj1PvrTTeHI&3fKk}l@+wfrgcsitqN9uNV+G5g%moToea8tmSE|QtRLvUCA zxp?fGy--x*0Fc_Co@^HGJ>pnH z8p;sy^B%}Ziw{@oylrTxt{a*+QNJ{8^s#bLDNJmKP_lOVdWY6tuQyLq?@}l!?@f8D zL}F_)uBh5(sr#<3kuQ6V0oe#u%q2*Ci_=!+G_BFBkV%c@dsYy-uuL6Yu|J!sIi)By zLzVyJb=&RW*Q)w~FE5c;IzlaO!W5WP#I5SP6M8a1CX|cKjMoFibb}v^tygjl215KB zjKj--^9JVb=d7kl*E3m$esuBd(!#6Z$noC$_|NAf`x65>kMl_9Cp59*UCuncXR1vj z-DUoyI5~*MkGxlPdx$IhQe)2PN83){i;}CcLt{!O9r?D}N$e|j*%0ir#ETs1qX=P@ zJLd}a%oyL`>P9tp8L&QYZunBIU;j)_J)M~La7E9WhTd8g87z5w$ui{->(7$U;e2k` z*B#5qiu~0z@3i~qDfvt`rIdi<111068;V?4s#BhEL*SB7tpDWWbRQlN_IH(l33%tJ z4CjxVMOLbigd5Cu>u_cak7oQ$6|pM(n4?sagENZMW}s~dSNhg!pQOeWOsIYvZ3BAP zi2|h}#_Y;E>P))gqW3tigr(ej_s(}E*Uhx^a#a*;;pi68#k~LwvS`>2;}&C}{CZ<( zF|U+(oiZnmV#GEpY$A#k5ZKG&?Vx6bNU09*7*T-pev`tC@7_X4m0Wf@3Z>QaOSRUC zD%?nF5=FV;5)pYCnaI)6{J=Y#dK74 zmH;@!@@fUgTAeXQUY(iS4YAn>tniBumQ`d1E%dt|647KDhX?f8IEjB~if?7vrbYNZ zy6Talt<6WDoCy7tkFf3^uy^MJL0TWKCqG>t4fA$MLSLL5ej|ZmM_w(=|78wd9SZR` zDY%IFQ?QubJ@^5+kc>swC(=TsQL(Gs`JE}lFRdB+5D3ldn-Ah~Q~QDa!uT*pr@t8Z z0|@)rv8qtiGtSM5-5QuKDOi(ll@h;?H!@GeUJ=lO=l3Oe1%4N=B5D$Y_nk(cbbm4o z$U}yECndd8&IPYJiWouuf?yP>+W*Ci5s`3}Szfz7tXpx4srGG$Qp9Ev{OTO7*G92o z@mgsi1;ZvX-rb1G71!E<@zdZhYBi!1Yz>W$%>c8op*Tx?Bt!w}EXX)A4DcN3*-yn9 zXlCBsV?l~afJ8kJMZdVv)i~?U6GL3@gIhh$ockCa2v`&gxM=S@Ge=t!R|!2I&3%Ss z3H?zEMFV%9qW6PT?{;C+?T*t3(dkql=|*K0r7`_;E85tvmZSm@iFm|_fj7FDLh>p| z1!tn2y=8L0?Oa=4sX=iYf$h_v@};2Hg|O@38K28%-WJz@4WViXe6-(DKXtz%r8v)9 z@lr5tKttX^HyiwX6L<5jI?FFx;*`biKE^^7uhAfe2%7 z{g^qYg6_%A$zk62&%d!G7>;6qou13BlD&Qxz|b4guNK4-9{FxZwaf^kFI*(!uK6_3 zPO?8Q*ps2K%*5=FrTdME0;GYGm_L_8l)v9X&pTwPpR=9tVw9^vZ0VR~!EY$XsfpK3 zAE-5~_4@=5D-~TK0KNIcWgbd|u$YX53IkM$n=ztVW48FPGZgapuqNUq(`&!WpTy_7>88{s*&Nf!zb| zVz6KKGdr?2USdrDAD5NZu$G)cAi|Yo)0HiCnL=T43CD8#KFzU;ES3h{K z{U(8*@(oS;^a-|5Q*e83QxL*j_@>`U>4+4v0Z)KyTh}lP4AoZh!m2s1`l5=M7wtKB zuwb~)D5-9r28!avL|ZZLoRL0m)qbk!X73~$qCU_pOfKU|3;CJdzpCtyIQZ~fauJ5`$d-3<)h zfDFsu#Z=_RG|o)rUrb>HD+%u=w%jVwn&WJEWJjm?nzFxF66vM3=U%P@0fZDfSQ_SJ z>=me-Gp`xMQaV>x$pj;9;rjfdSXv{mX_K1mj5S^w>@h3}w3d9cLX!w!X{8ZYm4`;X z^MEb48H+XA5IygLy=BT)X+C=tsGG?Qx@L3Xyxa>s)B1RS#pzhE8D!WXPlN3PSV5G7 zatp<^hsHd!gx6(8m^iL>cT)-Vr6*C2#_bFko7g4>JK9aR(fC`L`0v-X3?Jr}Q+qoS zwQrpXcxr~G>w}Q8#Y6jK-{d}Q`hl*Ts&V8xmSQI#&tta+wttx6=JtfvUhH0#yS`mR zTGFb7^OD@yQT%aSvZz%AK9bOZ%lYz0QyAP0%Z^OOy0f@{rV>+Nzq+?Ke&vxXCQ^zBrEZRDar4dFSrVcnQ6*8P-(o3M;CF_}r&7>?ieVp?sa#{_>)>09GmpoZ57MJEgvmA$X3D(Qjk} z2;WN-mn{3F<92g8#Y+tP6^u_{uQth}HauFfe$Hx%Oba@FLt(Tle-*$^>4dX(s zN;}kdaA2{Gk(Lmp)l6|-VzZUNR*>GL-_Y4taLlz~vHm?@6m#GbD;LHZ!j;|OQ1XPx z1wnTUN|$Pxi31Onf=Y*O-PVXpjnKy|3<$c#EY{?FCI8`Shb&8P(qfb&<#GqxdEi8! z*dQcvY2qx-9inYmtlxO-~!&Z|9xCx7E)*Q0Eh&G)9&;PBQFo zmW(`+_cW(ZR+!_wY%fT4&dh-aMnE^A5PuqG7y&ns*3R@_l|H-#p4hMaJVv&2-j4o2Xys2c7++Aid`DTcmu5SxMPe>|HwXyB^0! zZnqYF2{v9fXU|t{b&b1P-9QTwQ9u1*$jAw7FUS4rRsuTI7;ar-4~-slX%G455t>z5jWY z8QnWf3TohpEvP6cIX)TV>%Iz;!W9|`H@@%Po$X+)n%q$P`c?An4_{EvQm1SPwv_)< zNn4o7T%VOSO1ap)uy9T{;y_hC$gm@n8x06^6lr4iHp@jb%ceY}o^MHFH2(`3 zwqh0tp<&u3W|?lzBR#7y$>ZtTx*7h32^#kerhSnw_oIF0p#NBk@+Fd+yor zjV zkEq9RZ2k$!5TP<`NwLO(aXL2nnNOrtSlo2Gy6eWv>y%C)yu{a?(-fB(pRA4@-#0fp zXIra@ef#Om)AR9Kd>z}?clM;#5iXx|s1d!I8y+Wc{iBQ%Pn19|?vDnuM0>Jr@tW~j zJxMAJP!b{npwI7HP|8AXa6N1f@yrhjvC9^hDRmT@kzp2Sp}i-{3Ll)k%a+giGysOc zj5UUqv1PHyNiB>ZwzY}cc66v_MUn*g79}D*FA?KNtI`HU!ewT`ScqNBaO6)w*xNjF z7X$Q?iR*1R0Us{@mjTj#wCr0h*kse=Rd(VWx8ut5!=Vj)wAHT2Hm(SUxh{4{%MzH+ zTM5mNTd`V3?C3#G3KEMESHKn@#kW<}l;bLB(mM2fu1C)EnaKwZ<~Vah(?6L*den@T z63{$}G@V_U*TgdCdIlL}v`V)vHW?}XzRoB3l&g5IIR@uIU*Qg~!vx!Dw0?StA*@VJ zf+3$|wgJASCKFc0N-I_10hL&f)bpPcphmWE`L+oq+pNMOY~6QL zM!C@-t}CE=u3Fk^J_>W&uDz_gW zz#BGo-*lb4J7l%^&x^)s>*xs|@tNB^|;9)I~ucU0U3&_lu&#LiprlpA2j~ z{+_>mOv#C|_1a%{JMFe|YFfj|8qvaNG7BH?4tr`%u)qGDmzoaj@4K;ymGeGkI3JPw z#&>;^6%ihe%V0dsYL_xyG+>XEr^pyednuSL?V!wpT2abf6VOj~U&LhJs*5Sm`h37r z=!XpBxD$O24SD_{rh79f^^CaZ>Nfm9BC&{r`A7$$!SyH3HBm1f z7G^8a^W}j$*i?Fk2Fvr37OT==P4?6}?Tz^}$YGqxLpxfQ4%Kf*#upy6j(D-*eggQMe%=*Q4}tl6e;to!^pQ%Im_VXlDk zCq`Znr|o=$*l}vbX{|nwyUn`MzE^mYEWdt<^!J~zyx)j9RfQ$VE;+s@DAXPlz2Xkw zunGIc6_O=bS6Ag8dL^cBQdCR=t6jc&!zR&oga$JSqx{%k?yd&IJ`Nor|*VT`%urBw#U3Got@23l%1zfc>d!a3j!$$Lno*`&K z%Ln7cv7D}NZ8A;=;7GkKy&h|C`aRb>m~58Gp&%=p9QC(!M>kke6Ptcw;>|;{t0}*m zt(Z{jII_4aziI#EnB{Yxh*vDS|CSKMfO&HW+bsgpMPcO46ou_Kk^h-b4YQ=ij7aqH zCqHEK?2a4z8@p|aEIICS?ZfhVG21C){m+l>Xs$om4M{_iJeezwA>exHyTm1gwp8Ar zN?}L@R0PaWl~G%(iK&df@K%7M)bEiQ@2f6-cWF`8S&=0^y?arH z^SCv}n^s-{?yjYYQQ0qKTaN8P!Gi(wcyM7l%bMnJ1m=6PMuKq4za!YYr zf3@C~!so%rHYU~=JTk61&LU4{pAemxPzt*uHW#W}sn~x_sCf&8z_$GTY zo~WJBL1B@eA{J3QbjX4%1Cs`Iw7XXpw5;nQy%={w+-iur+*nl+ZKK)99=7G#M>-1lq35fBF9`jX{7bk^ITyVj6C z#WihH3KitJT8zNKg_|GrD9>hO`<<)sJ#MI$i;JD!Z=cujbYn_Tr?B(`bn#CZJ7Ad6 zyBj&=L|B`K_tAIDllNBhFExQbi|K8N#$>*@YSBSc{Zc9(YX|~q+OXS?i%-_!-ZVKZ z+gTf~&UI7_yuY~~!8(t9o>)6Sj6IIf(b{*fVpiva-Enw|KdT*+jigR2a=@v|v8?^{ zEW5B$j&aU=idlh#XS&S z5pW)|i-z$$)UcyCFno}9*0biDUmzE;4^+dh!aS|SN(?=*YAt|F#{z^K-dlL*Mb*#D z*&f$!L^(b1Q<;Ngf@98iowgLfnYxY~8x6CJw+5cfIkQ1Q=XVKVSo>T44^2kE7E1o> zp3vE{CLa25{%GV;1y_= zlN6Lbyc<)>Z*^oweM&84Y`#hzJ(r)UGl!|fz(MU7(eARS_cRNHl8vTBFHs+qVC9a; z+hx{{F?|2iwJIlXm+4{C^IH+5d@{U7(091o5&WNOzHG*JAA^>~j=R6sVQ~nzLtJuC z1bE_kphu|-%cORV8|uy$TUyn{r;TIX)EboN^H`>ZXQZ2v~p!3 zB!TFsE&oJIHL4v-H^`b)SFmzU*et0LW`*&2AWtA7N@NT>w~N~j)udgy&}RzD|RT#T(FAjCLtPH zb&upVf18ROsZ<*jpw3m2a?*bfV`xrg)@DUUXo zKapM6^YTgw|Hcc;5UOF(|3KiV9mtA`iKH+lyJQDQfVe7Uk!5Y_yVq?x%R6?#Bz3lH z$TDiKXBsSXax4%w$@ar>7UFxaDaGSyQW%*edS__u{G^Q6@M%o*Nk_{-Gz8*Hbjd&YA5%Yc9!H>cy^A>!DX5eEW*4Zduxp>juHHdwt`OW%E9X|s1ZY8-Nwvu2 zDfg;HAbT6?gfUoqpnoS34CTa(?c6`Tg*HO-I+zwWoUFuZaTbcx-5`yHWdSSW3Sr?or^PHUQIRFOg z2Tn&)1+N;vsP**z$}xuAHncUon~%{vTxO&pnZ%hY3{BL?W7hF9!aywa=%v(<917I> z$cesKq8jXJ_RBun`Iyx~2gYt!E77Ws)to4;?_W@;#lHd zEI*4yWA`?3g!HP;BQD8-K~(%n1o zRT%hi%Ix@E6cwB%%hEE#p!9St<}d5#GRcLj$6e0LjC90Oou^352YrIn62`!1-)FEu*FZ%$XWvp`-IS}?s7)_MJR8y<^O2V6ezYDc%PDD} z_##K0Bk0(4&gK%xVR`UlLy>^@+w_A|!skD|F`;f+Q)iA_7-ncMLT^cE8gjYeYF(&i0w-((FKHrehe7k5qaV4|hIoX?P@Drs4 zvkV2Q{#(Xjwn97R7Xv@Sv88&;EYsBy_CFkLWA=}PuR!YqF#WRNp;eL1Z*@`~5x*x( z;z9R5kd7OB2O}Udj=^6}J&KCa@_@O!TSdLKtM+MgVe9j`n%<-CBltv3i&2ml5KRZPc%LmqnINud%|P+Im1qxkD@I=^ zdL(PLL^pbxmE`pQy^e`pJE5K>AW6G%rF@dy1=^*XlwKP%9Y1KN&0{^JFXBx?DXIUWnuWuk}YD}l~BvP=Kdjp$HA7D z)062F{W!9aH_lQW(8^VTQK6hFlXW%y{wU7FybShQ@pjrn_5-aBiP+NTZx!%IwS85@ z8`PGC##p}(qsv>5_y^mY6oGG8{l7MUawYPq!wP#SF?WhKiz2xYD-pst=uRa1wxV9H z=RY7pc6n`xC)C1e^01&E4}>|;oXVaWsznRb1Y*mXGUa2Kq+Q7e6sVifN}ed17|V_X zH!%jf@4kB9C3evh#BWrz9s_a)Pyo{y1lCjLnz z|DrQ0{WsXl&L%0tfQT~ zAGTt6fSEwP{2$!XNT&VHGqX0bWRq8?q#Af6B!g87fq}3;)PF13uAC6 z8j*_@p_L*M9ySgW7cdQ>` z!m$dOeWDJiuJkI8o68w9O?tJYg|_+Quf0`o4?4D;83co-aW|;wJwD@I8^a%CcR-*j zAB=>pWCpZtBkQ8%5msXB1;w@)g62@6mpAVH2#hk z!&+>T6ydCIlecmy5=4Lxxpx>&Vc<@31FX(I7`SB0j$!h>`h1>s_Dp}><$xLp5yyIxw7qH3tRlLRXBeK%i5~E3QMKruignyl0IFF4r z3+K7;x&KYqyY;8*_U$I(6E=!ryTHb%pqX@4w?zFT7yI}9xwRw69+`FFxyc!HeLbW7 zMq3?H>T^?)k*kO}Y6_zTRrV~&h-QQV!YW;{ z(sV~D#K-XFv=wa7tbyNPD?y=OCUN% z`0D*Pvyk4QK(!QD*cTj4GW8pSWMmp*jO+xka@<}zZ-0xQ#XQ)8`q@$vV5w|=az{h8 zp18J(?IKodXT3XC5F+GSlGSMbmgrtxjxpTK5;Qx@JDcs1N1AiDO#|LQ;4!QcVk$2_ z&D*Mc_)w&<@uCf_)^~JLF6HNmbrZOI1q7cpR*CHW$1(2z`h&x&6C|jQnQZzKI{=2C ze*T_AtEMD%m^~aZEbQGuUeb6k44z%f>`1w}e-R9B0uwiHth2QcUjf@oe%u|PR} zHZKIyt?K?qNS{^l78HwknkXs;6lVII=kT|b;|}O`A^LmwwNA?WNq*^&{9X0)O*4g( zCJ|)x0%w(bI{i=F#c*M8&5X6tY-95%l~VO4rO;&1#%2p#Z$lvQb*Q>k{T=5<-Uhy1 zB&=dB!LbZ<#ECEERzn;qR0@HJqg}VhmvJfNXDACj(g;v5^Y_IW`{q&oJH!6xua91b zmXjq4KhyNO>pA@C%5|tbAt4$gc?g3TjzVEOlQi;yP*lrUIU?Qx9>h*|2!)rZ|BtD6 z;I1@Wwzi`VI<{@ww$ZU|qoWnuR(EXMw$sUq?R3l)clc(X^PO+(zwnGvv+Ayz^LltQ z0L8K4_og;~_P37|I9{peK9om8kT2rC7Wr-aYQ%mlSKCdLrBnrjE#mn4lkliYSYWsz zDBi5hiAspAdI*q=2IzdaCi*-?MofBjpgJBj^H99GnlEIN;*)>vi75^VBkVo-!yCA* zxP|CPrs61k{z^20M$sI-egJ}3k8`9$nJn)^@;L*d-r^nFFJ{YP-4ZoBw;uVlbXP;f z?5Se##?yv5>+RqI6JkM_D~fG?9@sXXb^<&ElwRX9fYGni*NB-!UNiAi%mJr|NEN`i zbVVKI^|~ixXj&RAxjBM5^u1Sb&{fCeHbllAz1z_9sPfFn=j(A_)O+0|eD^4vNd!_) z(CF}bOQKbo2`Ahl_T~~WDI7d@PEl~j;^&Gsi9V5d+}41gvm>;c0gU)dB3}f23)jlO zZM~ThYGK!aw{2<11i_6=)@i?jA}ciD^zOe&nw3TV+=91-cQsML`$~HDfLEa1e}YDK zRwp=)9N<@qn^<4rpt(&yq5rmsx5yY1;z2KF67~J1trG345K5@VEjn^qhL&cdiJ{4JGK_B9KrB`EwlF>5UUt2EYcu;o!rn zBH`%R;C!&5X$NeV%74oEiYz)fNH&Z7F%+(BE=Lz%i6+A3*j8y3q^0~GYCQ`Dvj|5?h$pL6*a6w<`m9K+c+m6PsI7_hLmToO%TRaFcQ`WO{(3;7;HroKP46#n~G~>OJaKN z_gGWX8&mi%ej5Tp-J5ja0Hhn=2!<>>cN!iPId@2vck_^OHzno5&KUpr!LDTcQk!;JK$pkWphBJ>T@( z^lj4LTeu8z*HFCcAjm`*j8vYg%(DDFvQjuui>7`^ z1$^IDFfu4-%>oD9m1N;J%sEJ2panH`FN#2Px~T($Z@9Y4Oe!$Pg~C%L-R+(0Va|`e zPn&L(LsCGJ-z5hH^}UN+Y|@D@BM8EtScp`;*iS@R^XD@m539YEZo=$|SqBCsbkZMOMt0JnA!P;ihXM1Zj=d*X@~vQ{1g{J_ z^U{1?u&!)$m7UN5n}{#$u{%TP0bUeW-F~DWAJ+mH#NJP>?Pfm2R&G`ujqO*98`98{ zS7vX2aSL9l8rE1632Kjtx6Cf(P5@}``c=vz*RB9Xy%`+HO`i)n>xYSI5LZ3D2EibVYzg!bcYOND%dvSwkD|ew{{RE zIw6j7?bc*}D=l1hu_7Pi3F2STbfdV#txN%h*iFZVCR=Om2aglayE~o2LeC%4`;1QA z>>igFqZEv7OSWAxMpv42{gYOV_UL6&p&CsS7BK36biYZLA4qf32GcoZ9v1_>aiNX# zyOSI{Dh5m-%R!f_a>a0_`JsZ$zl>wU_4enifVvGVs0#rj;(Un98c zRNYgmt69?3?4uQ>Ha%iqU_n!*?V*rMWaYx)?T|W`lx)*7BJjL#^XgxaWU}*IXAx}^ zUI$#0gHF1xz zc*+lk?UoP7#V?#^0W_9|}z-4TS`Z7WHcG z5f=SKpWH_u`c(w>O_%RT^P1w^a9|9hq=_P*hjzRTx~~=a&7@!T6&l2|h_uM{^$#hf z*`&M!76{dVE1VvCHFxWY%41XQXvs1K~jrhS5rW z|NRVlAgwP&gltja%-3m#8paa)N!+ }I}7s$aK1%1~J!krK9j&Q!II*uRn40zUm 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%0A2=L*>wryS(%TWrXfdGeI%Q|X#;a1lS^g~0X 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

>lXGi#rc-?!YhNo*zCLk32IG6Vtey8r?wq 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 D%O{RC0B~QHGIHp{>&F3FWG?I($m< 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%0D3=(-e8F$^^_ zg)RiGbtGD@wWpWo35WQ)t=^g>JYo&}F$r>ccal6wxh%YK1z=TE1NRI*I{vW^`F=$E z1XZ9N6Fj>tFcp?UZvf!>=gMr38W$e~opK(+F6tbd@);o>fo~;;QQahFoJsfYn=LP%L5AU&cTS**&fVF_7vj%Kv8IGZJ z=8K6GM}Q}OxY)bV=JzWG4zS4xGUFmF449fyfRRmt1&%)N6~%yh>x`5{l?v|x0?T4v z*1HJiawrBiv`8^?6Cb6mz3X_{Ban?z$dE)O=uWFpU@n}rKs)lY=Jn?YW2b=F@j-*{t?rj zg%HcS?fP3+*j3lwXIr~Tmd$v`ZB}Hq0A4A6TNs-%{3P6RW-rvJZ@xi;Fzb4*yA6i7 zmC!wh+Gjs;h|QlVt8`g!gTOG{2`piY#Ml#VIFV)?WLd5dM2U2*_28R-$FkS$yZ>>w zJ^wnweJtLK(xR$%y;6TVa2z09YMcHjv{@R@81G2RGL8ObyIT>q_1Q&d9cX{?nS*V? z9Kv$Bn=dZd?7nJwZ~5s^NBOgV?02~O?tU4Lc4#xFWM0Z@|HATa`}gnNXHWjAg>VLB zwkJpuWgfJYvXk*7drI-GUm-#RF?ilv03wfp7k_zG&+l)$1=|s`EYKJHsWv zM?8&Ncq718%<_-X^W>2>yHnJ%oVx4s!5&bspVQ$$5Xn zMmX6?9opv%>GKGcl$)eIgt$xPWRMX8eU~7hZ1FDm73K8^%~Wi6bwgf}LFheV&HX>P z(uTT}ys!js)0E2D^!hHl^ur77v}2~<x0fLbsKhE1i_`0iG3pLLeN^QqV>OkxHI5 zq6AN#g-6-eWp>YFop$T8H7ExNA*oP^DJ;Iz4TjzV_=x+dtO(BpRmVTUQ-W5$i=XuW z?gFC-pWcHUf;CYoy

*V0D=Q0}gdrLt+&MV+Y!Chcw%w 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 literal 0 HcmV?d00001 diff --git a/src/assets/logo/etest-logo.png b/src/assets/logo/etest-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..77569ab47777827f6218567a15f2605ca67b3b77 GIT binary patch literal 31855 zcmeFYbyU>f`!7m&NQofjh#=D4r9*cJN)J7B3@xd2OASaV-5}Be0}>+bP||{QOZR<` ze!ib`?z!ju*6*MD&s}%cayiUziPsZ*zaur(6^IFF3DD5ch?Nw<+GuE)&1h)o zE_gV=FRAOeslb2uE{ZSR(a;DfQ2)@;GBWR>q2c&Jbzi_gf3IXm^;LC$P#t{QhqVyX*S6SaEAxxjTEfSy;(=S~4U z7a!AOHHZb&3B>~&il=|3Sb-rhD@hPaZ=5{*oV+5sfZq6p#d!JId4$Dyc>WGm11!N3 z0)zbb20L3qt$qGGL)Fy8l$_jQ5GM;OC9ot2V2TS0wG@N!35Zzn3R!US^NR9v3h-I; zaEb_8LpVi+ge`dZEiD8^Ab+AfgaUAz^-VK0!+m)BjlanX`klo0_vFAYK0d`FEvf&otef zt)ULU19xqOr%Xz6&xCkIg@icyxOhQKmKI{x&Tftnz|^3Q5F0CQ7bhE(;R9>{3@Sq1 z0WJId<4QVKuK#>87ASkL0vP)HGxUEW=KtP?{?7NZwE~F#7gq9j zn7gwz%nRaXC2Iqyx?G8-&^pHwuyd zDu(-i)!F|rj{g{#EMWR5jk^CMh^G*ne?=lC$j{FwEGsM`Aj{9oCo3o-$S)wwFC-5Z zl6%T0%FhS>yOsm=Kdb(o%>7@l@`u0w2|@oe8GvQf*MH*y@W;Oq#mWiTo*NJ^LIkl5 z(9k?Gl)$pO-kCesftk9;S!@37&1KDm&F|j__sGlMxkG%z92}u#(c>`iWdP1QnJ`LY zoF!;+@_lp*R5od~E0R_@-w?N3QP$GzJ12HfW4)yQu{lj0Ccv9WOd-g8C-ROGSmusy zZfIDTQ!_w#SGvuk99g9CJgZc!XsASIZ*5sCez#J}W2j+hcyH~p_EB2@1JIujIduhu zRR;X$)1^TGll$|HS&wo(DgyOUEPp&gMTYt$zR=2L|2wJXgN**)Dduv)m4C)XbVXqp z{~1RXNrm0~4{`SYpWy%ZWLTmHx+VXk>PSlLX6*`xDf~Ns{&YpY?O*9sfBn}WBAj*e z{-5^pXehW6N9FHy=+m~7(d&zu_c0p3t}r+u%uhRy2cT-Eg*9}IgzM>`=uG(e zPnFZa&%$?3DOWSSiO+CW=}@ahrdUql7bhAfSB}(sD#OAyp}wGWQ)tVKJN5Lz$wO1a5!KJtm9*)_&vZ`S`XB<8k7_ zn83@@L=tgylnu+;7Rv~00Fa|K=;RMeHU(RTbW~F?0Z+)^$P>ZjEI(+gLN zYvz?P2?tRA`r~|xX0#7RQqHt~hW?Q#7RzRECB}!d?=^oMGEoLBI`W)}GEl4s#VKg1 zr5LA~An31O=0DLQf>Hevq8^Or`17CdizE;i!Z#!`HyjUEY*=+d4Fu2keD@MKTI|97NyZkdeyw^7lhtc!JJ zLD)PnPLU&&YW+zN*@3>;pUEm{C?yy0U>IXJX-CqD*?e9HR{HJ|7Bo~%fdVh`H@>81 zc|mf__qfsAd4pAOM^XY8ntS@kXR+tr)TPSCe?*}1;FWj18qTfgcScTg8$U`tem3&@ zX#v}-wAbhD4d!imsCBo;_(z^6u-AQs6y}k8Rjrx2dhzZji8-tp!p;7m9BqQUajN`> zPVy4!vf@8ij>ROo5T>tn1hzM_OCtqQ10sZC(#n2D}7*&vB>$(vIY7dF7ApjfR zime-&_6*0HMTOQOpe1UL&^u)K!59C+{~0}C(rVx(M7)#-2(+j{nCPpD%LXE6AAGg! z0BF>s@F^aO8X1%z0JoVFESzgskC^C--(wuNU?0pgc^GfEYeaSs&3H;t$45q1k^pG@ zQATSu5OeaiBT>HeJtpIQyb~e8$W^{S8$?^JEJEO6EEYFN`@#6XTy#l}Jm0b4(N*F4 zW6g=<19@D)<{}h7aeN_?fMetEr>hDj_2tVeDCjskI<>u{aWm`h&hREzzx)_V9XZ zF<2P_#!uV(2!WJoxE{3RQ{qdv{GP8gVR(ubkM6hmPJ#?7;Of|1&eRa_sS3b_{JV1q zN0E?OP#b1BfsiPO9M_cyW*9WfU-W3YQ(cils~UxF!|L_m`f{<{`)flRzL>@*)}ihv?xdm!`nOC$79Mfhjpzgr8sI zziqivPKfAI$ov~fp+u61R;lteQPmN45TCjchVeMFe0UrR3zENMzhdN1NnqT?BA2RA z0h@!k{)S}8CUlojh$(1%_YVnN ze-qQNr|k;@1fFtlyvP1%OYu^EU}O z_Pk#`8Gig3Lt^`jFPPc-pRKk!qB)&HB)!lK{a?gKbjAE3k!Tyed?d=Y=qFgY9E}iT z{0;)~{)5MxoJoO$xy@$BEM|FCY~=suIFJq8%94G44Yc@Q((Irm<-ZadGfeFikTDFt zln8L5-`Bi@PoC&Knm>&)N%H#3Aj#|NYxbF$nQ$?2@hbP1t7P^~7c6RE+Qh#bi458E z@bZ!lp()-JT4WkYzcnS`e>{nnkgIv0iERKQ?~sAr6GbR*<{Ee^xY>js+#i%9$HmjWKyYDtYW&zB0{PW-~2 za=JdbZ8*NXyZFS+VzA_HWCP_s?FiwKW@FDsxIN_(nY|Uy0%zYDM#BRDtSG8Q-@sC+ z!m~&zUe9IjoZd}4?P46lz}c|?u*1ybm+49>TlY(Ghg-jr@Zo5@SrQH}A8B;hI1p#o z(YU&>nj826WSSHsbdW2VJ1Zw`XWR-0*MR>nQ47vga3AB}W!uqP6o;^aK$Tyxt`iA& zm$gv|!>+G;laY;z%6oKqA#o|vcZ$r)IAkx^a5o21rEJ8?Pm}7~FBKFNkbs*{j4{*0 zSD(91i1YEiWuT>1j*E*c)GpEeP+QBNuE;Eg_VI^9@k0CT`O0D{_eO^R<^aato!ey^ zY!9{<_wL_+_ioU7t)Z@t7?L4x;J#7_P^GA-sQ3W}K?HFJ&4x(Jet0O{tTp@QQ@u#l zFeGr7@?1rl4<6bV^xJ)$R)VxGIGL%X%+#Gk9$(I04aZ$wK09|b?4Nq~NuzN=zqG1q zk4eVaxoX@&(8@1y!HLy+XxUiMvD~#BYnND@jI5Rx`Rcqc0m&N&*hiwb0hR=IrVXhZ z`jcq!C#F&k!2Zyx(1g)uzNo3?4x#O0aM?RM7qzy|dAyew4`3)q6MB;s0e9b8-fGyL zn3z~IFf^RY2r!tep>_{yZ7cXT*9xcoZ19TEyEtn2W$%*M;(@ZX(bn<8%#2~*(y)0( z4UWG=Cyb1Ya252c1uk`S{N&XWc6GHhIdGREx-iCCXjZ}e~7h<6G z94p3PFwQ2*oyZxf(WOZN%^bN8P~y4TwtXh@7T*SgyDEw`Ssx!a>TQmaiYS+sJZh&w zV&{=vqq#3Q9xcxXv+=aH47l;l&w+D!v;m}0lo-I?B?RcCbYis_3wTz)lM!rEKV6oJ zFHp=gRJZWbSVvIG3;Nbt)#aAVe|awV+|qAXU?n*y9k8)hWIj%TSgsH-$;jJwdU{V+?axlcFp-uopB$2ou|C{O+Y8GI!f_Qm$o|6bw4`mZQFIuw zhGvhy$fc^YC|^y0R0dzU3+~tXI_sk5S{Oubd?^?(U$Hiq=Zd>Xre_b1=ec(8e%H%8 z_&E<|JeJop>U<0*>8Wa}*cw%sjJF?|haq>aK9hS7hVOvK$rpv;7}Jki$i2gC=bkMs zX{oCD%w;{Vfxna>2g5 zV`asNLI}Z!52b{S!rS1k*;aT*$>!5P{B0nJelRvj89^FJYPs{)^*&@hh-og;3Y;?# zFz1Ag?F`<}By3r6d2C`<0MRqw)hH6@D_&G5AZ|Ma#gSm%F`R7w3zzOjCtdi~Gj)a9CUXA5 zr@5#oDG&zeid6pvL$`o2q2VIw4U4<*DC3oU#od>Oja^#e4Z_|E2z3Go+Fo`;;#?b#1~2buFK8D49J8Yk&H^FJnH z5@B>V5t@;5ImGO2kE2ZyI~98z z%`*shHZ!j|h?&Mvt9QMCJFKcD{=ze5s?|+RztEQM*^xIrf zR}GwvJKmaZ}mrauw%1}dv-^2 z7tMq^jhak<^7Uf>fr@2I5L(?mNLFOs;Vby8i`h<6r zdV2`F?e4zN1f-2ZRbpZ5`8(5Xv0CQ^2GRgw#3#yHycfYgOxymTi18Yv&^+OyndT7T zUr#b)5Y_ifXx0kztqpbBT1MDI;U+Hmjuw$QwfBtfBVw2) zx5BpNOw_77&eI39h}l5Bl(S4m44?T@c@&Wl2Jg)VL?EVoaQ&5^l4{9j%~kZ(!tp(L zVKOt%eQ#W3j@=U$f6~=J(oUlRUOX{`h%~}u51Rp}-aLfhl7B(0P>BFtp@zk&jv=rN zzwtT0S=x|uU__^AAZNz}-2iJ4iyOLqk9FJ9Adc$$_0_9|6MO&auC>o5dlQnN$R>Gb z=Elws1?P@qc{7R$!*$N1-luRkoFHyAX;NXD6re)aZha2#uqTJ#uT3M$>;AU=l9cq4 zcycr6t%pyQ!AXZgd9X5Kwvl9Y@|I)YH+F{X_9)FX->xNS7*hdbR$lT-coB_9H1~Ki zuLp|8@1c9AvV+KM%r+Y{o4K*0X;X4BmN7(3A^*TX_Tof5Q1I5kpw|)SL9y8d%VJ{C z1brcg^+ZT+Xz*OIw(usG)K80q}-#pfr9{+$NcsCD!c6!AmxhP z9EiL<(NoFn!~#1by8}+MhoNL1_xtV?;x8MiN_(`Ic1$d%{_{iM>g;4Mr8FUbrC+)<5f zsl^AX@{OY*M*Y@{@6an+$S%W#+*VCPT(PUeTrQle9yT^;=qtX(b6PHPQsmYA zF7mbB_-5XfhAAP4YCTGqH5PiqMxM;XSKmM}e9n8zaJGkDF1+5M%mg>P;N9d;&>NXY zuOtAX)o4UV6V@7usu|U)&jDXYjM;o~sF>FXoh%nzPnZ>-6D{ zSr|R#eDLkH)>aDjf%}4gMh_k7`@8q|y%?5ccKiPX^SvU(?X$ByR@|L3Eb$2aJI($^ zlSRDg!eypTxCbJu@emwYGN`A94qkCsM9=Z{ok4&9O6+*gR5}mOR zz@ECMp>yE@$-p@V3lcK;8js~6U3hTXiP^COaP}^caX;mI z!!{75omRpTO1m%oCcb;C z)t8M93_dLIAvU{sDt~pC@2kQ%FTE%G4)SKHKm`MlS(vS)F_y6~sPMLU{1R!9JDNxc$OJxc}yD4-9j^ z6=>*W3;GSZKKa2Y5&Nf==~=wKYHuaA5$c-QJ8&J=;z9MLt%n=^rYjQ*<*K`)@OfV4i( z{w`68g|abP!Ee{v84($%-h)8>IN~F!74^Iccj^vc2TQfq zz|payLiMY-A=W^Q6)qN>n4$%*;-Y$awXXs{5z2>p5`^!4$|sjgxJh9U2v zYm}nETr{*YQwCiheuB{oVSO5s2dIW)vx;1Ykecf=)3(6bAVaxuHCBg2czbjoxcv^I zSuS756vt%nwvtI$g7#4}e(}af#pA2WNc?vUjiBRkd>GcJ-SFUZ^a?|8sXOC7f$x0O zSg0LLu9Ui=iSBtbo3`m|1Xl>Y;u@ws@5AQZzVLIm%4WK`^JrAbK zad_4pGSX}WmOg=7o-D5>#fa?PlJ6a_ajUX;Eqe5WmU&34+6jc^C~6 zV;7f;1aMIhITs3lNAugB{oKNLoryzr@(Asc#(1|8JWQs9U(xB;s&&94S?Qf{h%tq zgK3*c z#n>*8+LLf9MR_0QAre)w9GvFh@GolWUwjGp-+Gu%;gcnffT4&Ed8!RsV^kY2QW(4L zfY0*s8hi15!uQejR7}#aEIhJA94{b(J$^(Y*i6pZgo**nbbtqu!;KLQL9D@Qh@!(i z!_fPBwbnMV0j)26h;4QvTUTG*(cvG7q}lOBgA*E&7%^%#S7Pm=)#H8&AWLlAM8IO3 zMYi80qYe+5=RtGjimz%yI}atk4OX(((d%eZ=;jiRzI&<+-egrj?e{gre+86Y$rNdY z{iSj-IP|!Q>srW_v;Jul*IJr0x1cRlVAf723~mARMD2OhVnjxUKW$;V_?Rrw_v7$*fG9ELucs22b94lsHk*X?cv8 z=09ydb9vcH#bw*D%g^tg!&mj71I3A&_aOW$FFf)17sLFq=Hr7Hanfa|)6C@Swmaz> zD6P97_B?mk{b>fgYT7h}ZqvPj1do*+zMcTCL2x!o%A*wkv~*34qtlg(A%gZeils$N z`rr?he!X$@@!Up@)h%HjM;5Ejb1OO--(I?%?f+aWRC~8d)G66-U28}l*_8$@XR0;; zJX{9M+>?s20B~Lx<%hJ24ym1n3fPlDDJ2DQn$YGDMAGETS|3xHsF@NKIlA*(Xovt7 z#L6~i?~s)sj26=%tevET?)GE+9RB=#MB4BYpbaF$bmy# zS$Uy?%cqz%p|-fmTI%m26z^m_+OM(i!u@0_=sBo;ILWbq{O+)zpU-gRE!9&ovZJTE zF#E!`kQV5+SyMKIS5pW0uUXG}k*obc8F(e?WF=k?{S>f&X||CR5zSh=#H9@0*W3C@ z%K)V^jxLJ_6k;8fW6?u`iQhA7oO4X;@{Z|ZzEurq+nmdpzyDz;@~#5MFkh?d zXZ9s|HBi)J$)fsjOBLBVzrb?*IH##tgJf7jhKrMTJu$#t<5mcuxu*4cD;SjpXoe8M zo+DXg?PS;BT~i|?BPKa|9?~N}kHFU4=tccw4yp4|`#s}|)*dklw zNKDxwIfbGaukRn6b{G#!HP1;^Zh5M@e-de?4UBiq8&8lzb?ZQNhqdEFa`3HMGI@we zR3CL$Tb+LE#rhK-GHKvgIY{yK2HH((k2jjWJ)4Umz*F!7Qf4l$y~CZ7qv*g+4Y6S1 z$8f;ebq5NY9KFYBw_8wiN#&$;1N>`i%z8x4c%%$=1?uNL<)s_3v|%3(Cg8uXtSeM>%Y_5fbd& zfU_Qd&`K-NdfZ4=GUtO(1I!i|zjsd<)8Y5l6WKmfAW;buIVO|o4mcW10N-YHOK ztCb4r)s$F7=Nqw@fjMD;sL375v$4IxU`XU4#%kOx;(aYE-@StH0y=%Ip}eHVgqs$? z0bOBBum_?CsLJvP@r7)i$F$OVMPHrme?b_>PeMHh0yx& zU;y_%L>^g$%=(gmtxnPQeHCY%?qb4eGuy@L&)^v92iEj11U$Ije7`;= zQ-;du*Lg1GyFbl0qeeNIEhx>LVF|MFaLT$8!!++E6dx1u96`GEdCpF7>8cYnKKl zvZzWv^}krTTT6Xr9x-#O{5nOM-}kPhjmkMrpt;;=Ad zos52l4q@pamGh>@vtxfQotz^`#wWXK(5(Yj8-@dm!6W2LRo~r*nI&;c)>J^_!`_|q z<$!DKZ^f$P;!(%^07O8huok=G;XBjQVfCB|oeE=kh6;8I_OOL~+`{JXcEyI92=m-B zv!bST?`U0XG~{q~_QRf@AAr&juV;ACn{?L*X8CO)esC9Dspt^-^(v0RBGSXm*iJYx zWG2){T}ZoQjP=7kASN-AxlSesPotH0CyS^!wneaK1fhyl6E&b`@KUwm@?dU`%;08%oQt@`t;CdV3z8Y;~u3%|!r2sCKZG`UL z^A8Kd+}{{F1gsn>w|Hns4u&?7yZSg1c!t4&)PJCZ5H9NZZd{nxCpL^~MMmFWXj!dS zuT-lFT^l6Xh+!>F1i3h$qjoc(9kqaGw8W90UuCx0&_6XsjMFOO@U0K&1?u?sj`jNx}o@!^L z(3sT;2rXzDQ?lv&0WD0Gxs(BvF~=D45nboS)INwBb%CVwN0*{t;DP!0nEjInCGxGx zz7Hj%a-T`>dkBc6P%8vgjh@k@7L!y`Qc)wl{l9&O8_cDBQCBpPwClJo#V=J*gXSGQ zBGJ*kn81N>y9A)Z&Q|aaLt3l>@s&s-;h#%7>*+}Hp?AR{b7!NxR0qQhD9ZX2@mc~E zxr!{!u|1gq{ohV!l|N(RB+A#N_c#&%8Ye~oU5uY;U$L9ffOGjRJ+UH0@xjJD<%-P| zbce3Dr_?WRUbCn|6HaK8hnyKK?47>)+H zPe&V1?{T+9(0l=HF4KD7?E^B}{0Lv-)zQc4+(m1_HUJH*ih_fTkG=;_VtGkjB+Jo( zM1V}{2i`2X8!buL=WFG$JhP99&9!g3tJbW?a@yl92=bR!rOeMV9X`qE3x>ohJ+zHB zU7di68+%O0E#UB|87vTqKOp-^c!qIc`*AzDd(8Ys=ojow1u3$~0k}kT5Ge@PgJarp z79%~cim}TT?o4le5nGaqdupU$>^U7uv-Lnd&$c}VnmWhm`SfbSHkj+N89CJYIOC)! zkXv7C`sv2XU9XOXX#d+5<V zVL>y%HZ^H^Q8*F{?p40htuknm-;1vcTcv&Q5q=1bE1a#uWVfx1DO_P$@{73)3dDYO zr?Y-bkgthxZCjmjLMx83E{5^EI_~k|R%WDcY~>36l2*b670|jHk2-Q^-7Qc73d*J> zVKwewb6fC2#WMKRua*}%^~DpFFM3;bIdy1t_#_iJ zxayRF)L@r?PWPDJIQxkI-A1CrR%^4i*B?5_@-rhYe4JGKkN6;%7>*FM-eY?-fgG}el zbupeEULYD>Cm0WHQrD*ZE)=13dvOOz)tG9ej!chI{PKd}vvK&&z{6~RF*$JlO|$LQ zd5hfaY^1bWj>f|vXe@2r#>WVOBH!_KA!Q^RP=-rkH-R3Y&hKI^hi|Sg8EI%}@Xh%S z>)>pd3G45JnmjX!fF{xc2SJJQy7v4$HZn6ruc;yxUk&!gNL_L4 zAG;)hzH63axU-wO(C;@M4?E7(OL|-#^tOK=9jy_L=~8k8dR>aOo4GtsKSU_Pm19W) z*b)Lx=e&?WXKH9@2yA1++GqKeO{ee(v;Xm!RE6(BH+9ZMlJt3!{br(VB3u!TPSnlv zc&tQ+@zbrv!BY1r8iCvWWFP`p(L$o43VCu~GeB%I(S_`5NncLY`4zxSZB~ftY^i4~p zb<8qmcf}wW!sLKU0yCvo+s3v7=&r)l{0kd=1GQXokS?Q!ME8o*3!cetM?^*t@?MxB zZ{1rbZOTg4ItK?CyJk9Pm0)2usiRZO;!mZt)aX?cjd67dYCDZ6Zy5Y3v2Wc_m#Q=~ zXf&BgI^@D{uQd(0d$9I~LcQ2d?uSDv805;h?n4;rNZ` zqSN{vnF|80ydAFh=;Q9YD-Sz+@E2MR8?+H3RZAyV-1|#D=V;F6^W+_j)BeIR!Yl9H z_QF@^F03w^V4^moaLFd!A|tyk;Hl%pMCh<)!L-L^xnw|zXh}YPJ!xY;lNN+-9iPyA zZ5i#(9ax7s8H-l`kJV8gd%2SDu82-wT(xDMUQER;9?$jB}~+d@~SubQPHri zMMYM1yYHdUC-%Y=XDWyQ2zR#x(5+K*=@96xJ9RXugCYxUR)=%iy{11w-J$b^_w_CA zyGc3Y>0peb$0VOQh~3^2I_z=ws$w5dF(Myh&ml-3Q?8!W0`;cUC^Fcv-Lo2t2AybC40{@d;%@C z9oG}x0#3kPW^N&H>&|hjZ2mi3hxhQS!QhQ4#t`-dcE;x7@vF0+;REl4Nf+BKnhz^_ zx68a7`UmkII4)6OHy^AJxpiRG#-rWhAg{W7xx3G#V*S{TY?|+S9}VyiW9dB2L^lXg za{DE!a&yCwR8rcN7R)$v)Ar`V`a?#a1^lf;3zBE8*}t0Brv3h<0HZ&=aFcuGRvp4{ z<*s$>nOIz1x$sDpBjz)K4!hl6j{R|8gOpACY76gVlVqMBd*MtcvaN7B%N?zPkmouk z?Gbrod-trLnB(oOFx;TNKWJfUzRLOzdt~~;^{$s!PQb;63Z3%;`l}Z|OUdD8lfP94 ze5Sr$cU&F<3ct_tHR}!A*Bd;Y7g#(mZu28eDc5@@8!g0zgyik*x71b5PM|aG4A=~F z&EvY7SuUOUFi+3a&Bp7f;SC2$z2Km^_@Hh$5fYCDX-Vv2X_Z?ZGwyo6u#?W(&(>C` z%i%P5f*T}BRcX_*>}?~V&Y5HL|R@}MOc0scloN^aET;KD>jOQ;!LvLD!$kHmd{1ZC; znZ{meiDju5X;XC#?D8$kIoT{-HY6!%8HCF`|`~VZnGN`pC4m|t981llumSmTz`1XwP z)*|6@JYFlaOiRUui`?s)YnZ!z>=FOu=;%++1z(IAN>*GFIu}3nT8my1p4V7Vy9emG zWo7KOUe0C~Z^z3-0~1Vo1YTOhV6a(f5_++t=bK1wQ;d8c*t;*FflrTLs^S~rAiLOK zvmL8J?5Ha6yE+6W70r}Cem-)w!(r!rbgM*ASDh8Jx3I!-++Y(|zUrz+(QJ9sT4!ta zaA9YzrJ<#v;WQe4*i2YkRY7jMh7h2q%($>&qbqwrFqnpfTlgnjDHb0e?Y8XA->&Dy z&%e4po;0nq>?4SfX~fUukAxD2Pw)=ee!_P_x&Og}hPKr2D=(!Q2xB zR<^u}m&?(X)g>Kl~Ftd2T=v>3efluP6M_1 z*~8KDQ{1uTgnPp+B6Nghi+$$|TzmSpPE}h?PB7TfL4AEaZjhnftW)OHaLt|tfsWlV zRJA*!ine6qcM2{k!zUJ}_TL3*CQpR>+#mjSPwpDQ9Z!gAoEzH_gJx<8WMQ^pJ&=Q) zD%4G8Z3XxNuLJB^zDgimE>es7-S+rV`Ran!TX}Z@A=(Bs(38m=57HW($ujCP`IlE| zh_T0dZW8yeUr_o9O|A7;hWC@wiR_;NaS!NziaQ1DHmxy~FW2V{Ni~}0=d8qP=lO~5 zWA^%8Q)bYlQs`~yH7yp9!L)3b=sxAfCFN|XK~9wNNYqDUA!CpRe{(^Ib24s$>7&nD zD-+DN^!vo01rOLJwGjqAJKnwT^_YlUXPspOS<5a}^XgO+ygxRx{5X_6u~8FV9v+wP z-x5Wds^6(dF0F~^q?_#CRS2MuX6F@5@iZKTC8+oF)V@6XNjV^O@_a-v0H0}QVWIsM zz_mLrF76tgxF-j4ZcftWcONV3%=EOjPN8b>tDK;kni}1}z(D;cDYWDAOT1fXVs z)%VRfxBFivEtHdFg!8*?qoYo0LW)rQxC|LHt7 z;ob6YmV6~Zf|%I9B62vupCq$tdb48s_Sv&%=|G;qfjD2w$)UM_U&Xri$H4ZFT1GU6 z!|KRg)IA@+MMSV%5~~ISa6NMH=B!tG_ohddkoy@g_GnmwO9su#NAcO-5XGPIJvLFRxSgqHNzy;nLZw!ON4K z7U;KRwshbSbQ|cTat-dAe@};Y4WQlojt_D9Z@5?`yE{hy{+t$`rB-*=hxS<7m;+ZaYbh&56E(%qRQsc9*Of9NY( z38!Iwet1~eN8lnfTafh4vNTJIa-u2=>PkKvlk3sC767ZsuP%2QaBYS%eR@ULGIfq< zzpc2n0{ejTOGpd=DY$})ii%L8q9u7G7NDebfT7o~U-yAQqky%11uOzci3Yxv0?uzz}bx*0I>x4_bo4npFv?Wr1)APNnML?Abl#Fx-Ce@==iEH*zA zwNd{wb4D25av|{cx(O9QvJF0aAAAG~4@(0B1M8TW7^0g)>DxmYAn!7D>A-#&baQhv zmamk=2fR_IK}HXom$MWv5iL)swyP5+CLd6g#i|PPY3nB6Xj113m+n z@ZsCp+37Rl>IK|rc6@p|0}42Z7YvpUIA=>(czC*yFk}D7)Ti?%Vrk;U6t5EYf`rS6e?@_PveD z$aVyh&+|Vn9D+@lS_inPg1r3qyu7@UlarIU4P;Rf3Ic#hfJoE(tZPejG$aLq%t*+4 z5rK}PSru?xc4T^cY#N9nMX{P;1TYm(!YK6_xKMq#2xxxIwU_>M=?eh~8^%(@0$*sS?v1;c&DjuO zQkB5dz_HQMM2wHlZRgfc-VL$vI9eCpdlizw^9Wc7c)YMdF7XBSJWF3G-fbW?&iQw{D( zoh`nOHVwQ!HcaaK^>L*?tq6S{u=zMZjt}e;=rgUWy_7f~Qj-Ng$qi!^p=P&Vpx-KP=Ywsm!Wh-*EZJqNtzCY3yB z%_zQ>>AriIF%O8V{06}1sw@DNX91faJ~}z^^z!sP3Ec0%Ez=PB`DTs%Y%@}L;niUQ zQeE5;`XpuZcE>qzrWJ4x8o;hffPD03d-%rTj^f@-0{~#2%(yr>%`9pe0z81!QP{yK z;mzaGflWOd($_%6Nd(BaA@xyG-`Ll$ctBj~<1qOQ2LcPKihh#Tf6%gU&6NcJkN{NM z9Dvk5-6tvNXMlMm0hw-64(Kb=|L67Tg7m`_Wy$LfT*gcwK~B5@eEYSeq~v`K0E+JO z3@>A?8fYsIRTk!R> zAm+sYP|w1mku5PYIhnS-vGKmBh!uPPXE-AZ;NTwt|FXU~+R$8||0s2fRDr-#q_;YB z-&zG9ef_F<(a?Sk=#w)Yh*HdczP?Ngp)6VItianv&9$|)nD=Pu>5XreqPZ(?rYGC1 zO`RFfWy>rx*BdGaSKMUVQ&+AUzJKv_K63Tb_nXQ-_ATvktne)7{(0u-!<8ofV(D;F zKS6KJex#s@-1)HwEn^4Mg}+Q_OTDCYjM}dwvmpngaMX)jE1uW0~n*z z+-ql6+~*jO(AJ@Sw$`Rh(bN=&nJWL4M>#O($l-;oL(f~K6s6u3h6&lBUlsG^+w9F3 zTIoB<-?*Qfd!+9q@SlHCO&oUaR~yhs^>00ywlAaKdTIJo?8;l6ZYWT=YQ|{ki%?do zUiG!Lx5tWGQ?LDW9t9@>s6uuxLaxckX=;tWrg_#A6>-0UDpr@Cr{));P_HHK48TWa1}8IeIBodgBz4Z}F$cq?s+r zGS*wIt=#xlXv{qEjEfOBmAW}wHXtD0-lo}$`}y;yBZHIRBW*Qt@xoRSVN8 zS|`N5rTw4rw|0K2Iv)34A%tFk^rowecc zLCU+SC-2GiVy7OV^1bzwTdQ;65ZC+6*!Nni64uwga4Obs^{9TsYyY=h<(bz}OVEVL z;>p|I;cf1>LR)py%f9nNDN?C*6TieHUzi&fn52A)s+nZ)`qhJbSYStFuk|Ei&-JBL z#GY{pWAcxBQ{e3lr%O8@>>O@=nVsh)R~cy`ZdKXrA7k15XTywZCY*+BP5^V;4W8}t z8(Nl=+Pk>8-V5C0Ao}s^r@OIe;Azc@S>-+l%+L59LWtAEa9ZHY)^FNVE8gI-4BQ_I zr;iBeFF2*K=L>kk3tFp|Ef?>FlH5)V3>IOSR&!3i-XQ%%nbwBg;)ELQOZ(T!x)4-{twC>Nwn_WND~^p zNf+ze6-PXqy3nK(gW2u^8OnD5l_?ymu!?>gl#V;_U1bH6MHHyDh2KusSoAiFiS^Kb zZ$%Wqr6{~CE}l&_m_{n&kiOVGyHpye$-=n;I_M|u3_YjfN1dYanOhMVKy}^d1Ejq} z4Y#cOpw)XeylY3kOt`P4+6StF?k=iO76yrY?Fukf0lf75HGr^`DmHhKlPq7lB4;Y> z^QQ2=PGVLq^U+*f9B(-r)|hvb_s;mk-2*ACv21_O)ZvJItSq2(VPCzfXa2n>df5Oo ztBfr({(g#4SoKcOtHLATMQ@Mt>$UrO|7NWUpkqZ zE=*@+)+UfdnIEg6qJh6pmEoV*+?l*Zjl)@n5vN)g4ZzC4(N9)~HAKP&y zB;B=*R6@7}{7^&upd1=cbJ%)mdFhYqg1v9JsDrRuT=;c6`D_C{S5N$A_si_skjv+G z%0~P{4%g;8r)&?h5k%e-&wk#R$C5buJKJZ*^c#KmxL-$VR7>UlY99CI;c`w@cQ)rF z|AC19hcU^+5+kmL_XP#rj%Xrlhabp?>`4a>k9Y_8J80Q|QWE&HSHKKr)GTn`xH9zj z^Y+d;&c>;n?9Tc5Iah5}&ZJ&&?UM_&5 zS|(On>ktGitHL?fuL1@?zK!(3vp*j^Ki=+sCB1bc`Z}`r2kjjXPKpZiB^mjECcnu_ z4hfaOa9ASoSVBML84yML4hf^3*VK6Qv22JRo8EyO9A+{2BhRhjFyx`RSyUb zWepF4`~&=i=it}AEW4*YX-4ygU(TTE@{a9>Gaq}{HwJD4@hOJ?ulCOKuc_?o;#iOo zRA!_JA~-rCMVd%&c1MXIT?ickAreX`(h`wT2WcZMp+-eOq(s2bAs|f%B+?R)DlI}F zlmG#ekmvCGJ04#6%6tg-o_o&TYpw6TZ-y|m`<2kwwH>GL{N9Hk4gRJ(o>5%3GN0<8 z!ooUIY@h7x)W+U7Q%<8WYB%u+_6c}?MYTML#OunT%F{U^KFq<=3=e6USH@ zU0O2L>Rm%cR42Pp^GEk8NG}-g-u+okISKDkOQTn%^dHPo+t9x_zam**XPOC2v^dK|dWKSj9nTus-1Kgw~a` zmbSl#5?`|etv5_abAcCU18ZgLOK_RN?F;z7Xnru`LJRz+HQ{;Y9ct+nR>Z9dRhs-N zR`DTHqTs`bZ(CPF4RuL$CRp@p^+_{Y(BE@obL$gtXZ#|3+btjpIUcSrMvGrEBhoW@ zeHmM4M_~SDfgIJ3f3C%)`55hi%G0O;#oIFh6?FqCDdX(}Dc=Nn!DcTbX2xlGq)c5J zT!Q(#$er84Igv(Ly?Q1KvUwHuYmONDc-e4(e{mNfl)JlW90m-rmB}jK(K$#-ejqT? ze3Q{T=lxn!*TW?f^b<0=JBvPrX%Kkam6%$%TrG!vyNC6-vvGEq?hq_&J~H^nAc7`9gFN2RY>U)H6-lr?lOWK@afm-Iq2x)7pnYd20Ydjx7K6mpQkbk z)&IJ&ULc+j^s|(7SP7ek*_zfk_X66dpzim399lze9Nu3hrgMFi^+W1?%5~ob;fxyN zxbc}S73U_-m9av3_8)UAwds2v#Pq1qIc^}Ek>Xw#Os90kCA5Lw|mKk#rFCnK1I> zhu+Vckl^4ER;`AgADKmQC(({K*WTK*?P`pO0IJZA%F0CtWT=s>uxsv%AxPZTfmKKxf&B(~bE+lAB(PSxv9S>dX-mZ+9opG`AK#!bmd zO9x5P($WUQBO~5~v*GG348aCXdN6E#psVfl+%5|U5p!T(!6s-RgEludtdff=Y79?h zM<;U+vu&GEt&bkq@>SP=sI-}psRH`KU2={-V~-~4nde8feH$`$)7MMf6yB_PyG$z$Sdmii$mR>m#BB{mLj^B|Ku!l z*d$N5u={02ST~Bl`O)*``?HR+PeDVB3dYi`r3o%+qrKVZRrHJ<-#nj%}ZO2VZ ztw|w84Hn95<{s|qENHFo(*i|3DOVKcj(UU-s4Maq)Tw9p0=EnQU*$ods5aO}XQ1}>i2|eygRqLtiLUhC=3711v8Y?7_H2KGB7andWO+=`Fh!<1iVm{1Wq0LLfIGFdKQjPJpoZUP$p})VFo>~S zyG!T*17Dyf7#lNcW|k%^1rR7h?AKJSxq0)6_H7uk){(}X!an1PJa(>l6bpT(*8;X0 zNm{DbqyWHd#JBm2+Mg#PHswQhAIH5b>DGIQ}xa zT5mzM8WOA8X`pZO)FEj!HEs*mr>AOsa7)H8{EK!5a4bZQfvZ;LGJUgy86BZ8*q>S#UGMlEE{xv;YT%lZ^@l#v z@!u7qR zUK{dWlRTEcAB_~-ULY z_G)6jVpRlZjCIHI&1K*tko);9o|Kx85M-&MPG}Vxf>XReS7SMhK)4jTH ziVo!bS_I9BXN%gj4Ry^mG<=#J`sFZf$J`r>P?gaIMnF!f!Z)DH0Zp2eo15DL3g~aF zFyo+K4=#hzF8d}!Gq={JqkY%uJGLj^3s?#N_ZZ@|-h#(L4_}@_NCzscUU7a7vexgAV!a zp_WIts8Wq`u%B|fl;5BK(#OptEICp>H*H#~SDu5M_s)NegL@}1_upx3s}*#dj}H4K z+cDVP_^-@+HUKwu%{r0N6{ zQqF z7+o7AkZt)YP-uo_MAD@?LPd%Sjzs*SLPi6(;KMo(QLGTGxRt%!u~cZ(6A+blnH4&= za)8wG%c=P=d241$e7he1`l*c0aYPRCxQ=kr{WNg)%#$)SXn}%<{Bq+Wh{kH{-XEdL zqM0+$Lpmp1k3cJ{e<^kl1ES6n#$sgBH=k@RjgSx{CVa!UT%Q$c#9gv9@r9KSw<8S` z+_rWmU8YYwd&4nJbJ&zk+qF6ojs>5Hm)W~!^7d-7`H z{|oQBfR4nKg*-lJXIj^haWh_1sV!3!7OUga?3;i0Pxk~66_aWiKg+_Io0bu)O>XYQqs$B z`P})*O^7xLV);AErWrp8>pM0Il#Qw$U?B*-=yO54G*LY;2gOvW!P<-qgWzOJC#H2k zqtnywf+-^K_WUFd7_69SFSM?U1)c!u>tpKjzLO&y91=3|7`DrmpAUNyDkj%z_oU4R zcM`17$Pn=SpzmjCC1{Wh2JW>|B3oXdZH%rlw2RMnBb&(Wq8#hX?k$!W*qD!)mASGN z>DY%&CWT@{7ou@ zS1s<(J8dZ+%wIqmp?_;5ac-4IZPL%*NxU?Phe?187J~tQa(*u2?iUR{`49t{ui3UF zBqxLv@kFz;I{WZ{8M>hhufRDtL2=VCsTxnZ!M_&1y_jz9-K&FPRI{b z7jN7qaACEr9J^Y*YE*Tz{kc?pH*&z?o(Bj-Wsy)VkhRvYFNBnQ!s~!lFa(@DbUlY2 zhe^JQQw;k)^rNRm`G)j_V1QVvDL;|<3N4kuu&K$MI(s!1DV-A@x6o=JVyiz9db%eLxYD&A zk7AO8y#waLk9qZGZoXFj#y?Sk$oxs8rcnQxj3{$0M_OAVi_wzdad&+Y5) zuPDXihwQSv#cb?eBst~2YbTW(b)d-0&4r*J^>j~Mag&=M=CGOY&PlpF#PP~aBjf)d za!T;qegjx%+I`HA3315YiUZ_9;{g`Ch#A3BTWbhA_0TAI(F)koLBIyTBt6jLXmKmt zL~LsE)m=iGam4$cx_dH{X-c+w*kY&L8(e7B6T3S9pI?ub3WK{OR711let#8aQ*RxZ z7W~7z(D3YOiW=9gD3n_D9zhtY~Y;AfjNDG2_dj}L~e)Qa)lKfr^;Y&+`9l8Ol`xF-{B1N; zR!XW4h#1`V4)t=5;RE=WAs>>V5^5`v$c~2Ahm?-8fcXm9{bN?VH`I5cVdrb>D`A37 zYu!rgF+sb9XBC^`58wHpX}s?5sBZiRKs~SOi+>%lT5x>%O6L%|JC;t&mMjjF06}-ncohMVd*`5 zlNB&(QaF%ygiAVI>-^%#(BUbPFMHgtd1UN+*nkW*dpXWIdo|J!yTVq0y!S4KF@>MHf!~Wa8uz*55*qMD%A#N^tq|53zQj;r9<=@v{XE9Nq1`^V#U$GZ^FQfmDP)3 zbB?)~>gD7Dk+A?cra7@ib28K==KDAmfEkY<2#sJ9@rs@)MfOC!{qaZda`&9^yyYoY zbC}}~YVeC0)aj2;tip_iE{+N2Wls)F*w)nN<;{3Po$12SLTX~#Tk{Q_=8;pHaT*`j z4Bk$ICUvZXSahq1ub61h15vdVgFZX?>g@=kk5e;e(=Zx2(`(wcYRQTFxu+p8%(gYR!)<2Ne~ zGN+0QtokfI@v;Z6r5*ZrWGH`7{V&pr&BB;#z=U@09Qzyv_UI<={AZ&$$%j2Y&mSLe zbHkoE`s^~ITr1hrNVZZmR~5hXDj*|@%|$$Z{BL4nK=r>@<|BQqoZUH3emjG);Nph& zUQUyjEvO9|kHcR_CQwGauv|4yd!yp2>hz2QWAkfYnAtSYoWNPpO64AWrF|p%dU_=+ znbvH9N#)AjdxG(K7B?O(C#lGtCMQ-c^xgSY9zKD%0da1FFm2#(udH>R5`nS~%YBy`2Udc&m;y*Km7vdz}ekGqw z{{)``U1maeg7KxaM`Io1W1t#RQg-lXzz7F1K7zUprU{m5pmfrQJya|WC{n!P*mCvE zwNuW!@|2CXCocrGA4KbfW(PX!|>p%XVbr!Jv=pcc9`t0%Ww!e9E23AYpzVM zC3Y^qlGG5i{8+z~;%7NsKYJ%QsUiU){qOuq!6-LpC+T}O5T0%Z;{x;w;P564et65RO;Yn!o?phzyI#jUhAmzpf-7p ztz|N&obf*ORVDQ|eP}%-{|YT^b|*sFQP0((^z{)zX{pTLiKE6V4Y^BE)SS_yZkczq zNy|pd+w~8dehOJp*DV!U=)nMI0jXbg{)t!Ze7;oU%p-@l0<-B>3GnT1enArCh2geP zMXc|5ZTz0S_Ypf9g3BLZR^;_orKR|SrJ+it@#V`FPjuA|n4ULr_4x}M+Q7@{>oboi z8|!wpt#HmE{}CZnVcdGm;c$jD!7iUha&Hu4DW@Yf}YPFSu6=jYW zatNcfNxIuY4BweU=V-G&sq}!ZVo>Al#~>9W`SG^m31J=DmK@}<(>#;p{)oTYaFEhj zGMx#mVOK9yp3j!Y`{61x-8oUO+XaI=lIXWu-I}RR+m54e+@{M7UDyDRG5_5sBe}q- zx05^1!dnw}JI+ASI~K~J=JQC*-~S+Wy2n*Z41bxT~YP9Ejt_oyowkaS{JZARRJkSQ3rSmbrB zh}n=kkR3G*c72k~87C%>!lBSEBjG-4qa9i$Sc+P(eu-ohwIQ}V&pp_ zA1DkhuGl#Ld)sE=e(#Qd^}SK{;~w{UoB!O8JIrL0-u1;as|AVljG@|f1Zs*kEt3lZ zV9+*CfB)}w#@3g$Kc-MK-`yrZ3syruvZuM+INHN!f%TU>&@dRhQqs7}9u-`Mi45XZ|S^ zpPxwS^<|aU##p_gvNT7>%nsobC-ekb){_bM)b==aF9l~#D8Td!M(>Xg>3`>*n4j)) zo&Q+(V}_=<_@%+EU66L%UGqPHT*!8eVHg_~xj}mC?j?tFn(tAZO*DGqFgopRo0xvG zXiH*&ehc7zU>WOwwYQ!9b-70u+mg*99k_XKS-<+#{qu+aMhdLNsm0uym4{SMhaRor zI_#);8VkGaChN*BU4!&K!almPgH0h8z!K;&HO(cMXrqRh=j z?#fKi=n0DS2zzpRFl5OqT*e=_*$LvYws+4i&NXng+6zAxy&TmFb^MBV8WVI-j^kQ8NgccSEd5q7=m0VXK~KZ7Ewv%ea>Ku2wa@rA5RoSBWB zxJ4bBm|!&I${aTOD&2Zb&eWElL5rmu%vq#0V*W^{YaU|(JZ`0EO(vPbg);($uhMz&g^~if!LWg{{Ep$BsCi3_ zJN&}x;C{pq@H216!b#1k@nn^1mp{a)SFrnTIoT>JqfyfD(Bsr@mzpy%-}QfnO?gRC zEsa_a?1}Pm{)sIW;v_4t*S8~Or2ThLhP7fUb}<54Uw0%v#DRwDwHV2|c&stxc!4Zd zB7c4^@skorjSgx6T{7ax#$6X`hF9*woDAHMKDK^EX$|T3InySF^|d6K%|c+=(iqyX z9E718o2Z~&3V&*stVP{Cp(skewOv)Un04?u2fhp z8HGuv85d_y_97%Bks5Y~iV`Gd&JpP6tF5f(3kbChk2O zS6xjd21JN$i|3O|&(dUBH}VW#`JJ6r(Y{9grDvAP6Xf_cqg*0`cv1I?uRIKJa#3}; zE!RLSA7{sg_`aixj4Z#jxIbTz&PUETLaPHa@!(@MYj>Je6`W4i$ZTKij4-q^#sz9# z^HF9hUH>WfL^v?iRnU6x0<``inkng;b&CJ8*74uM(%-=6Q@rtz6L zs{Q!@<(Zf<3H3a8r@L!50{D*`*Tf#(Z$eLf?1P?snj=*EA<1}e80qN8C&S-#m?O4I z|72maryB(2rwi&IvKorokI9iDBDFo69BJ%)1{xldZIzr`;>&en9wBkLFo+Qir_N0X zou736hZxX97J#z^3v^kU@v;X(E)*zuE8rdS@CLHk*iE`!r8pvCs27BFbK;G+R9)>o zxlp;pZ_uu6lFPv^pRM}KU~CWnSU8)fhAhPc`PuEUktHp4`2xQmj!)$qY0 zz#}`X8)aR@g{vOkHuRjr5!IqgxekH%Ll1fXLtArC_3JxT6Yd$w6Iw-?|61i5d1AaT z(&t?W@`}C9KhQi}GcWPzm)!Qlr;>i`Ie!|ITQWz(M)oqSv>OS> z#~}NP)0KgONp!aSMF^K$waM5BQx_PvZ&^Pom;T)L@^7~VS*Ld!n|V1rt}N4-Fy|UI zG`LZZlTW!z4N!5U#eDp9HVCM9Tbms5ZEaD(Vr1`j?a^Z8FM(O}OLs8LzHS}D>)Kab zyFEW+#&OaQG>9l9i+mJS4b(vD4IX2oP=pRITBjt^;=lbawslT5_|WD#jFNgJNh1iwsqA*XeMT4(&}?=czS%j zFOmLYzG|%Z7R9b-TxG>N+1r2OgMj)0hA;)^%+vBjRs^0HL53a~89E{^Y&pWJNsG<+ zgPl-0W~7{MxBY#Mr9#a=nELl$QtyuDrEm>SJ&KHrzn|z)?CbL=2f7sv-BND~c`Q2v zWI)UzYHcEJ7#RvPawN0gjBcXwTn5J(zo>gE&C+^-vA9@)l~~c)<6cYiRtWYrvYOLV zP8gKncud7!CZ>j~)NK|k*$OSDc5M7aAW6Bn&q>nD1|jS-DB0kW(IV;^irsuu-{ivJ z3z{b#-0mHl!OL5xkN(sh**A@wge`sxbe(=?1t%YXVe5NA-I^V1!FpfRObBVPy>f2T zMdbVD)~KIxd|1Kw(oYT2+i|C(KQ*1raqR!Ny4=he6d{n~=-u*gxYR?cT}4s)rq18j zuumftdSXMh@{k4K3q7ARZ@_&%sptJJz)DZoZN3KWIMQ^P}@L zSDz9kyFy26?NLx~UQ}#I^!aJ4_K19#^mQ=E{(d?+_!1O$){n=DZ5D)BhO1eI_W0XX z#eCJZDk{Y=2jJHk19IPru6JwF?`!Ne{RFp43hq)20?>$-S{gENG3V>H*T199%1)xi zMWgL)(V6!GC86iOMJ-k_?3rSdZHF`CUUMdw9q^>{)%IU()$xIcM4t~Gn-M}-RAJBP z6zFtU3erR{Gikun1aZ1%^_8`wRg?P92I4-9f7+>(_`b;pHX+_Duc`UX5gOhzVcjoE zg4|h$!zE2j1ffMr|B-IvcFDIvHKgnZ$-(f-V{a>sOiks7TMfWlKSF^-n%O5u|N?YJ3T& zrumI0q7xfyDI{hX4QRi7iErV8QCDr}s9g6cD~PdyzE=vgKHRg;$M=2sp_!~lFmI%Ruqnrhd02Ql~UK*TxD?)^&>R#~I)8h!Z zGi^9GEmrdVt^lbt)vv%i?3v4}`OpcJVwl!oAT|hDmCOCF_#O)=qgob^_d*U8xG-oy z42A}c1$2%Sj-6_b80d2I4*ORSst68|e+*Bh$&!1)*jMq*3M88~{(M1VK3i(GNNRv7 z=vgA{KR8>3$Lq3Iw4dF@*qn84J6t9nA;d>VY*Bo@Tm}F2ny;RTMCz{uNZwmndC!tV zKcBHr%tFXMbwU#jx+uF1Cz|Gq_erO`2df0>f%eBnYA<4$Mrg&zrOrX0amG`gvqt&L zs*_OpE9bWcWFUVI==Ep@4{s6l)dwaU6Ee`d#429xkt@K7LsoH$Zpywm*a?kR0Pg(L z%~oOKY!pyehO@pF7DXAPtKCxgRmB!hYd;Y!r1!m12+{iaGTU~>D3l@bgkbhdLJzFtrCMEG zP4JH3$)P>is}$R6&(_w~%_m=f8H5%u8?!IXJABEcI5)T1pHR!^;XUJ>S`Me$Se6mG z31d~8k$bGy>}Mkl@sdFWV=l+d_^M}7suY0+n_NQc)YRETa|2k0OkU=K?x#S&fVF{C z3(Sc;R*N8aikjNJC@PK~QYpRA6wTr;hC=`husfToV5xY|8E{Lth_*%P%n9Od)ztD2 zf5f4Jqf8I{MIrfPCp;v-hL8Xy;i(?8VUU8NGa)6q2bnozo?*lBwS{9Dy!zw_hgz5S zztjUa$j5uTE@GFq9O`1b>)&r%s0VGDCy--v0ml#+ zmVK`#KmQ|x!3aF>=hrTJEP)=;0MbmVDvou7M!)4jd)LKZL#X@gc$+M@ujZZHqQ#-w z2o{4$>&?=B5<&L^?nl zeVpF?o8zsWV?OyAvj-r*LqC047JSVTIRaSYHZb(P(H|!FGuVfZ{$ck|#-T{->AMa0 zV`r>NZn{XUrh)WMWab*zx4#)2(qxgE$*anfN=y*Ee-QSTv2m~VZ&RT5ML#obVs6-`bYR&asa8Oo`P&SeEU?KJ zu(cBya!dZNvpFFX=+}vV%|s&{k-6G4fV0x6wq71o@`gyfvXETUD7y4F!h}c!C`nPl zWGzDWh4749gW-lr-WROO)M$41oIA4=xR+|;`dMdaQEyMt zf}tBSSP=MUm#0h0XOEW7>V?#!(oe5;C5&nnD~~ni_FKL;cqYlqD*?CXqWqU5AKUdH zO;!C7*UM>^Qp^T@el)icuz?`lQ0Erny3Q)wkwCLcv8=84EDT_3@+F;TmgYqT(=K{L z{-Yb%$~owRf@!WPX7ZYM(dLkb(VCmGoGRr`Tfa?`RBkT-uL{55@rJ)$l9G~I+#iFv z`0dSkeYA>Wc<08#0Fm+)Z2l;au=t?a%mF;1moaCx^?sH4+Ut>nCEIhVs4x~l3|=VN zmPs1~&i+jXD_+|@Gr0lCK>+Sy@KXT6pd7wAWGfPT({0AK$->;#{=yL?XGRv~2R1&5 zkkHV=eWOE}hD9||=j%eWqW}wpL+%4Xg{C=mQ!L#!^5=zSuByc>JCJ9(TZ5r!? z?V|qUIgKa)~xYoqo%BqY^1LVvYdZ41J)@6{OvU_z!=)$ zeO5Ft$w=z&zfO`t{BI1`yb#Npi16#ZdogF@?B`1COPxd;6){a0F+t;nYz7+qZhNM>cDTK*5P4P2H;i~fX3Ih zpA&mkSNDl@esT+Z#&Z*FXuDtl$q5jSz&RYhJG4)!6@p5e)oZ1wS%cysjaaqhMvEKE zG#iNLLIA{>aqK@SY3Z>aBO_r#X)LoJ>px()#^kO?^WfPFf@ECwAkx4`KHbg+-)lu^ z-=<0ifw_HZuuipM^{d4JD}0Gp+jsDxtyZ81&4G>J20)8Pn<94tCli0NR|qKLz6ZWW zL+#OMNeKxTjKC7!0B|ODRn4hYX6khmduu!dtPY~Mvc1*i7(D=)LgZ2w0FBf3{riJ0 zU>Iir-(`fJ^iFP5*(IxziwVHSscZBFt+O zJUo{Bn4B^g-(d#sk5tm3u=LEdX%X9AqU6K}fSb~8F zM|xP}{|@R~c@Y4oPiOH|r+P5pNpcjd?nNe+$Fawi{-l&bS;O@!P3&F}$~?Z$TLP4} zp%Y}HigjP@0#$7%uk0ZPHQ`V_wqu<0Y$0#biot&9)S{wdrd3hZ8(&w_OZ{>TRKwIeux4>9L^BV0iz&oX~s{~b->%t<`k0ee$U=y zGi)%$E=_K-;>g1<;Pi=Z1phdcyWOgd98hZB|DP;8hWlo)X+EiRjuh8?wrFN=mvTZzU zluH{TsneI&bK|MEbVTk54Ba$W%$qrT`OV~gTe|YcjXTT8zF(bpKiRIh;}G}Xe@u@E z93*?QvnMH26-5r9vYj7vQ8f^#?BtUR?Z`=tM+&#Fve`My(o0-ge zzu=1ON~N4FF&Q;30KH?Co4k z?OgO#JseD(bs61lZAh}9A!#xIkk8lu@A!ZG28!bc7A`JNI?V1ycTd=^>P$RHC1ShlpCCG6J=VQ zY3kV~4U8d|n1f@$sEfnPuuUzTujJTYRu+Vx7i#y!Sktw7zw`ENrHKNbE8aG~!M4z6 z&`EzAKpOac2B2sSti~x}wHxv262$&0J9ykdvUo?iib>eDOkmQO9vx#Mk4I)pzmn6N zE~>!I`8v=yudlzJt4-m+n9$oUcMNU=TI~7>>k@sZ@vKc4t-pvzRvpr_EcKmCZJe1Hf1dv*$N$F~{L7;k zgX9!CnURB!B=1A|t|k{_(1c~&ge03tRek-X7GBguex)E-Y^5edQ+*i(CE*A5y&srg zF9u>@@siiNl>{f=I=+W{P34pz?pVCqh3-0eF?pFRA?-oq3XXnVRG*(I z)4xnEK7Jxvfi}XZ@e%Zp(6`bSEA%4}BAxwlmR`R?G))2Km%JWiob* zYt|8oUdoIMKkaJvlfg8PE>48bqQ2w)Kp=7c(sP9Rr$_<>;uFuF-$>)LNL~WqA>3`4 ze%Fbcy_2<(y}k9%==FzYAf7|mvz7nfN3pV;Ocyg680j&D*)7Et8-3P=iELkO?*)8+ zHSIhVDVy*4GQsOcUCk*OCMf%0kE5Yp*DDUxH7LxBcDnp<3}{bGnCrIh8+r=*7Pn++} zHZS?m} zE3$PaM@fsK&p5Wi~SF@hWOo24tsZJ6@_u;1%4NoXqy){H(DclA6kkajuVodWKz7 zClpi{9eeXWU8lwJJiL~&L~M}kEcxQcR+Yk2TIq*(0`L{=fQ$q3D&;~X^j%;$N3|e2 zk#&0|T4g3;!YTSino0FOU5}~?Il(%D6^;E6iZD%dI~ov%Ns}r()39XDUs7EK=KL<) z?E$rfHY&h6{~ccCY)X9jIrQzp?hd@;iVh{pQNDmn0FMjnA02!RiL;Rm7n)3sLBkWpEzDZSVn3i zka`e{o?R~3ob9``Te~*JmI^f;BH6m+SdHgfmYGp%6i0lcrSA?0&&P-)A~(a*wX3Wp zZQC$y(OJgZ2!&`53H9;1JEY1&&X1>)MAWOx)~Z&hRwKI9NAB5ka2n-(0(>Nx-k)!y z4C;aO5h`Z>PL}=R0bA`8OCJyG*z_~g&a*cQ^S40*IHpFEQ;?0w;8<$@{f~lZGz=~i z@EuEv^9xU@kOnlJY4Bz7>?@CaP5#0QqtrA=Sgi}L2Mxnb&dWHg6jw~8L?eXMDD*10H~877?DCV^fPQ5?C;2{CMV8R^!ns%A2$GQW8AFmi1S z6A`wxE4K|XM9->kG%d5J(+JQ^OR3-o2uJ3cMz=~#*b8lf zie%+3!Dj6S!PP%2C2qk<%D;pnxjrFrGm4W^i|6cAqmt*o8%}|YI8uSF5O!O6F=L%) z!nkE|(Vp=Q!8{Lm4}8os?y)TJz}rg@+F~ZbvsEX-ldI3Tl_+tm_wC1(+fBvri7BXC z$M1Y_Kcm9alaM3Cl|%6EKe}^{j6rpc?vfm=(`T8VhmX z+@@okSHt2IZ+!`s(Y$=GNv_oSF=$V*8uG*is`apyx99pz$Xx=3Nvx#H?`by7V?Qfo zI2_gJP3ot5eQU!Yvj-1Q#0`v*5UDaU;{^_VMF*>oU>nKB=~ogL0fV%RhCg_~Ytvgt=X}=6IYKDGHb|C%jhjQ9fN^|0vb@@UOIEK-HMqNTu#)f@cw$0$GjlS%Fte{leS)q9S=mT$;mvP!7!wAx z4&QnhcqjNJF6=DaQe>Lo8}3h0TxD`i4W-`HI*4|vl5AHx1Y*dYvn$&NEh{%?y z!{b%3jZ2e43(AMese#+|Ko^kYY1V9wL)h z+rL$#SYD*O3})m@6CZ>20WURc+LVotrro795a@ztbh}bY2qZL84&LZqXZl^(I@R5T zq(p+lg{EQ0D$N|8lzb}rZ|27mGWxT=+NZp-P-tN4NPc>a>dgs0hvNLa+Q9oox5w@! z+^Q>%ZRt9DxZm9#gzKV=`lO0+Fo!lvBz*2xG~8MAr}QKZVeC zT(lPX=b0XopB01OLa2*{sjVr~Z)cXDV%^so0updywc_3iB0Ia?bF4>GF0G8%#4S>o zq{S1~)b1;(v$2Aj2{0ikxi6GyvU3uJ?fK)szlA~ppGPB5RPPXvQ4h_Kmuym`*hp); zq5vfx!FhRC>As$4E+^l?NuCl(NFAUA{T9Vj{?v$>B#Q9_KWi=;c5emA_y}}U1iKp~ z`g@uAFTPIbw*BzEGf+38Hkk>;Qrz>eak}AyW9!?@xB`}`B6=k|$iLw95)uV1CE?KJ zD3{=ogRb=gjTF6nSV_tEQ9eogc@;D(tg^%kqeRdwYZO*cW>&0sRtkrH+*Up$BAq)m zOlRSJwdVExiUtG2*W!lqVGFm831>{5N^}!eOT;eYiM2u2z*}?7`E;k<>N^R1khWKj zK2-j@-iy5l?bh1wc@P%tfuC|~XL$BL*~J*5DBezHHfbEG4dN_~>g!fD5EVv$oX$}7 zD-R|{Zd?&VDifj=c-I+{W|n8ZH=Ti{uhTg#bD*bKcW$jHD&29t@U>!D~!Td)&ps{SGwjY$Kf&T zgE6QK>Q!k`q}8s=1Ogs&$-`@zS+hUs8iZ*QC||l8b@j{E-qU4Fa*{Bm^LsrW@0^9S z^81}{-*oC%Hq^Y9v4f*jQ8}E9)_;0PJnZ}s ztt=>XoKnQefKr*UTEr-Hu)~z(!`$i6l5JUMzV#%(w+Xr7^L;S;h8Ar03|cTM?JIMO zvTzW!08KVno&4G*s7jeAL_Nc4&u)$BKgj&x3AuPF)QX6_j(Yb>x9bf^#%cR|0}zib zmfv+IQjyPjP8QVHk?QFG@awCov9fLW8>vHEBG|mgs0*X(SzqzC*Z6(YRERY)i9<(X7Gt< zU%HsCZ&>Xj)d0d2RA@a#>y!vjXL@xKZ(D9|?-=NgLlcI+oPG0BbWvKDYco~VGc5{L zZiNGKlXwF-PCE^=%?xU4mD-Dh*D_D^#5wfVb)fULuj)0>U*bP#fyVc?!Y8?`yBtDO zvJT`k42DNU#$5~y#eRGznpUK3a~Pj8lk(;T6qdL;7&C4ovU?<~lKS3l;FTMMGb~KB z&dFUoPYR9cmS{i~!WA*SwWme;LYo7q*m=rB%~@~q`suFFY+O&E%yif~`Aoa#;_^bs zD!JJ^V1VlAbUR(4xnh%zH2!c9rn^bl%?G-9ECP->e_pAPy1@!!nC$v9M-u%)JUPR< zBb6XE>s<6GvbKonVq0ps?1id38&!sJcF21=>@TAwck*ZM(UIfw<_*P-p9_#+KsWBR z?;=GKrE|Bn`Hz-LCiZ-{Ro%1_VQFT^@eF0n2$bIADe0pMW9gZH(3?%x9COheQ`}9= z)E0N#L}a$b#&+MlToD6rh6v3G1)CAZZy96fRVOz`lp+o%i+jeg6(mC_8ZohvM7yZW zHadD(y|*j`i)AyAN4Qi)GJj_d#9gK59ZI;<>S;_4nP63DFlr!hV%v>;fo?5EMqM93 zMWr&@#cOv{V+CLLnw;JG26G#)bJ`uYfqX&-H%q176<;dd?%K^T0Ux(AL^Ph~U7Y*? zEK6*XS9}+PK7-#U6!tN~EL%Dae>4H@_0MnVh*KQVTzLE3S=-4igBS6X(&dQ*R#i$J z9t*pdiHa#^2|K{VkN1PCMsX&*geQIIF(v6HlSimdPp~~PWS+!+L;-?d}Ec14b8Y)xoQwaYlv=Pa?VI-dxAc3`Y1g*{3(b>eaBcy7o(_IodCJ?0!uE;eG`HUg z`r_Xh02ku4BH@>txv3eRd}(dq7Nutx;$IrJqNxTcXQI~@eRRcBAABf(xBLF}ixq=d zrFW>~d$$np3`fOWEz5eR84uSt8HPTh1A(&o-*9VIZ`WGh&3Zc?p_8QD)eK~4*}7VN zG^^pKfd)CB&e&j+*2km;aAnn0`}7~PXmJ>r`s@e`^N?6+waGzE^*kV3c!YgFpsZuDNMagheRZ!U5#;-%?Br}s$myJw!a zuBt%sM~WGp4P+m_@F3I~^Iv=Oo!{j;cS_tbB-)H>V^*5N>Czo=xxr0X5~vG4*LiVJGkKn>P=Ze31?HAiJ|xB$29_Hu+n~maLgO;jFK8 zKyb%*w~ii-q^EaO%L9cZe!2T93E4nXE~1ij;hxI8V-^BA5yFVvqLU8{ajhl-MHK2Y z=Gb`oNT-r#BkYtX-f!4P6%f4c%!s)3e1mX4K(S|196xATfluJ{9q5FziBR1saODpT zAZ&GF%){mE{a!HoM&g`It{>d4)xGq*1tLh>8D`GwS3045Cd&={Y_D^rcJxK4lpv(Z z_}e0f`u4_8=UVq803*s5xL);y zQ-dR4TH(GFW#Xd_x1thn{b3QJ%%AMcm3_ zq;X))Qpa&h%Z{YB+^>f4TEu0PuA5e3gTJ!Ozm*k9(C9QXYupQ4&%lOC@gg_vX~dJX zKtgH{bAf>g9*kq%n*X>nht=5T4x@}yJP3_5x66pBna@bWoTJ2~8UR9^|0uPDjg?gH zBecWlpA;qaWv9<6J?cI_-^_XDj!rNl8lLA(Qvzcl%fo8b+Ehl00F-t86J0u%02b`< zNbV@i7u@X7O#g=2Q(4$ASoa1Tr6g7p2PmnPsxuTWv)EX8gU^PYLX|8IZ+rC#w1&$f z#|{_*+Q=N>`2u#AjDy5Um>URmpg9smp~E21>pb}QUvUnSF+u{{NROd4-?2kN;NS{H zQlbkPz3s9+4C!4r)9Mm4K<9!^2LOTMByDSC`4tpolE|U;Ly>px3-rKxczVc?HcSJ@ zG5BZvABL|A6#n~M!+)Qfj=0+Z&ykgrsiWtG+9M#9q>f_X=)`KPiHTuQvwF4?v(=5P z-C6gORD^ShdCR!F>|<(&NKogI*X$BvOQrU0gIg9*e9kI3EB|F7Ix0hA}1=PXbWtlR-xCiRr+O9dg_lP?Kkm$USw`T_~~+CogKI1v9;8iowf7e z%&X5yw)f9f<9`+iot+K4VV`Hxo?Yy-hy7U~bha>bGBr_gak8{C|E(60sybpl`4+7O z>G6f((HoC4_7YHbK1twt)+J$W|2gHU>)E%%xapMe44mk|YR_X_3x-!%MR8ANk66?N zffOFAtF~-x%ihc0yt4*gnYqJIG;(^|iV;(MtN!xg?9*|I`%7R)OBt>n>9hgMOj0a3 zgDzK>6Jdjh_jpBeG_2O<8t8kFwaT!$Y#t%4zYevmDpkZ}?LktSp+iXIrm{`64O;sH9;+EP%65g+9tq9JW# zD$cN~BWqOA=53f!8q;dObsly#2z-f&1m0;%CvDVZ&3wB$6f*JxB2(83r5KmR^YnY7 z`|VsgC*=lVn=0im1uCT+ULFpmx$X~_So3EN>cKT@()XkVYq*K0*G-~EbKXauJabhFYavODbNKW5(XWoQdQqS1f) zgL#n#F~(!oE0@|>3QqKy0J9B-{7Q3hie|1GBZwoO$=!Ll*?-{|^l!;X5VfKT~3V0%4t z2mQGhVPbEr=w$EU%w%luWcsfz`u|!G&#&$SNME6o1gm>l?j9B8h#}{0ox(OTe>M(C z=d6x6VC5A8rsFZXnh5ol-l7=#egA70tqf$*9Lswq>iPRbPdK znPQ>T%)vIXc!9%kHVBO8jJJl07Uwibg(h$ZRmOAT&v8#HMldW34cTlE4FGfAa5z6& z)Yco`N7_PAJM#5%a8V^0*Fyyly%m+nUV*Cg;8c5oMkoTqL1WGm2LE`;!(8+5K0`x% zSi8|@otJ1mYBrF#tNp=p)4*o_jTN;I@|Q0wi5Cwl`W*3v^Vo3ld4Vc+{@k{wH5=kO zx{WKD^pqh6#_iee8{4&7EPGSFCpplLRZrI23)}j;K%#Ug^y~a{#rWFDVg)IS|q zhn^OE%rg-Qo-3(nekQ>a^FsTqH4*osd(S(lSiI3yUM=HgD8@8}hy zATSWm8->xmxC>osVF##S6(`))g;UUnlm2>)wf9rJiT1ufPQ!t79zp@su;tv~DErik z53@ayXM%>Q2i-~AwskSndcUG{?eu|cJnAm>#B z=75bJ?zQ1ck=rF3k`uwuMCY|w!?iSrTBv1q=V49(ZiU-UFQP{H$0UNh?UakMb3(V( zS9r_Q9(t9jWDgfx4LI;##}*(J5v{@u1b1|H~Qurl!B$& zPygQk00GJH9CH8j#-u;K+8^V8*ruc?^LGP(-$L;R@aLHLERDZxsQ4B5_qOt1fz8kN z`rn((zuNh=*Z8NUqv!79FP+C`{saS&f6q$(-5U87`fGvqPbe$eZ_r=MwZ9tp zb&2_>fePGz-}pZkoWEN6HIw?&3L4SxPw;DA^{a)y$J9UZ0DvSh0Pv3p`z!qKp75{m eG19-l|K%4IWniAaE&zb|{PTYf;)xVL|NS2j&WG!`{?Mm&M)2nk*aU8C@pe*;D)f9sk8&paeW9-^B)$xRksT+hmqrtbB>U zec%tlU{Dfn?~d&)GS*3d`}Q$CmS_Pq>LQu*VnG5 zN65?C1KFo;!^Mwr)Ydx6#3Fpjj<2sDZk7T_bg1i6<`Q2Ml`bK$z{U}NzmYZ%QAc0t zZ9p#4E_~6q(6K77zKqT{@Oc8bF@`y5`Ig>G?{tG%3MQ1oYZ1p)FHezNQ-$70xxw)! zL8jG-uAXzs!1&oRTVPZR>eBEETvIDAi5wR}<>yalMcTblR*Y@lZ@fL*=psVT6mJ@N zur2hNb<$t@k^7I&0u-%6t8q#>Y)5>$MX+;Z2ah|+mTsxnFp0WX2u&K(Bcn{@@hEJV zR`Vd~;tDT#8T{WB^!3;CwJRJL6M5U_kHK%kNL)Q)U7+tYp00kG4F`d27lO`M2-0gkX}5Flda5e4E1CHZOh%4sbdU6nyifm9Ak11suyGk0T0QhaCP z^LJ20f?vq)k0)XGIT@MHm3jABlb>G`sHs@Icw1qV?#NH!p>JZ{ekz{QhI#MJET7t^ zOu>b5#WC_4LY;Z;t6j}?GMMJk&5PJo+;`mXA4*!d{FI^olO%q^;DpnsFVgr#5&{4M zl)E+S?>up{bF?zDv$Ogwd;P%~sHYV6WaYp6C{dP^>1G4AAUy=Jxuv*bqt7|BQtYek zp&|5F(=X7FbG|!UA!KOO)tr`Lg|-XyI2wYuUUH+ZLt~zIFcyBofbqn%J`#Yn8#*0= zMld=kCGmd^i;1znyH|XGgqrMx*&rO#$CQr6_w9;~8b2r}pF;esVLXt_a+uA9!_sM# zc;Lxr2CFyU-+WNnFZHjkt0POMH`{t_5L>u_%kcLg9XrKGloCYo0E}%U&M~;q{*Nd<#Lu?$^ zXL0NtwSvE~*R~CFV$G@-YpGO7^9a^vcv$%g-=3}PXcuh-fMt*X$vm|(r5fnHHhMpj zYiJ#N2rHO!i;@EKJi8C19n`C-zc-du?C}YgC0Xn7^(Xuga8sKY6`6Gu(2|v$@!5Z2j)bKoKA${of>mXi+ z$q&$&qR^;}L-Khx>MnCb_HNw(w47()lo+rPC0KG5%f`J}rThS|b?wFUh#kh~8~*C0 zc8fZN>h&h^7xOgJrqvGUt8g8XY$9s=k3&^~FDDqp4pQ)Vj-%%>K&La7e zDaNN1vVUmFt8ICF0o$%95r9x$UAg)o*zz8$MQXILZb}?u;40p>OHMMRso>@4$ zAL%hh3`0EsN^|z!5NClEGg6**EjW`4gi2{X-npcPWM!z zQyVzRL$-PwZw(6Q#)pz%rNsXsxt&RMA|yUxEe@ed8@9NRp8n8wwJL?R`tWwx8D7_t zpj!X6*;m)5+o2v;V~qm07F^u|nxm!y-|z0wV;Xmo-}f&hAv+0!*IUu8xK-Epx~?Us zn;cTK0={>H`>U;+p;#Ca=SW}))oiw_$&Aa(Kf1Q0_6H?rE!R2&6g`4Gi$^XR2H2}Cs$)v&)xrnd@)|L8kqvO|>)U{&=V|IF@+If+BB^H5)0LyR@Avw% zGx4vZ4?A_-`3R!{*A9}R``2qNvpVOJxqT{|5d_zxo@$a=RqU_S9&SR3qSa$ejGXAbgeL-FVK~s4|I%^p#$~*{o@}XlY~v z%hArvBk(oE?2J#WKKSKue9&qps8-=QhWHDMN4D=c|xi-_o0mzrQ*7#iD0;u zT=UOAMT4M=vbUB6Yf8eQmvZrTsp82D&84gDnyD z4-yq9-to-Y2tOb}Grd|fx~YMveDRH`atb_Ut!aTwq-OeTWl$bG=B7T#URPPqt~6H5 zALrAs~WnTF&C+fA+^e=OR-!hPFTfR@KGtQ`fUCeVSv>+O(m)Ys0yc)Q( zumOPyKPs1!Cq%uus9GKu_{=Qs-+QU?%^Afk|3#E~ThSWdhk^;ZY4qMl^n0WnG z#UDbcVY7);6Y;)Qd~{si3XPvc$xg})90(C{z;YrEW1ey;9%amxp1+Zzmk$RyPK% zg3}VS&3xo&kTvku9CP}y(_uMIh7h3bm8TC~_y%&mcdy-6J6-@~!Q~&9Upvdc7iSw~ zh@yBimDQwiq&A4NJgTo-)j(Vn`Ee#w)wd#$6uEI#0;yb-UieK{P?}kR`QA(>mcCBc zjLdvv8D@oJsj_x2DJ(Ko^4-u=~p(?Fv!@#Q>&;PPDScJ-rwUc z>$g1|@1F4POwyiocDLPK4<@udp75VntS@4-w)*_|u@j5C;&c98A(D80frvQqm^|dm zaoL*j5lyI}AL{K1lt@}P8>lljyQ`yv)bT-+oUyfq`lu`XK?a&`zT4+x&17IQS9R%WRdGYTH;G$s2m|6^#` zro5}rYD&o4gwpV-A8hY}KX3I8TCgbXE58tD=O%6qHQD5F^zC>}Q^raq?)i!S^v0O! zgUmPnpmPGzw&%zjsJA4#-8?Zej@#o6p?I9pLawvnih@q_vN3(#?`TlTC8FH|q;S0> z=LE!s#E29t*%#{&Ydi1FDC%K1EtA2t!8fME#9x}jl3GY{o&769P3Hw`XKRK+I0g7m zKgZ2C;i))>_2PNe2|H1R|PT9UluxOg~9i>#3#F`yBGp0S@{bZ1|mF1#$ECc#(sDso>r`FeF#pO zP2oX<#(JgRf*HFR-ZK(XNqgruK;j1F1P2?bb8-vjPoXpYF78)_cuC4+|xkHlZh6ZaQq0bgJEZesL~pnbhp?};`O6k3Irwl8wxuvNt0=u z8|1=>oiSQ^D}U-989pIz-cZt*{22*0=GvY9O}JQsbpE!s(9v?~WRwY`tf<)&<1I>uQ z-;J>gs*{?-%AOA=z4DCZ{G0@(XvE4%7U`@q*XZD3>GHOyMIx7(GR(OuoNb)VA9syO zU?~1ptG6*JXp%#r!Ki`Ik#jd34c$tDg0|j|hDK$yTfp|Z#uA~9fs)JW8gm=3YsMX} zfpSs@H(RCN6<;dd_R7sL9v`wuBIj{ zBYZ^2`_KT#-63|rlnU(Vt!uY+g8_?~=1=1{w>S(twIF zzoVUXfI$7Fn%|ND>jjQEHvl<~fm=^h*(fw)uk9ws#M<||46=Ot# z$1Rj7sPj{{ihI1zYaHuz5G<)p-{oi(!pBJq6xI>mXWo-B8XIiU`E-jmCAOEo! za=)uGt`7?U6k`Jbc)zFL-&VFx7N(}oPOLvKKXY&@cp)N%4H$UDcuvf;0?$Te{gS*` zt@7<4ll`&1n^WM(~M771OUJxo1N{OQEI6z9*<2~mFd+cq1Wglu-Tq83b5`}ao zc4N#zQKm>ME1a=($%ai2;SxwxzkU362Z9#c!egZa&FBAN8mHRTHZ~{=o14xSy2TG? zg{ekqajjJAqpR_IjWkJaLn4W{h4t1u(NQTnc%BX5XWz7~v8xXe*hlSyP8PIntrb+( zaZ=aKT9%MMs1u5VE29td0+h4GAF3^D)=UFDNN1yv9NFBv-Dz6nF7F1UqztR4WN^t| z2=;oXy~8mh$2A{!dEhmiW#g)deFwFocybFe%Hd>u7eIaVA+}$?no@Diyg?x`I#AP+P6)d zJ@f>D=8!>;qtmCIR{#`ip_;ypNZQMGL4$90($k%I%U05A#y70z|eeygX?CYumZn)=^_YE`M0|B(5{=^6!9U{bmQD!&m#C0ewDBC#BuoQ7OMwTk>JI{o zMr`}mT*eNQ7Chq>H!nnC)HmWNRD@yUCj}FqanHe{Z}%&i^xDBl9MExm7r^4FFX+q0 za}{_%$$Eu=5N+U*GDb!PXXMlCGff+Gdb8=IEoZKH7vB~Z1lCK@V@cDXyy=|qByOK3 z{Wkmfnnw|_;!%&v2WBKtI1oqyrGxXK`z4c%7hL)yd2-iv(6$S_4LY*F zggwlZO)n~Dx`Fpf0RlJZWiVg0s3fvD`GLc`)+i#Jk7Rf-p{od*e(uG=fl! zFu%PLdJqpnh##HFSi%4I0j3!sM@=k$10a(>rNKvoPRt4r(DK83po2v~6kafBKq=!D z%Uh)ojGS%;hqMZ9)n2#GPfE&+h|<}~i*!3Sm<)Ixrh1z6O7v@-eGYVAA|#zpPlts!C?2YDl{&D~QC`ajE! zJ4EGmWl!N6c*S29TrNZC4T%( z;*7{Mc3z5gV#&CXvWgeGBT|HHn?xK|w6RxXfixp8l*_;PnFZQtgM z!5yJSWjfcW7Bd7OYbawH|GD1x=ps%RosU(HUSs+tLqvN>%l?nN?iZwNGxe&f%jI?- zvKSdg#}8(?@m`@?m*#!9YC&FVgwtw#-oB@X_j-(CQW+l|tCn3D`{WHwxDpyc{duvy zoJoj^);gzFA4WC956UPPj2k9I0RsU4=&E2Cfjc%{OsbtUn=r4k*kQ30-dEs7N!QNi zz#Hqnj;#e%OU#OaD>&%JZxDLYD#} z=_NeLS;%p7Te`ieth<=|#nBQgqOam@YSdIg7`h(b4%cT>fpUbE@SaDjHw8muf_u8Y zWP(Y$d_$a{Lc5`Z8T?SUoGSZDRdiDfzb>2sZExUXFD2 zSywnQ3(T`L)FH077x@S3j4Ix;!wqezPEw76s;0+?z0#!|;@Nnxne{lz2OQN)C7rO( zON^x}lo|U*(V4Wr&1le<)6c-Ahn02kA@UqknbMbYR=btuud+jwl@O-K;ef6G%@Teu5rQ>7eIrPvyDRcFZYd zd2_6Z6(d$rW1uYPSiQiML8U{X>DWJI?a``=vuC#;xJY`lg06!=$1G_<$>pC3Ls;J=R47&*Iz-$YaB8&c#Y!WTA5$bKb8k{V|fMo=-X z=JNT*S(Q}5CDHpc3bkXCbFTB@q^x?v*@cIwX^ft-CIRK$j!K`NwIJ4<-%1M}k+6t_ z`r~<{u(+3Wqf0IBgeq9Zg1WnLKKJ3IGmLRS;=m@_`|oiY4x9=QKSK|{ogW9JZayyDq-E|SCow?PJf)KMm1Z_NmybxGbnBC-Y$U}E}vAG&V8A+wvHHf zPE^R;N`lN!{hcH3MV-ZR%vKIdTxx-(Rr?x$Er<|9c5xK3A z;H}Jf=&3H?U`$`b%kK$ePZ}?qI0p1L!nQ$fbWh!k`2rGlrq6%4D(NL$>zi{^ii^+clHb3?C z|1B;5YUfvl@lQ)fPnzQ|dgHI)UnP(~!J$v0$P@TaLF8BHujSW2q0+#g&|izOzZ&>; z0r{tae%ya|{6ChHzgqcq#`C8YJ>uWr;Me)juNMBEQ~$&R0K%jIz<*@eU*Ug`gnxxY e$o~TWS6oz-fqfcX0O0x4@BLF`4X66;?*9OdxvPl) literal 0 HcmV?d00001 diff --git a/src/assets/templates/student_import.xlsx b/src/assets/templates/student_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..10357f35669d30cc770cb931f4add595fd5b5ea2 GIT binary patch literal 9892 zcmeHtg;yNe_I2YTs z?6pA%dYNts|L{`Jx{~H9Hs7bx8LX`-+*uoI25*ClEfzWW2ukl|0yl#~5KvolI<)&>1k+Y+kGLK(S`fdheauK zSe23s=ayqaW{4*D%3rsE>ufa3v!55GuYCA)Brt-!WEC2r{wWf2w`4YSH~?TDDxqi4 zk@2u)b9ZnCn>aXte~Vic8cRxB>{z~r)=$85@31UyO4NNCtGKWDumlE-Kwc-3a=FY# zGTq?Y8?xfyH-_3@8L#?@zu$iTO#J=S+$z>Q`t_c1u|Z49}Aj3mWspHg78QdAv$4FRSWiveUQc6^fSZvlskazjj~t)1T?!~9;!7mxy^0E7nh-~sV+Gm*5 zCNggBPp=rdb&7(RCmI{pA6?xL3n2yWAo^H|v)Q3y5X$BX4@7a~DCk7`%r(=~ji^8T zNVzy%cwDK7hd9TBx_5&wRgoM>L|g>P&0@{rGRl=14h=kk_)Q?Xm}u8|Uk9COphTja zZFa}HVbo)Lb?YS4=xi@d@tq&ipPC8+#n4fZPrnL>n`GVzQ+>xTeAGj*>1a&vBxD`a zQCJ7?HYsz|nb};&79;FM@UKggH{lVh3=Qy}0{~mpZv|Qmu8Mm-ch$}_tunf6BL%hq* z$Fw$$lMPq#ADC0B%PZ|bqQxh)3#cKdjA>L)Y}Y5;9lF`shV_(BXrgYk(g}!G z%qt&lcKGHEJedo5c?2U-j@mHgC5Q$q#ajXVMEK@QuSilX#?&eOe88f-v^<*4J_TwY zmld+ZRJbwikYiZcW+Dsx3U|dE9nOf&N3pKO(@JMs3^Iv%EYGebr4p+q(b`S!c^QQd z?IGj#^Odn?8WJl=nOOT|)Oy$tCMko*Ip#KeN#f!1Ke|aXxpGo+kUT}LCR`1k=$~i8 z#|t~obO$hcWl;+qK|TgB`_bquCZuh}*ORfKUAjYjax8fxTyY8)OmH@+bM%HHeBw=o zI>M^z`Sc2&CU@GmCymvT=yWu4-94^pq(AX;Ck6$oJ7oufsYtcsF*& zsWoqbhpr!Jnf}VZ|MadwGz^pIUf5B+!$?yBrdGu6LZwLtfyLuv4-vEPdC1xIdNbzX z^6Xs+FAnqa=oH$3$#;f&B1P_0Q}vOr{GXXg6&_U?#%(Q<$0LT^td5v}BK=0^-#ML_ z{Kh^Ax`1iMseKnXMkOZ|n-1$~535q(SEvy-?RL}1iT`!JFW+D8`0R7ADZ2HKRj%gt zRt+7mpSQYtyxFG&N0x7`=ZYU%#^3NlqzO}fe0QJL=c8+6i9@`M$>CJmEC zr)&z(UotnxrAyIX>R+Id^!N2GEW0Sg8@nkSTj3<8W4}m-oh<+d(Y6>t#05fO%Lp`) znG_g1k7;p?v5>S)h9Uv_*TKwDV&b<{NaC6?2C-x-n6Nxs;bKP0*~A5F>B%*xBE7vp zW4v5;eUjjw$1(hAv>-dJ)VyGl)`Cs7-c)Q55iq|OdE-5VjMNxCu$Rb8G*y7@+nVuI zEITSFwF;wmy=Hi9OTPEM7u9$vS=~pTh!Yl-%1oUI*v{S@L=`CpA__uBRvWtUF+Tf0 z2<@k_;?Q?X)ivTEebqAtRK23BQ$>fF}GY}J*d6x zSn!jEC_i8{vG)r11`?3+y0Dh)aAvb=bnu>58Mk>HFgYdUu$qLF_cg=x36znXuNe;I z97Ec*!66`COd82f#3-FI?^B!X>$dF7Z>hRGiT>V{?m@)aufzL#?`Ptg=(PKqmOAoo z(o^joe!usx>$V<3tWG5;;|3{yE2sSKCS9$}?abMJKmYC_4|T>ONOqF3?PTZwRBtX1+39V4$1aX zs(fV_PQrR~ZaFXO~9BI(z(%4%uyYPb68 z#KYe2sveU87tf8eUkbk1^q#(<$HDQlx}*8|ov@jWU`mr#atBdI!anzj1EOf;qdnzv zzSms@FFSE4s`b?{TSt7*Cz#)>O2si^6zz(JCItT6`YelD*~>qKLeV0F?^ zzaBzX7V~~SSKYrRgdDwfT?(yQjNz4DUuc#^vE{*hE}r3=zIlZs15ooN7$hm@+!Dh2 zzR|`VvWRciyBm$WiXJ4^5zjE85{prOsH&!@P072X8+pv}3h)kAm0E6dWB^@x61lD= zf}Vf9e~D%W8OI?6ht{Y?odH8$jmq^J{Pl4gJr&SxKC$tg90hm9|U_`R| z*~R^)gDA>7wQ5pw344esH4-WrE3wEO(Wfi+y&Ol z(nn8E9kUfz5-uR&ZQ+w~;A2+#3c$^G&Rnfc)rF`U^KTd*aKelDdZyL7Y9%7c%G)Hu zcIJgSHWh2aFORXRgTiKLB%F4|h<_vYhdwe68<9pr?rfi)54i$YCb8^^*q1qCijlNQ^E)LbJ6iM*R%xoA%s zbB=z8OleUXC6OJ~ryw(#-<&1d)mS<>1$q$Bhhwi5+&!0E zk=N(j$yE2sipG4s&JDXmz8x{cFpsdy9^cj_cMyfFW0~SbaO|V+$mHixKV)RMDty!l zPwZnuOmW?OJ%*(M4iqvDK}JOkSay{xjAyB*^zT)uc}xERdcKK&@Om@#-& zZ9Wc8yU-oHy1o*#No)5B_(XehzMHMwUc18yOgtV%7-$oB_l0ktibP^BSyE}GgV?}~ zQ{JX?r!p@mQn73~(TdPq?lfbZ350yi)hzq|G%g2z|?hpEFtcL+QdJCTd2> z5>nBcUW$egf9JuV7bTG*U$m<$e6m_Od*HXL?yi%9NWU;cWUOdGqVkqV#Sl{*&%iR+ zU?EL=%2j&`w4aivEA6y{%5H~`@3C{eF4eIUDz+#VVnLet-4wsLA+0^K3Uxe9+AD#x zGz|u1!p2Dvf~wj*1D`is(^(m(zQN{eVRRxaD!QJEcu7dU~5|FEQd101VZA> zxgYfm8!Sah*AhTWt2Ws$Xn)segWSwW#Ra~@-6iUq_dtYD&AuW0sMg{}ESGJ6>u#J( zOjs8xnJA!_p!5mxWn8LvVn2%^i+>UZ*A(eTJ0`7nSg&-q(nXobGn}wo1&2L2dZ?^J zR)|!xmB<4&)T$gG%LdlSDySDodppRZVmjaizVl)iXlt`EAw`G3iwJVwAA1>)QG*}1 zbLYNk^vPkj1=Uh=t5 zE{N9OEQG0M*+X6qOW?SCqMpvHYxwU&M%_n?TMJFE@iu_lW#OKCcSn5HldDu(PbAsWuQZq#=blO3Mfw?$m4?5sQZFFva zgKR@%?w7Aqf|MjLSkg@LGxsM2lc~`TgRfa9;Krt{>FGaKgt$39l`NnYp%7F60OMcb z*TvP-*4*XydXT0<%n}b)C*iI?Mc9k-!h**3CMJfcc_uDV9C&R)deEh)LgMS-XGtG< zoIgC?VA3okCs6z-@vRx&IL)|m+|;VX+YLxd2Pdtse;Nua)g#oi!+rQ6aA83-ms}Qz zTB#j)Q!!XQP3|8CZX-PO8%mV|IPNjQY>qZJx85=y|UjTc;6IatRRCLF=)AD?AW=1 zHe+J4GC$>`w;@xFtVj6kIQq##mWJhmbS~l-xHuGD=nP?D4cQ8!;GITzkgO- zYhy-h7v;P{kG3Hc5Ar`R0&E^4=D%WWZUu<^yqhsZh%Zcluq=M${)W(dWCyM z`Rzu@N#_TPrJnTJ$!JS(ADivKT2#|vkTH!zmR5E$U-wOBzh_(|-P{JD^`-7ZrMW$=`nYZ~<8CyK7h(~|8$u}fqMM`-bK-(3Z!aj12ouk=X()rYO^8qR^Ekkf&uBf6a#wRg_7 zu05j8s=)iQcdD08Z1Nd{(w&tt#4NB}q5>29xf)Qm=4UkaHWrHWbBdXNEwO&hhcyog zsyU#UGA9B6fcJ+Wt&E+`&D30-t?ey;*JY&o8hBO|%a8DZJh|QbPUS?GCPfv2VR%G^ z`Nl&rVb6TY%;oqv+*b|jA;4E{mT>Bes)`Rt_v;UbYh|Z+Q1JHgu0m>>gGJ|^MQ=#P z#CfE!RH+B>K6>qpG=!2Bhn3dX^5!h)4GE^&b4geoV9g0>o-I?!1^K`>%J{`S8$my3Z;@(@{!Bu_$1;w`tu|dz1bTe0@{U} zTQkyY>t{$e>A1Z}m=9O)qzRFWuae4kZj{2M+b-IiX^)L*2`A&ZoGjuX7~hfl8uIwI7) z9bp1iSKR5m<*UY@LtRx1doXl+EJ9RhoAq7Z+>oy|=J$oQCHZjKs@GLcL#Bn+mOIEz zb(BatExR_KB$iP@J+a18u!<8;4nyMH^9){3nU?GWrc9J_8AkS(=C+dPt0nu-{K8Du8NQa_b?;R#ms5j@HwX6zVw3tGE|V!o+w7PtAv2QgRR?QD z#f-?0RII{YQzB3X{j)Sx%I%1)0SyQCP@Z8!tC?mFrXXhrM;A6z2WRs?8rc6UVnT;5 zINng9j~#Dd4WUb7#5<$Og|YBR)La=8K@e|E+_}x1$6xm2N@s_4+Z-msMkn?6ZTE=| zYQsY*T%Ukiy%AU%l}OlF^_Q%?2)bIMrvwOJut#L`squCJ1T3FMBQp0R8Q~_Rt=Xf4 zFofh5BlltLvSx?}lkLT@NIXL?O)4WP#>vMJ!Qvvrh>p*P=C$8ZMe+p-8kNXU3Q!W0 z#of$UE;B^^hM7R z>2W9@O7WYG9ktiO1Eq1MtHAX$s8#WCe=1u6ocx>skMoNzAC=3kOrqPWF{VQQ$Q;gc}7Wy|A#qMOrkGL1>N zNwjXb`8JhSBi&5D5O)&=bPbvCm%W4L7ysmY z1R3}WNrgmB)sJ?0oGnKDHPije#G5=P=C;o*H+U9PFkwf^>)MkYDUi8mQ}*!ai~2Q` z$uTPP$!<@b+!fI)=9&}R>qBmn?~CjCO>9eU{c6^eG9y0hH5nP!<>#{|Wj5P@qe8in z4hB8oY1R<;Uwp1Y;G3CD*2j57s$-ohQ9|Rh~8gGy~eIJHRD6+hNHeM?T7wa2->xZ8P5fma!>_sJeZkEeg)0f4?20Kh+@>#y*?yTHG~m4SbO|KSip3JB2I1prW?pLfszj!FI7 GxBmxn88W;8 literal 0 HcmV?d00001 diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts new file mode 100644 index 0000000..feb6a5e --- /dev/null +++ b/src/environments/environment.prod.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: true, + production: true, + openidPath: 'https://ru-iam-api.71dev.com', + adminApi: 'https://ru.71dev.com/etest-admin', + storeApi: 'https://ru.71dev.com/etest-question', + enrollmentApi: 'https://ru.71dev.com/etest-enrollment', + uploadApi:'https://ru.71dev.com/etest-admin', + apiVersion: 'v1', + clientSettings: { + authority: 'https://ru-iam.71dev.com/', + client_id: 'ru-manage-testing-frontend-client-prod', + redirect_uri: 'https://ru.71dev.com/manage-testing/auth', + post_logout_redirect_uri: 'https://ru.71dev.com/manage-testing/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/environments/environment.ru.ts b/src/environments/environment.ru.ts new file mode 100644 index 0000000..4cade21 --- /dev/null +++ b/src/environments/environment.ru.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: true, + production: true, + openidPath: 'https://ru-iam.ru.ac.th', + adminApi: 'https://etesting.ru.ac.th/etest-admin', + storeApi: 'https://etesting.ru.ac.th/etest-question', + enrollmentApi: 'https://etesting.ru.ac.th/etest-enrollment', + uploadApi:'https://exam.ru.ac.th/etest-question', + apiVersion: 'v2', + clientSettings: { + authority: 'https://ru-iam.ru.ac.th/', + client_id: 'ru-manage-testing-frontend-client-prod', + redirect_uri: 'https://etesting.ru.ac.th/backoffice/auth', + post_logout_redirect_uri: 'https://etesting.ru.ac.th/backoffice/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts new file mode 100644 index 0000000..38e6edc --- /dev/null +++ b/src/environments/environment.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: false, + production: false, + openidPath: 'https://ru-iam-api.71dev.com', + adminApi: 'https://ru.71dev.com/etest-admin', + storeApi: 'https://ru.71dev.com/etest-question', + enrollmentApi: 'https://ru.71dev.com/etest-enrollment', + uploadApi: 'https://ru.71dev.com/etest-admin', + apiVersion: 'v1', + clientSettings: { + authority: 'https://ru-iam.71dev.com/', + client_id: 'ru-manage-testing-frontend-client-dev', + redirect_uri: 'http://localhost:4200/auth', + post_logout_redirect_uri: 'http://localhost:4200/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/favicon.ico b/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5a76904a3109cf179bcf3ba3f17977f24e234a61 GIT binary patch literal 1150 zcmbVMOKTHR6du8yo8rQ?OMjWVEhs`4wYU;pbx{{0(t=pQYAY2KEVkODZWKx>O-*WT z-f13_OlFd~^ZfkIok`L{R-SO~J@=gRo!7k+!??oV%#6YHrg8VGVcakb;})4JY7#v+ z!=UZ@wS@JV3&s>rq{v6$RH4jc&4FD-Ox=Vgz7rh~`3`*R3|{vH!LW%qjx>ubIvg%ARnP>`3ZXX5msEsVh|76h6JTacm0W zD;Ob}i)a3ZP1u1Oq0#MOST133-hkaa$Dq}M)1X|d!XeutcT8gP8XJZt)UR#4`}z~7 z#Uku4AJIO}p`Oja+TDTmBa2?<8_ex3*hh!x@Z4VCK+rzrjO!ROH!8Bt7SxkK4+OHJ`eCtcD6DouPg!cx3PDa z!{?(S&@&OaF8qUigsmo`F3)`nk!7)VPxtK&8h~BGht*B2xgiRi$@)HP3Vm?uQz)6Q zZ&wfy8wVczunyUd)1%ONb0#t!Mb8J#7!U=m7WvLDsX@w?%>ALSnb zxJ%8FSFiznFJeb-ap)0Wa@cvB})0Q&NYvvHsBQ5R=y|^5t1fd`JHS H|GWPKL>JHL literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..4435d2a --- /dev/null +++ b/src/index.html @@ -0,0 +1,18 @@ + + + + + RU-BACKOFFICE + + + + + + + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..9d9067c --- /dev/null +++ b/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 0000000..b930a40 --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,63 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags.ts'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/src/styles.scss b/src/styles.scss new file mode 100644 index 0000000..88e6b17 --- /dev/null +++ b/src/styles.scss @@ -0,0 +1,483 @@ +/* You can add global styles to this file, and also import other style files */ +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; + +html, +body { + height: 100%; +} +body { + margin: 0; +} + +*:not(.material-icons) { + font-family: "Sarabun" !important; + font-size: 16px; + // font-weight: 100; + font-style: normal; + line-height: 26px; +} + +mat-icon { + @apply cursor-pointer; +} + +*:focus { + outline: 0 !important; +} + +select { + @apply form-select appearance-none px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600; +} + +textarea { + @apply form-textarea px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600; +} + +input { + @apply form-input px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50; +} + +textarea.ng-invalid { + @apply form-textarea px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600; +} + +input.ng-invalid { + @apply form-input px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50 ; +} + +select.ng-invalid { + @apply form-select appearance-none px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600; +} + +input::placeholder { + @apply text-gray-400; + line-height: 26px; +} + +input:read-only { + @apply bg-gray-300 cursor-pointer; +} + +editor { + @apply mt-2; +} + +::-webkit-scrollbar { + width: 5px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #888; +} + +::-webkit-scrollbar-track:horizontal { + background: #f1f1f1; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:horizontal{ + background: #888; + border-radius: 10px; +} + +.custom-modalbox { + mat-dialog-container { + padding: unset; + } +} + +.tox-notifications-container { + display: none !important; +} + +.error-text{ + @apply text-red-500 text-xs +} + +.search-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #54c6ec; + min-width: 100px !important; +} + +.confirm-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #609b35; + min-width: 100px !important; +} + +.payment-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #2a56c6; + min-width: 100px !important; +} + +.clear-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #576071; + min-width: 100px !important; +} + +.add-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; + min-width: 100px !important; +} + +.copy-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; + min-width: 100px !important; +} + +.copy-button-active { + @apply rounded h-10 text-white disabled:opacity-50; + background: #3176d7; + min-width: 100px !important; +} + +.cancel-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #9a9fa1; + min-width: 100px !important; +} + +.cancel-button-active { + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; + min-width: 100px !important; +} + +.delete-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: darkred; + min-width: 100px !important; +} + +.delete-button-brown { + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; + min-width: 100px !important; +} + +.del-but{ + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; +} + +.add-but{ + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; +} + +.main { + @apply bg-gray-200 p-3 space-y-4; +} + +.title { + @apply font-light text-xl; +} + +.dafalut-page { + @apply font-light text-2xl; +} + +table { + overflow-x: auto; + // min-width: 100vh; + // max-width: 100vw; + width: 100% +} + +.card { + @apply shadow bg-white rounded-md p-6; +} + +.mat-form-field-appearance-outline .mat-form-field-infix { + border-top: none; + padding: 1em 0 0.8em 0; +} +.mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float + .mat-form-field-label { + transform: translateY(-1.1em) scale(0.75); + width: 133.33333%; +} + +.mat-form-field-label-wrapper { + top: -0.5em; +} +.mat-form-field-appearance-fill .mat-form-field-flex { + padding: 0 0.5em 0 0.5em !important; +} + +.mat-form-field { + line-height: 1.32; +} + +.mat-form-field-appearance-fill .mat-select-arrow-wrapper { + transform: translateY(0%) !important; +} + +.mat-accordion .mat-expansion-panel:last-of-type { + border-radius: 0px !important; +} + +.mat-expansion-panel:not([class*="mat-elevation-z"]) { + box-shadow: unset; +} + +.mat-expansion-panel-body { + background-color: #576071; + padding: 0 !important; +} + +.mat-expansion-panel-header { + background-color: #576071 !important; + padding: 0 10px 0 0 !important; + min-height: 60px; +} + +.mat-expansion-panel-content { + background-color: #576071; +} + +.mat-expanded { + background-color: #576071; +} + +.mat-expansion-indicator::after { + content: ""; +} + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + margin: 0; +} + +.swal2-title { + line-height: 40px !important; +} + +.mat-form-field-wrapper { + // change sapce bottom input + margin-bottom: 10px; + padding-bottom: 0 !important; + + .mat-form-field-flex { + input { + @apply form-input px-4 py-2 border focus:ring-transparent focus:border-transparent w-full border-gray-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50; + } + position: relative; + display: flex; + align-items: stretch; + min-height: 44px !important; + border-radius: 6px; + padding: 0 16px; + border-width: 1px; + @apply bg-white border-gray-300 #{'!important'}; + + .mat-form-field-prefix { + > .mat-icon { + margin-right: 12px !important; + } + + > .mat-icon-button { + margin: 0 4px 0 -10px !important; + } + + > .mat-select { + margin-right: 10px !important; + } + + > .mat-datepicker-toggle { + margin-left: -8px !important; + } + + > *:not(.mat-icon):not(.mat-icon-button):not(.mat-select):not(.mat-datepicker-toggle) { + margin-right: 12px !important; + } + } + + .mat-form-field-suffix { + > .mat-icon { + margin-left: 12px; + } + + > .mat-icon-button { + margin: 0 -10px 0 4px; + } + + > .mat-select { + margin-left: 10px; + } + + > .mat-datepicker-toggle { + margin-right: -8px; + margin-top: 5px; + } + } + + .mat-form-field-prefix, + .mat-form-field-suffix { + display: inline-flex; + align-items: center; + justify-content: center; + .mat-datepicker-toggle-default-icon { + width: 1.5rem; + height: 1.5rem; + min-width: 1.5rem; + min-height: 1.5rem; + font-size: 1.5rem; + line-height: 1.5rem; + } + } + + .mat-form-field-infix { + position: static; + display: flex; + align-items: center; + width: 88px; + padding: 0; + border: 0; + // change text input size here + .mat-input-element { + padding: 0; + font-size: 18px; + margin-top: 0; + } + + /* Select */ + .mat-select { + font-size: 18px; + display: inline-flex; + + .mat-select-trigger { + display: inline-flex; + align-items: center; + width: 100%; + + .mat-select-value { + display: flex; + position: relative; + max-width: none; + + .mat-select-value-text { + display: inline-flex; + + > * { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } + } + } + + .mat-select-arrow-wrapper { + transform: translateY(0); + + .mat-select-arrow { + margin: 0 0 0 8px; + } + } + } + + .mat-chip-list { + width: 100%; + margin: 0 -8px; + + .mat-chip-input { + margin: 0 0 0 8px; + } + } + + .mat-chip-list { + width: 100%; + margin: 0 -8px; + + .mat-chip-input { + margin: 0 0 0 8px; + } + } + } + } + + /* Remove the underline */ + .mat-form-field-underline { + display: none; + } + + +} + + + +.mat-paginator { + .mat-paginator-container { + padding: 8px 16px; + justify-content: space-between; + + @screen sm { + justify-content: flex-end; + } + + /* Page size select */ + .mat-paginator-page-size { + align-items: center; + min-height: 40px; + margin: 8px; + + .mat-paginator-page-size-label { + display: none; + margin-right: 12px; + + @screen sm { + display: block; + } + } + + .mat-paginator-page-size-select { + margin: 0; + width: 70px !important; + + .mat-form-field-wrapper { + margin-bottom: 0; + + .mat-form-field-flex { + min-height: 32px; + padding: 0 10px; + } + } + } + } + + /* Range actions */ + .mat-paginator-range-actions { + margin: 8px 0; + + .mat-paginator-range-label { + margin-right: 16px; + } + } + } +} + +.mat-paginator-container { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.error { + @apply text-red-500 text-xs; +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..1c2f3fc --- /dev/null +++ b/src/test.ts @@ -0,0 +1,20 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..228abf7 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,50 @@ +module.exports = { + important: true, + + prefix: '', + purge: { + content: [ + './src/**/*.{html,ts}', + ] + }, + darkMode: 'class', // or 'media' or 'class' + theme: { + extend: { + spacing: + { + menu: '255px', + '33%': '33%', + '48%': '48%', + '24%': '24%' + }, + }, + screens: { + 'sm': '640px', + // => @media (min-width: 640px) { ... } + + 'md': '768px', + // => @media (min-width: 768px) { ... } + + 'lg': '1024px', + // => @media (min-width: 1024px) { ... } + + 'xl': '1280px', + // => @media (min-width: 1280px) { ... } + + '2xl': '1536px', + // => @media (min-width: 1536px) { ... } + } + }, + variants: { + extend: { + opacity: ['disabled'], + }, + }, + plugins: [ + require("@tailwindcss/forms")({ + strategy: 'class', + }), + require('@tailwindcss/line-clamp'), + require('@tailwindcss/typography') + ], +}; diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..7ef944d --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..759209d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "skipLibCheck": true, + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "module": "es2020", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ] + } +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..f3d7d22 --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..3cc643e --- /dev/null +++ b/tslint.json @@ -0,0 +1,155 @@ +{ + "extends": "tslint:recommended", + "rules": { + "align": { + "options": [ + "parameters", + "statements" + ] + }, + "array-type": false, + "arrow-parens": false, + "arrow-return-shorthand": true, + "curly": true, + "deprecation": { + "severity": "warn" + }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "eofline": true, + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "import-spacing": true, + "indent": { + "options": [ + "spaces" + ] + }, + "interface-name": false, + "max-classes-per-file": false, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-empty": false, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + "no-switch-case-fall-through": true, + "no-var-requires": false, + "object-literal-key-quotes": [ + true, + "as-needed" + ], + "object-literal-sort-keys": false, + "ordered-imports": false, + "quotemark": [ + true, + "single" + ], + "semicolon": { + "options": [ + "always" + ] + }, + "space-before-function-paren": { + "options": { + "anonymous": "never", + "asyncArrow": "always", + "constructor": "never", + "method": "never", + "named": "never" + } + }, + "trailing-comma": false, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, + "template-banana-in-box": true, + "template-no-negated-async": true, + "typedef-whitespace": { + "options": [ + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ] + }, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true + , "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-pascal-case" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + } +}, + "rulesDirectory": [ + "codelyzer" + ] +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..8a28ad9 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,11 @@ +const { addTailwindPlugin } = require("@ngneat/tailwind"); +const tailwindConfig = require("./tailwind.config.js"); + +module.exports = (config) => { + addTailwindPlugin({ + webpackConfig: config, + tailwindConfig, + patchComponentsStyles: true + }); + return config; +};