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 zJ3P*dKQ`pUFFWR+%aO_-q+t=MPU+7OB@6Y%BOk6h>@XkiB{R<*G+(Q@nA*`*pQ(eZ zk(5xx=6&g$4aJegciB(n#|A*oMjL)So{9y^lS?3NIx38Hc%6J0Jo^TS3p}opgLdEb zOyS9?kzTEAz@tRu5#k6u!AwwDJ0?2$I`|HkLZHmxJ||&Pg!-eJiggC-<|{AJbRT$` zf%j~QCq+3}nXW^Lj@mOxFr&!%ZQ=poMg6-Zg%7mP3+Tbmdc!HTUX=^Z&b$^(>H(p} zx^-JvL#qkH22SHSRTOfuRF`N$QfFbJmEjlJW+KLKHe9$q`R?2c?~6e`<6k)#79`nU z7C46Sk{HSLhA|@Uy=vJih82)#eJN@=f%L!%|Cm?$&SXSJYXa~N+`)P>P}Jf$oDy=a zn_vr3UgVJUD`@&!fH?1cA9!$TL=56mbhei&ULu=oH+MLGac|+N^Qv>ev1=+IIiUpXA_0n zGB{Py{OA(X3~J?;Zx6DO_qL}Us=8VxdIqCYQMw(!Onfnyej6&AAu5baNlSq~{XRyX zM;EO2PXu~s))z3qpY%tkagdgRvqH|cC8v0!o^+0(ek$vV?)Ikpt+H6B4@5jq$tp5%-@>|6;GC-l1cybbO6QEa!@;cwvjYAd~P;0R!wZi`9dVPu`h zwfw6aKJQxz5fSS8&*?{M#^#=39#JG^yOhI|B`8ZWe^Y$ZY}XR>4my@We&%j_;5CR!Y2 z*RhNnkGq8y@Q?@xE?%bJQRN{|Z<8wTob7Gi{!2Bhb*T(katkX za0{bxfqa;ZZqeA&xG-i2%0vb^g2Q8BY0SK2d9i!e$Q%5o6uQp|+s4X-{%Jx}`x|Wb z!XJb|mzRwE#CE}_W|lK0N-xt^SXjdPnK*2E7$Q3;!*tFwW7M*qVggoJy+GZgtFph5 zV~B_tN6Nwny>n1}hhk&=JAEwV32x^P%tP zN2P(sFBQarbmFDHM5?B|&*1-J_7lF=^=b$aV>IZ|aXth#ihv^-9!`P9m6L)z2!M(~ z9!{okn&Yj(^c&9Kkdvf4!?dok<}Ie_t$K=tYM$;IaE=Wi0+`vyex(Ky#P>a4 zq=4d_1hFIHO)h?~ikrCtcvWVi8Me4c(<|K>cqwY=*!Sf_L{3FXxbbOSHLS4Ja=J7g zHWTNHwG+Qv8*qCQqUOayu4}n_nKlx_yOo);1kh#PNt=!R6c+jzXd5N|xavBnK}hd` ze-cxKdJvFW!3S~hxy}uD(^bPC+Y2y%*`o8`Z1urs0t+ky6I|T!P^O_B<1-`u=LDo2 z6O!|aa3EPUA6OCYjSd6%C##~)^Y>@u9;$2eBxocwephVQ|0vVZ*Yb~jui-lXWvPp{ zTIxPbYakp4SxxK;OtdRNy>eMZGh~v-Lx|q8*%|UGJChZG{|8+=aiYUwyKAU`{sfkm zSDWLC_hFeiI@1S@b>3*8q#F9jz`Z2pgJET9#Tx9s5A6NP^6?j#7l*6Q_(1L4wYV%O zWih#X6;i`cMN}blW*rfyEb`QN2yM`XlX<(o!kz{wl;wuHiaMK6r`iH`eBRmb%Kar8 z$KiPwZ)ox35qdch1Q~sPh`SuOa+U61aBC9H0p5;A%7pwLINLXWdiPcR$2DRb+U<9V zx~tT0HXa_-qQ$0^^xv%}j=H`S0TK;UZ8nue2hQ8|I^@qJe>W7R(9NkJOJWtW{+JAf zkbfn1Uw%gaS0>)x_i_XHb?H+cd9${&Uvm+Lgs(ch!h+K4C>)3ijQuXYi6Mg_UG7x) zSb}US0mCt2uT$N+avT94kWquS_#^ZmsS89An2Tk%T$Qd~8BLw$xhqV_uYq}}V{3A+ zTz;QGQZ&PO7^5~$|MQ-wk!#<515m$U+wf%@iS0p~#A)V5>wL=Wp+s{g@ShE(5pB1u z|6+tPCoqSiKC);STk#?WC54d#G@T0x&mL)qoMaJr!)Ls^j%DMpH(yXQKtgFqFV`|$ zEB=G`PAgYVe(4BM*I>Y;YHnN88ef}R2FvWCDZ8v+h$LoQ zca_qNYcE^x2+d!nNWL}x$!yX3h%!_}4QAeO&HmE}eKH^DLr;bubhiGMTNsTX2eU3l zCe2spC)(FDZWEh)+nPW+ch!Z&tZ--n;)k}ObFR(Qz4d4!sJZSmGe@)eXUGlN6abDh z^R7^lFI{}7UPhWyBlMu$q$a1_=ra3VD#^-UqxXl8=R0NrVj%GvmUykSv5L^hNzw8) zBmyPnhbyrW!7L)aDN6e{yh-U&0PEQzX?=(9d zAi~V&>F3+W*fvVv=iZjfb*+cOEy)B(%DIj!(Ix0yN%`We(a>?Qdq?Aog5iuQvfT|0 zcj7ns6_M6vQA+;rl29c1Pf6S+F%5~NfYY6`{5=pxgrxl-op|)hDjT^X5UMd+4PffM z8`>E@?z{c@c2kkDf8k6=)piy2NO1tSYoy&fe>f?50CvwxbN?E-*>3bhUR?GIp3N8} zTKk>DQUrDBoZZg9AhiEl9d}Ad@+7%j2P*b$o3ycqHMrzO(e6v*@x<&O`;5nnMmbNWs0r_>Ft?iX zaZt%NX&8khpboC@yPD7kB4(lRDA2ANb{9W(xyt*93tm|m+iZR)@$ol9U+t%pj^GU+ zq9UZ_u|gfHA3_~dt4-7nh2c~^WXwxqw%H?BAcMqpdy!Tsz{TdGTPGbwl#@sgH}MtK zMmNj~<(Y$9M~U-cz@bBojaTz8X&erDYjGfcc2A1;mSzyE=Mt1jknSEZ=5zoIWY$Of z_ylpV7S{>I=fHid1FoYo_P-1SRbIEh-y1&D)L41_zWSBHnp=r7{hd%a8QjNY3SUKe zY{c&$#Z?@J^`tfAa#b^hf|xQeYX7KFyCbV@5XwXAVr%#`hZiC9F=CG{n90FkTTc&3 zLL{6%%n>XTMz08mymq>-W5$GEoP7gD8=W>p`!Fk=Iv;*~uNOtz(LiGWt<xIzbm_!ctsIWjwRrz4UZHgmRgj54_ zzilRD{3w)N8q?~1`RV&KfxZ8XU}_hkd63e^3U&m=ILQk06SV>b2fFW66BP>d_QGqDi0nHi_K1R(pR%Bo7FP$!hAv zG+8#nRIGqal!di64kOWhha&2Tz#(gXe7PAjkVOY?Rg}NN`#u~lNEs->7;PSXyeq=T_eqc>JmV}1isyt5M!>B!LVrHFo+gT9gasiBvrO*} zKaEK5d>(l%gtU#-=-DN4r>IQEx|KcqgOk7OGc0Usy483R9P63lB=wO(2T5g@R8xKs zQ@+ETHbC?T>BE{(^iN|}5Bpoo(rCt zYq;@&!#XLg4dxNsWSHj)W^$}(e%Q@xQ{tgZJfU}>;Bl}beT7gwugDaAR-+6d+uLky zMfST3oq@%MP&!G!EmX|i%hA<8ds**F8oOL|n>8Lwn|e&%V2k?uUYd+XcDf_GxS-9h zOsdu7uQ)_1xW9SZ|CQ9=XQ*v-RPgsr&r%FLH4(sg&a<*#k+<{{pWrNf*`?7TQ zigH-06;1omBEDuNq`TRFaU&R^&R%`|`iK*Xwl(Xz7KI+Tfd5~~8b82oLJb8Hg`?H| zE{oQJU-dmM;yMjUYS4D;0>IycR_c@>Y(d=Y{E->R+3|J$2W!v3yw4wRZ!6DzdFH#o zsEuFO=H1`~`6K|3F4%f_Jo!Kv#$%eApP0hL;E^%5|7y6x#eFfSSn>~*4hV=9_@q=x zHhz^QkqAR2wpAJ;pc$xL<#*JZGk1_B{~+-pB(aw9JxOuAhlw|l|K2sC5ewys*vwZv z7BVwOii8V;7qY^YZJI)WazBlGHXj^mH9tqc@%~N}Onyf#KyMo6I=F z+qF&3(IE8uOh3_f+)AP6M;3~LIc(%8Ll;>iTjaS6V-u>uD}0}nvoJ&(Te?V7oE@~T z`4kPwgYt{5(i??ohX<4PgW5TUuxO_T^m}dmghRC!D|0v?phjDu+DfhR*)s`*^hoSs0SA02_kIEkomiA!N30vvhb)K@*YQp zw~9#xKzo~!a)(bUutuw>OIwO}uls64cfc+at7(vx<1`keWw{@rOcW3NIJVl4DnnxF z{T3p3-OjDFP$lVov5#ddqBCV&+*yv7Y6e?=1sgxFte9AkU(#5p;VUjEuL?`gCYIjd zMTx(}U!t7%JknlI!`39)qIar^cqDyQ*0BjW(Y|0m7ZPkEdd3uZ8W0k+tKZDId;dlX zO`RJhz4I#bc6H!np#tnOU3p||C$?pLG^V{OHZCjHl1vdp_O|))lv;^#Yc4{HI9WH7 z985g*qH$a5f&gGq$w>tdB!UQmY)4#I)*%YQbPUnOfig!J2QX&yrT;t^PQj6xof)}p z!XSR7br>v3e|Oj3RHk1oC~mpXswp(IVf1mW-vk^MPSy^mAEyQ7$IBn2TF;BDy%*?G zsR1+FSa?`_GWa}Ekfr2fzab((4UqJZJCtR}r|VSgGOR=~xX@b2`M~jMQHC#9X`1AA zV6`zcsa~@YPU;;cq_mo=}#D-$$gbpLgAj-X|)gj}wj&eP|R|u^kFrHZ~=H83=qe zN2g6N2-kL^#-lbpKN;~l#?J)pd|-cNuXg52GDMh5yEgAuD{`(re;(2*DK0uYn*Xb= zn<-b%a7({@IdrCkxIY~}@oim+D>K9!75>B)j>J~Fi1Y?1d>g$nb!GtO4ytz34uJ6Q z(h7G_Hq@LPa~k=9z*LiOPI( z`4}7Hzhmd0%tgUO_c7@EYu=W%_tcMz7mKNuS8iq!|SKKzFq=~UIaB#5?_FO^IU;ulJekKkm6D@`kMNz~Fh z)j^O1We4_tkq=A$lZX{JlfemZV36@JScBgv#cY55fbn9SD1KZ@cd`|(q8#4h6jbkU z+1=5Y@gtJRVwq#528D=Bw9qlX3&0X1;O;&Kgq`QZ*ZcNhG*VSo3f4ePRr)y0U^8cD za;sDA$q6$p%SKm z91kAPQgmR7xND66tV}liZu{7cX8c)=~G0t&mSwBQLxX@x3;e23{+(QFhES^qsN)m&XwWjhz z;aRPABG(f7mgY~DD`<%K8I3m+x9HC`axelmrFiE&$|Y7#hsz4cUuW`KQlx}+6`SI6 z^Kt|PQ!P0UC{JQVb4r_+Zh2?h;()8azYGZ6;JvqI8fS+5R1Rwzck4blY1MFR*@TuG zqv1%!xyLlVOa3WCa;|x-Kz}LgD*GeQ31xn-LU^tQZY2Z!Na=Y_0nUjZ>A{#DwH*F}fjY0`&~o z)itPaQLNh8*@b3yReYbFc2EPJpL;-~U3|?DNB(3*c0SR5?c}tkc!VeZi{=6daiaP3 zDg~S9_X-xD92D(Jm~0s@^f#N_?HPIJ%A?B2t@{E0gac53#5-6$Glo~x_kRzhN{`dP zj=}B(U?vHhsr)Ovm>X)+F zS$(^vFkLkNgTRR}+v5gRMPT36NyHR;SGeP?n0j0n3&!UW7&DD}4GTcDsoInFN%z#9 z3Cb!155J%SPPk4RU~IhTy8Lcz=RvQOah_`d`nYF|!nS!JkAB|l^iXd<%+{{1|41-I zfc93K^Mvw*dYp#l#+E+%5A!lB63povNAR3aO{N=2u{O)<<5*C1$K3vSX4(gO=i%Rb zO`8qJx5wpmj_7k9KTl9qIfib+lo=IaohM35f__YbK=R@L#xUze;WjabL^@4HHwhlS z6L0rab(u)jZb@q+jvyF6@dS+jp;If}?_2c=pc%c4s(~)AKR65pc+h)}9OgD%VZ;$H zin+lH)mz(-CKxin1#}K}O#;6Z5 zJrlQI1|*7c^1H_VY6n6S+Su$awo(Uro01KVLr1?bhK0>Mld6quB03~)Z=;~ z$UkvQ!qHApW9&XJUPzXt{qznI8I}f&^Oz2V?{%1J8}D5bn6374jS1}J?MGLOwWeK$ zL|Xak!a|Bm-c!@($&93e1)x!-N9!jBK&x}SgmrzMRsxTEZNp9h&wK6HOwf;`BqSiy zasNxC><(Q3T^`5xe#9TeQ3Z5973LQ#BXLT3g1GMdKF7^cWhTDK>MXOIQbF5;4FtyR ztOBB&I0Gmw^Ug&t4512g70Euo&xSQ2Hd>6Z^6Ah%Ef&dKinab|TN=ni6D?0cj}Vp* zf*Exn=4Zsm3hx^LPMss;r@SEdiVX)1=$j2^nrjh#2qU=Gl)yZApQu7xn#6p>7iIi4)e@`T3S z57YSSGACLjk?CrFa8!1j@=5I1B0@s=r1ftVa${S)qJtLRhn}rI_g_JqRVj0Mt0_;x z^C61i;JIGjz!drx-*!XF?T4-o09|$lcwE7PtrN}V(9<$S2J9T&b2Hb|d*j{(D z*uU0;PEUE3g_L0a4-eH}iQW$P#c^?(-v2L_0^&9ieDIzxz7pX@vM~+iB!=yNTOlE7*CQJ6m_}JTLzGwvp6< z)koggoJQ#PA(kw3klIC9%rEee?+3Y(kR6X>(5{yrt9c>VaS#ManbzOSo4xbHyod|x z6y;647i3X6*;$Y>*bWuLJ;{O%gE_PSlltdO-!HoUE_APFc7gU&os{-VFdsrMhE`E? z;-Sb<+6~k(VVYsc=ho<+Ygc|pFe~pJXghsd_#t@>bT-;Y_(rfm| z`)-jQ@rL}jTpI$Q^2=o1a^*_M=5nz|;ozU{6w&3W2tPD7SmamQ|yZX>+1z zpJK+-bs2YvupqWH6EJZ-|39~b6?PQo*}JqErlr_gX+81#IJLyMA?7HjX4!Vg)*3ts zS--w`4YgZw{}Y7jyPNPFB}d-D<8K2MWD6>AB(nAp?yijaDRhOgM&DX%o~HBT_MjlQ z=SsEH*m5d29kb5VfFR>lOBbg|AxWNQZeAHSj%mo}bHkZR5*97Jv0Y=VE8W)%wsWVv zCDzJcD*4D$9iZfQs5|B(HR`SzQp8HO<;iJDLwHJJvZNlF_S0;`es?VBmAa1;?YCE;AT~3B zg)gE$RZEwi8J3x7Ron&&ofYzd=pc#b7o6-Rw>pzrwFx^}{w99q{LVLjEY0y&J{l~$kolb~*Y{S0KrrltBj`LIPNL}wqoxMM_|&7u z@l0}5dSWreoz>Cs@Q^F8W(tlrg{#%oKguNJSMn~eIf@~)c$yD!2M%5VTPse#bLg+O zevvlB`C$7@lE5bVruTXs@i3z~#C*D=wgOiy;D_1gaw`!5qbQ{e$3UE1HOxgD0WCrVQ6Gybk zWk@qP_jAv0-KnQ2IIlK;4^`&pp;=&HHT*>*Hf>JS5-8#9+h3sOAVWG%i=>B?$s@vN zlNi5L$9h+#kodzV6l!tuL+hWRQOMwYVQ&W~6}6+NS8vvt2eZ}avCnK3iC^y&frPvR zfD!?P_Xuzs6>o>Jsc`>nE#%Qi419b0GQMp9N34XOxLtN(Z8H1&184c`pb~#Y$x6^o z)+PiB_dBOS$Q;qSRaK*UY{Q{%6Jes$|4I=jw)6<%#0xow9?3<`NY5*ml}ypQE{v|$vxN-kY@1MkL?6b9^PW2u5LuhcDrpIE=bxKs z{Sp4mUOFZ_3olnOa~@uf5w~eo*n<$Jckq2CX9KpQW5zzeJ6gp zp-V<@U0O0jnPIn{K48V7*eT6})FeYu_2EL7uSr2O?$>F{!3y)NzL_Jpr{w0D;;c`} z#(~cGU6!YjPBv$)(qpBC538n&u%RVQkM(_b3cYZr3oYT9%lMj8PHqvltuPfIHH$)3 zTR|*R_lkvGs70=E&6P(#vPg6Mg9+73+?f zx1~$5ZGF3~Z}LcIyC(1daEhzs1AWF4mrVi8KzxWh{h1~vLDXARmCwJuxqF{h*Mhqj zm6JW6$BUyVe+pmqCS+ zYyee8evc#}Arxb87J)b=ouK$Fa)C-l472$Kq3yYM$hZ^xMq=NRnzmN+qa`u zXm@Wu2i50mB5`s?AguO!P+^~_^TwSn!Vshl(Ezp02G{*C9GE$Z-=r;46sru5qAqd* zc778-1D^FC{;>0;#;Dfqr-6p%`en2eiLoYnJeaEOUV6Tw4*1YJeRXO3CXzt? zT0FmFC*jXsrq(e>^y-4|BAJq&(84X@K3MXTVqhd~i=sK0f82Q+Pj?|FNWri=idDL> z9tn;pOpf+9#A9@t|CZRq@e|l^GV8J#*D;I-bs#^pAnw=E6{n2D{GKEei(x-30-J%rfq{OhX%MnNU%vtB!5By7ZK`KB z{$I>=jao!>1MMf zu-STi84e6YdokFJf>(8grjd@xQdu7+51$p?P^pE%z!v>71N_uA1X00O+glgK)Z@)U zVR%X-+5dY!_S8WNwh;TrL|dnLuXiB2vF|&$n(y0BG-0@B2?Na!jtw9M15`J30v|WZ z2n%gX2|fDNH%fZeD?w9PBJvGjB&4P!jHZFcsR$x$!;J;etiM80Xc%{ebO*i0!c-g) z!Q)6PCd~s=pT)BgG$dngRrnpO^&0O*0&T-HF*CzCgLUPN7G}sKP$D@GHT9g7qm;K_ zx?rlinsxvn&mji|!6Ct_Ds#dgh_oxSi489=wsz&feZcqe(JfxM$$?}s;=d?Dl@Zv$ z9WVl!zXTd->hPbb^wopig>-HG>~dg$hR~@TRcE_2xrC6&0YKO)1{s0^xG(0hm~Kla z^7yoTj5dUSoKkWe)FtL`vCnT&biN3FR6oA;_ugQQI8K|7zMcxm1^3t zUNe@`CmEYO6&>mma(Snawz{@6J6b9^ncxNLATP#V!@a}oEZH9gg+FeDTXAq?uh}xD z4)#&WdOTSi;4{Sa?--V2Cv4dZ;XO+GA6?0jfKVkf zy{w23O>(bWwihZp{6;BBE=WG;My4$FX_l)s_p-tQn>!4S{G{mlC5co&J0F}%rf)ZER8O8_JgXx0 zgm+o9-BPEm2uL%yJ$+jLU3O)5kO|hKz4-8O2%`PWH28P0;oxE=7=5%rBf7gPW3+7{ zu>ec}V`GG>U_qSN?IKK|z9N%yG=t*DVqsQ>(CzB=w`oDV7m%(FTJl)@v2Zy=%rjtl zHD`Np7NeO(B^A`%@b51?y-xW-DP>!7Wz9E*Q7e9MB@4=3<7O%vvA~B*s%u~A3GN{b zNzwQfkFrZ(8?Z(1^EsMPFL;gfq^1k3a3cQGd*S!$GcsGj$6(9DoGIhwuE?)v3CWX< z7+UNq`H0#TPFT?f1a;1!5hV3HgHXiG4$qhz-`iX+Gb;ZLbOU`@YbMjc&+L8Nrqdlq zlie5r9dMEr(Po^znC}ez3xO{>!Q_@~DdQ3O^@)%rXpV-Bio>wwgQkJIgInKxPC%3% zuSR*TKE!|t%_rk{Bf)qOH&%I5P=TgXkM$D0NE13F!|0)$bj&1#V=RP>L9K$dOS!hU z-X)!Ua3_4|5#KekZm@l_HnjQoEluUm=}o_C#jMT1@Lql0hYm?`QXM0-EKY&@5!MK6)KZa;CJ2hS8hY zyU8}JJHx1f5-58rBNKQI{+~9cHGnUhrSt^$TLG?62Xx+X7GXAdK+cQIoocaiLBCsY ze>`N5Mk|5ySz5=G{lFV$>&+5otM8hwUQ0AdLM$m0X$6pD8Eui@A%%+5G-|<7t*mwJ z&+ki3WxYzf`q2J)(JP{xieWD(g`bV`e&U30eYSPqf?cbh%j5a-6OfJL8_`6X7d3j~ z1mHK9Vms7bA@pY`SiahSJ{MdEAz31)-zktoUwxuQWjv?uha7|`#l|c#*>|YZGJ8(L z2}6UVCZny7=&jdhJiRQtl8`ZS`Hn}qgGWU(!=MJvqp37CqqBeXVqsyaGHI)(#;JUc zR(~{~(ssrVU;kL-C&3p?)Fe+t^H6a~^@fNHSJhC>*}z7eFG}>3jXRi$+>OH04oFubcM8oyc39gYkX35D?a%(rA0H5TVy)m1gh1%Y# zH;SJ(KUk~tT?z zN4BIJdIjOkULeyt#0Ao@kUz3HUU&Bmh~A78i2|)s-;QFSI%kH zFs`S#X|6N-zt+DW%wZGwDnj&@vYF|Sa~jk3+o=k*k)r5_=!e9gb9KFKR9o2G%WXHpy4MDPiLzS@9KT@e`T;up&I-*gy4jJNXb11_k%ACG<9A}D<>~5sPs4%c=g#I>DJcJ{?Ek^mwcF471 zS53|s77Kk-HR|QHh#8*M8NRUm`ji*#-5yw$7qoRNLX04IiVk$PORGlk0M_C@l%Vt< z8uv9E6l{OW45s?FUtlsXOSAHti4ES{r?XbzpXC@^0!>XS*5biDxuZh=g8KWmxd<1) zh3qFidyfg_Kz+JiaF7X=g-)LZ?}xbRt7Qw~0n0&YS8YyJ@2>#_b`eD1>y4HsD6PxU zOJsvGpNWO&48PGSD_1u8zZjZB{mm`v4b$CJR4}eqEMQVYon;E#Kd7$in=#DZu?cuy zfPc*B%5B!l5UpI?=b}-AiGDy&a{3;@pe|Mqk!bgglPQ>OkX55(UasG+ zSdJc?qS!?A<%N{55p3WqKwB=w?lUcbueD)j)cx$|v25ex^?F-gKM^*cd6m5Na*TaZ z*4Mt0UbmNd7DbfkqvAL4T&XY+rt;4p1SzVUIoSE>3*^-&<)tn8`-NQ7m0Zy`znyB< zz+<%uj77K#`_igvt~ry4iw#R+-<>3n;k_=>D#X{3!`SQ5W^4ofxL{DHs9p%*wtwkhSxL>!+9iSigOhnSkoG? z`PwMx{2B9j_J*VwJCHGuB z--|)(io&J`r}%e~Zpzue1b+~<6*1py`DT%2Ulc^+I&>l^Y72HBD6Ev}28Aob#t~5A z80cK}>8HNSRG2rWvDKSThzabq^@V0tL1@a3va`T}m$XBkCC$kJUdAg$u_OVO2nZhH zM~gaE!VTYCH6FXVGS;uJ0ZW?5yF#$?wDLm{wH0Wy2uRHD41yCS$xd8@yE zC>G^>mTL;l_!gthw&Ua3z1;+rAM@Wq{Q}p4fcrDFh(uq+qz~h+S9 zz{Ok?2G<3Ksqve4u69ZhK7)+vm5<1 z0|Ht1zKNGArafs&Ly&cGE30};FQA_|Ad5zGY%oOl?UMX)l0ByLGWy)8)yk;0<%7cU zZ@s2GOP*v)2q^w3k%8hLbjtdDP=TK?8C0UXF4Yv^V&4OPW+$s$SltUb%|g89oc z{C3fbd8vbw7=wCl7UMss^9liu4S|IBq0{zgawc?u z1DiZC7n{}^N{X59Hwea>V{R2lPnMiC3j;-Fl3&~PR8P~Rc!wbL0+%t6ZY+xl;=AX29nU0Uec%fg#ApJGp+;!#5c_}_rQK7W2F9*d>tdSN(F<%Xt7#To&k6`4k+QCmI9%)VUfdN zqm*6*GeZ}y)Bv=>BEB%o_x>u6*;uJp;!i;ObY{>iE>+1X0^V^f$Uk^s`*l|A6@(bj zG*)3Jv=HAux>qY22=U--p0lkwCsa{vq(5GnA|F?G`!pL=fX*Y0mlG(|Th*P{3#ZEn zsY$`&5~q)aP~A$4o_QHLRJzeHrquXu$+h|{b!O-lzsH^N>WXR*=?=q$j=>>%6}+fS zdzSi>|J{8F6y~K)>4B^vZ@O33@1+=fSZgWr7YT&f39z#t7|h=CycXy>{`#74ZuB)x zX8pI?kqG-;Vt*s-j=TcGydYf>)4>r4hQk6S$OCt-CFwL_pm(^K%+$&_HwGdUo6QpP zY<;e_tU29L++5%L1=Hrp0^xg<&^TApC^1G0&#u^3+Jp#}xUG0;28N9&^iUb+ll72{ zgCw%iN2+D!B512&dfl00m6GxEMG=uZ1_v|6{rWQN{5Q+C9=yul zk6Qmdp2=+*n8RjI;3yXg>X4LMc+G^T*S(%2QX%&e1}0^9gWlqbIruJbtVXRZ2#>oC zWJHE0BGAac*PJ-l*`$glx-wG}T>QoO{Q_c8#PF$~(}^nSm*c;D#`PFwy z@(a=?Qm}+Yj(%_8#{MY;l=uI5daHn_yYG8=U|>k;7(ig?E~Rq>l#-BcaOm!CK^kcg zkOo1zLsA{Okr=u|8ib+Y#qaa~y*G35xtW`D_Fik9wf0t)2dt)CCP5Df_KTmFyc(0L zjZ+^<^Y(d@woBeRsPuj4MF;wuv_T_@y5yCz`kx7>lRsPL@>Zj>iC*)#diyGr+^@2X zExhCr(wC~*AkxBxMglB_{1MwC&m&Rb+ee$=6-nAf$g%RhX2ukU?(kXY3u4`Cfv-9X zE*LWibSve?KZghp#+tiOd+se;Z`$}}KMRfN#qHanfOm9fBjj}Jvd5xQF*_f(9eks1 zhl>i#<_dM1)p7gLMc_}U=wO&ALF)p5f;CH|VKw@p(etwKZ>1g74yK1ZLyMY0uXq=2 z-I@x0AXcYe*ZY!m!8yC1k!01u>I#V>4=bp_z+B{me-W|YCRv~*@8!C9Wy9fn1c!Hz zitnvA{a2}0D-*jtAs`ZxMq&+P_hFF1!L~t8BS%$hUz!JzVT&U}$uuO)%wn0-a)n-UyIi zwfuB*hvkLQ`pjpfk)q6FPg@_%7V4=T_zqLn$ItI@=h)JU)=&3N!IW1+Y`#%&JD^G8 zFeGZbjZr!&d41wn*LY0bEM@rOY#V7FgGL z9+iw-4o{B>e)s*pf2pa4GQqo@OT_5w4O)UwnpMmULrGhAk>&pvBnx)0>6b z`{w^<0o*oM(>O)Y%%IgQycf6%)#>^szqQ#>g`-uYF5;)aufJ-O%grXd9`{-?;~u4`m9ud68Th z3JwNk&f3f_x#!*=@wfpfnOAd6>n?_L_(WP3S!Ww(JG>uKwg?3Wr3k9td>yQM8%qRMHaV|@j|IbuDEV%Ktq@N7Z*lpIm&N;|FVsD5Nim|;Ik?Ag_32ouisIh7N!8Y#Y6Ifo7PrcjwL4e=N ze&xOoA+j^tP#C{B!mJ9{(r^@@r>OZ(sk|tYb=6jtM5HHzK7=9=O+6797_Br3PRZS& zM@u!NBlQ810-o&NO2u?OL<2U44LCcE@0`#FwMX8t*fbC|&)v3$y`BXG%qySl%HvOF}{M^!V&^fq#=bDM0SE+(hVuxS- zqGG~BQT){vRXiJc@7D);%~y91{X!8QP6}77HBff{LsOX*Kb}Xt9Bm-S zb!W|=pkflDl7I5Hr!AKCa?UT!hl}NcrPF@fHe@<}o^0U`D>t;U%9Oicx*j%`3c-n{ zH`ZHWLU~Nq{eWTRTTu|XmTuKa4+9vuC?UHXxuzvNmnk9;w`y-PyXR%9hcIcMh-0=d zq9-o?KelH;A95&-yNPY*qenE@&@~bGH)7{-K3Bs0ZyJiZWuF;aaCnn;La>)i43#k) zT89~yUZtJ)FhS#B2dh>UrtB0US5ph|lS}iyWw&OVV|3w4pw&I73X=?aSo2)NK!$=# zdp%T_wLM7>g}jEFhpMl$Di0jqEa1#?bq-Q1u%X7!PO~&HOi8p~$xzLp5Ya=&>zE&Z zpqjSx(@oe9Gm7c$^BqEew?x0JYqhGZJbl-8m8|SJN}(*+3nJwoFWJrM2F#?BLxf0B*Ciz7?B{rOI-rYse4#g&wh#EnyN!Fa#${t(D6p%X;dC`bP%D-teZr;2q`KjnWfr+E;ZbgwC2O1) z;`aM_@!~;iGU)>GAna<}>){L=lEc^Q@CGwM(*LCefIV=G?6{uaxJPNIrKK zJ?Jx263c2Z{{$WAMa#yYBkvjHm!$fj`$YxMvk5Ul5G5~VNvuissyS6< z!_f{64@pmD{Rs?di`mMX%0P#YT50<}-Jis*$0cv0mJTCBzemxXP*Teis2S4wG$oS7<3klX`8+upO&x= z=y8u!0X=W>4DE+#F^T9+8g-VT;Ji21|V#wy%q6B`M0|+D(Pg1x(wv4kU!aO znDvT$Q|kWqq(Q2jg$U`z>DMr!P-CAC{~Y5wvX~GNe%>7a3fXX+hwi2cN!DgR3viYB|jbLNUyHJv{n@GJ^ zxZNl2K>jije=qS-aE38%cnRg24)A2lNjIsOqL8Ffeiv@vPxgLkX&Rjj}1{U38PjY#;1hn}xD(gY(rLwwt|;>Q-W zgcj{^w7+s0MZ96>ez_T;J;advvHtU9K{V6Y_eLc>cNFifyd*pM+RCUlPriIwZ2Hm- z19?Vc9xdmph}GDNI)~a6k^5rCwNCHXYS`&PMRbw{B!s~H z4}^S>r&UkCCp_5fan4y4Vp?=n+W?lySBl|a=OIkgk*}u;Stfr=mF)xJohPl#x2rZD zGumyqt9TAp4fRa4m3ID#rNbOCtdHl7thcXmTZS^u6wbO6SRRj-L2VOJAuJ9L;#|7K zf;6*=C0$Nrx%c*q-XE~H#X`&ygfhoedLeyzq=^`|bdX9Q(Dw3X;5JnXkL2%R=X~wC zJdsWT=6A?K(#ga+B>>Ydk&IcXO}V_8FAnu920)c91U)PBD-oJ-g^v2Q9GbTGvvU~_ z)V%S=Gkm=UZ9j+iSpgeoI|mPPl$An0HP4D_Fkihifrmlpr)N`XFBWicGa@=;Jm0L) zV-;k|-u4%_gS9@TR)xvpGV-p-6XHs{5EJ#_aUeU*S!hHCI*}iPYAJqGy7=VZZ|-M? zX?EFmf5&)%yn0FPIfw7m%wpV~Srjdd74@c@q7pf+a#ZAcs`9o{2>cW5(*1_??8eo# z!PGMTO$m|%pVrI2jTAqi!W6E@f5y~7uivVLcEyPtZj!k)a!5C9FQ;x_!L9(M>3f6^ z@U~)3r4Lb>L~4Zla>0c#*Qa!~Z1#v%*>UpA4@#e%*-6R24e`(aK@(K)E6{(*%=1zr zrUGZuk)TH@F5>%qN@KGSq7#j9*=hx=sgH)hl56@vRR)s)NxlyG71mK+9&e>KsZAJR zI!NrEq!K>jw9>zZGMys!gqgBt$s? zw`{$vb&p2!p>Q!rzM?Z;%GT&Z2+1x+;4b}xo$hwau`5l>_m52nKvNMMn5ifW;emb? z^BcB5lKTc*gdc#5D*XJ|{8_Yqbf)wAp9A@m2YIz)`o`E7;%nB@#uhiq5F9 zUxie(0>!TV{%dBy`FV%^Oimo!jgYULaHxQ0?Ycgyi;s`@Ln6E_k1_q#_pa9aO`2DN z1~-YD5sN+7#LyuA3DZxc>Iv?M8Mjwmg*(4`7i5mnrR4fj3-$$@4_O>ftQcpta_WC< zZRLinM(%xomF>;4YXVkg+TWsnJfCcYgRfZN-MS?BPb^0j6SA^ZJn(tjhrTXhiHaTs zAtj1l`=xv7ZNS=|;uR4Qo^)4NqH1 z80Kic*TBsF{jG+}pPH;S!=T0#3u=|}VTSpc=A@ee6VtWnP4e>l370sXhd(8SexkYY zoS+7Z|B#hFR=@PqX13hf+wy}PD>vj4m1SY90O4ycSZD|aqX5gAh;foDP2v)wAIZ2}`~A`BN# z{sA}`R=Wie0uK(w5+V)gZfDzPDc!1m3>Lh3b~*P`3*aoU@dUYc)6>frZRPhx*cwfk zcVEA5WfEx_I4}ehssr=`Kw~)knTvn3Hs05+mN+2ep@5JqRP-dyN!RKbUB!B z000h%DHn%Bt$qf2i2aDDZe0-dH5f-`%1Sh)J#995=kvj6i8f#8wF4{5iY67?tW+k1 zKo-0zkf?nZY-_GN(m1W1?YFFNd(<2wrDaAN5LDkd!&zJfsQoF+D6GuM_|p}6!)_&Y zUil2Ax-6W>ea_P%U~$L2FqN7UlvC&P7X>Zx6pq#CxyFLuh{Gek$gBc~0pd>Bhv|OZ zC@Qg=4{Y{d+-FSn_Z6h;IU1igR;j$F`+84LMubjQVVKurTYERr)Gd#m$Nhq>9`(oH zqDn52I+MJzSrZ>w^b_j$N$e&IH)QXNzAFxxbOhG|XXATR@6m31n@#Gvq!6&yyVZ`(s!N+UuQL+kfrn4?5tCm>?3EajhVfm!T^&-=8kq3DP=4I#E@Nj7 z`U}8lEUns3EUD0@tgBvN858>{>G#7AGeyK2-rh*6q+{Tv^P{(ce;#ov?Ed3oxNaJ& z?JnByps8&~pZrHM4jasafRQ5V-4o43&8IFhbuD}2ryel4VT}4)?gF#?{R&F)FULd; z!;;lz$`~2S1_BZ5IIEX$Kh(~%61Irhwcze$oAo`Pv`hE*tvkG}`bYq*-uPKaOKwE3 zJ&11eb2yk|%!^G)0IMfLzxHrP@x$V&yE=aps3x3s-7V;-J+SR80v~Z4C^hEmmlu~n zO-{%vY=c3Kz_alP?%3)7Blu0iOl!`un#EG;OK2}|hD}ms_XK)ZR|0A0xlYAiv(9#9 zL)X&Z%=<$p9)wh`&l2{c6*{5Txr6dWaN~yJ?#o;e#HgfSxbkNR`Rk=X)l&O`@qJaT zl!9&B+$4S4;xpb;(c3_ya%Sh5yf!jh`pCa;F=K%~%!fVQQIR2oh6Rg)51!D$kJ}kZ zcJ50FVI7>uXr3b);Jy zYJ$_?$Vd4i0&CqZM_pv^#nKdw7h$1QPJOWR4}#GWF1hk7QKleCpO%V8^j*O7>J4qctgM?k;de~`#nzE0?+Z~MhDACGet z&UPY+eJn?7NM#|i_$i-`fAPm*gHwIur5878;X36~$1p`s4{X&>%4akuN9@yQeFy9P zzs48oC>w8&8H4Y6ITBZF`nk4AA5fpayZw3bix3!>fyW7Y;YkDU&LJk256` z4cPR5xz!%`+w%5(i>HfIxk<`T4w=JQIkAf;K^=agu6^VWg8@X~Y-!!2oG3Y)6?CrG zjs_ySc9&hIo^y@yx;v|kLx0871)3v6`aNt>hs+6qOg#rO3LHN~2Uy1SpQlt(Cc|U@ zURte4Q>8zprlcIgJ05j8L7DuIkn$%;n}K1ti2Q%Wub2p|1%ucsz}+L9n3n-qu2~bx zCsQWNXJ3p?H!$q=yy{6`SohXD^Q@~ELmZgNu8#cTi@);s2e^*rD6=plMY$BWqJqvf zRz9WLn1!0T=F{cgg}FEWSVq6{G_lC-I$^!t&A>nu2?As_eRQO8@3vKW=DeyN+B|Rx zgt-?+)uo|!7Wsqz8=H_d-?mwk$S6qZTkP>2ee*lzjY7GuJ6!EKZtUP`T&R5Av0fJ9 zswm(=W5jcYt>ty8!6>8bYDw@ppivleF9SoZcVC^XWF~u1s4TZRj9R^plZZqh-LAI0 zD&S{TyRRVS#g8Drg{z8yoAvvHpMS09QWOC2k2H~(dwo5{t{MIxJ!aIF4U!VE<3``T zG1PsaK)1BSZ=3phGNFJ9x_|L3=1f2)pu*@~+V{^z8U;mvWrIucanL$*+G={ZZ%4)3 zE+?X9>>_kcuygOF1;*34N%XpJ5gJQVRD;5U;$`upaW@`UE|kh=!nI$di*Z`|6zZkN znEg;nMZuwN4%;*W$kef}6%|oec5gw-(|ZZep~qI@W+5Zb^{76?^2^@eV-%=9EQf+H z6GM+BYUKKhJO{KS{)ro#zth>2dVUGjLZ_1AwxJbvlM>tc6)}JG z+peaw+aklmz(bo0)2z5I06n7)ni9FFz%CDV7y_nL7#morjvAYF-EO_~yj-eYFTjkW z)%~Xaol1E#Fssul^nRhMvrk3LN63(=vf$IyE6Esz$tiaSFuprtFP;xJ7w%U2KFR zawYcL8D4s8lMyS`r~CXu(U7rlo!50U56_x~#M3pxM+#jZ!+myjQ!eHIE|B@y7pRzL z!~A20IVLV&n^%0SnoS~qjrw^1r=pkQ*ha$X98XTe@M!kj|KhS!&=BuSpXuKP>AKmA z;FLYPizO-wA-c}s8(u|CUD=}a67>$E6t;D#h@#Y|zLBl+RqvKhFMElg$l=!o1F4%d=Eoi6(5y3YKv;$gZ)|+S3 zTVne2nuh_yZfao_O&5Q*B#`1iB6uDL4E^?|UEsV)Or<$Cv0Aw%C+$l4B7*@CrA7#k z{^3|@Vzc4o?A_ChA#vi@VFHXg3w*a$wZYl8$F?jvgl?IPa470e6GcX+%Z6`(2>UjF zaS&g`-v)-*y8Ju;PK{9u>m5tCIQ)NP^W;-%a1Q=Y2J9wVUNbN8Ij5D*hxhyJZ^OaR z+Qc1iwW?4Wa+Fcoz8!ww9J`0a-5n!Hx$}1Yu!RR6F{?2UPTB9J>*g92a5v?7+kKi0 z0U<6wrJ60){8s>o*16G1JMw(}f*65KTDP`p1Y=XXASWX^Py#;WbLp zbWe<6%lYavQCAA>9LnvRz{7FMa#(I5NiZoJ-nzijnF=mv1X#FN(sd?eMluJ`=);W4 zD!bykpoCm1e;6$?{W7N(8#4G)(5NRd!%l7%hny;MysOx z#oG#HYky_}V2PkU4m`L4AMK$SeX`sZZ;*9GZH(^IM+wvuChWsPCGpnSux2t$Gznoc z*s4q0StiSY77J*YIaYO{hkUFdW^|=5Dg>2sO$E0!dN84=nop{BJy~in3aO z9yzscOBD({R_(1AKrW*1pO<0df0Q-SyETMg)w*=#WB-lR?yH`p1Q|h=sqPuo*nKE9ssmt@994Xs zaZXYHI|$`>VgYuFAqS|2!8#U4@Ka<+$-&j-IiiHewh?Gq@d2!RxG}{tG$?IWw5T(v z--^$4I4j~m@bWc^D^c4x zy^@@&N7p_>^hZ`=*M;OSZyuw;pI=LI^`nos5tXuDeiVX*l0}074_4Kj#t=}ya6dqA z53H{o364!m46(n^TgYm@&CzufT0TqRI<)!4($udyT-X7yv5YbNz(^`Q{Ii$K({Mpx z%GBV|!+JIfrI-4G*k>J$k2J|pBSE0``6Y{)BKNoGe!d=5j^HG!ncmzysv|~*MiupR z_dy^`c7e*O@xn(ljbclu^?1bIDdw&~{7U=8d6N&%H#48N=Up7XoEGd>XMkj@J{-&&q0u&ENSv9-xgZy(Jd%NAAx} zMNIFz#fTjm2(`oNP3$Z>W0={@jE@6b&nNDa-(Dthgk?(A18Xz`ot?fmM9T!4MDK2Q zeh{A)Q~41=<&96G5@LTcKclk!1APxKgCAr&HBgro^JgYG__GP<+>N?4PsU@ zxObcH_rt)fjNV^wU#41BsRj=wJL*yLIi)kD8^%YAv+@S1utI7pDl=qQPE!(C-SymH zwMO1Iy0_gf$!0K9HzNYtnEy%jPxjPziQRawaPL<8;t{SaAP7(p0-Br|P$CUCj=i0! zNC^8T%cfs_wor?CSdCx-$c$TNhEllq{0+dde>=U8Y<(6LB0vDt#cgkd1M(beBYf>H z!ksSYV5X)LuvH>X(5O3X)#HTf4qVqyVqGYL^%LiiRIM=ghJC2dCHt)N0$|{rqb^AR zl=_b3V*wc(M5gh%WkYcf9LSAo;tyY7L5Q0rRdD48lqr&m#@jxDO-)+urCR2sQmO0b zh-axQtjE4*XRWBSQR1lJ@;05dtmx%}g>hk~cLwsf^4`It)=0e-!>q}9E0c#iil@on zM<2;JC^yku{Ex1gkX@bEG6ps7sR6rRF6XQy1Cyqw0h5#YLptXR0#X6}fyf0pmv_8# zpx+zsY8)Y|lJ00E(qrC}7Xm(Zz9eg*A9w23J6 zaCrlZ35>JBW-)0@hdRx7zdJ8G=9<2T4tQdn{hC3X_NlyzdF((Qh3dB=JuuNxuItX9 za?12Ec*%oIV&3$C*XZSML{P?K?-?oojul7*T}*q;RR;M?e7`~einGhV5GqWb+p-F6 zJ81{H?1#lvlbliuLr%Z8{7H$=L~cih7}0^2@0lY}y8VM$T4g76b^Mg*(a_+qLQZ<= z`M0j5({mg_MxkJ3lQ#nf6=Oou_DGS}F*V@s)Nyz}%(RUV*zuOX!FMPv3I*^?54Zn$ z`wm4jxMee$%X8c2nMF*90~8k*b-SgfTbL6B0X=P_4!&cM#%-{u1tV}`LIQw%kQfv- z2404dAaN|&q*O)|6dCL`Ii#0e$mdE46OZ+J211~uOW5!?m5REupW=R(!=T$eCad`h z3bcF+drwdNc?Yl2CXTA>#>zcPc+dk1@-gtjJ_|9kx!DVW|9JA)d@=G_GHUYnpx*38 zBM_@_4r>}}E+z(|evq3%U*jy=%(I~oSzXV&XnPiglFOgIuUVCK^X80zFCh(s1xfxF z;8E;?+}&70E*-B}c`devo$5t+22D^>VI00Br?pSd`?0b(ZqX4?Z4kiFEd*4XPoU8# zFqGX&ZxBv3XCq)5kki^b+yHL|&&m3&{$TQ)Yd&sZ$uYLb&PL6zpV2g_Gh6;``S{S7 zY(K-jh#l?VFsCZNc*NqG`xbo?&PNRQ5968>7DvIiqD!s2FzC|1}k z_pV=3(Ct#coG$Q98lZRXtxv3d7CXH4fbr=NhGZ8NZdm?{?U^E{DmWRft_Jpu-ETwV#F~sxoVYtB?QO^mQ>IwOHGp`1z`VE|? zKgr-icr=}enYzb1bsVJc*~M;CGLUnB&& zR9AnojX02cmX`_90*vEJH1${A|LH)ECsQLj-ZG8?ek4cDzHUCQeGi^^BGvrHFVn?#AIU*2H%@_}B7P2gwxTwimzz@3i2Gr;tEFk5QV^l#G?|nNJ6sqLJ}02N$DWywngWOidA}#rL*8>0IXs<&bP;=X5T-#MigeV)+r7 zby!d9_Y{Wx8T*ggNtc=_kxu1;!Qv+n5iM;%Ti)Xr+FYy|AAC09%qf z2tGFPE0++oq6jvK6DX*Cn8R6d*l9oJwX-d)vt8U8&g$w7ybhxIMLkSBlj_9s`I7O@ zcm}jue_+W3xMv{cLY-HELtg=M0J3@oYH{v$y`nlZbIL+p)+;whznaQ`JA$$!m1QFf zeyTanzqMI_|0wRpY&IDwg=5I-2UkSXT-O2j&1Ap?ZM&v-EFr_v(NIFOV74^HD^LP z-V61;2?Zz2_}72|DCpi7j+z0y2BRFpA_pH~D!6ssf6PMu?qKN5H9H!^Iualv>r{*` zbc}8`Tp!d`a9NE}TvIt-%7;L4F>R(r3R6mRQQZb%ki?|v;C`;baB%-lB_DMj@Mt~=DZVGL?X&9UN4?VU}yt_!e zSAvB~xK~^Q-h&h1b$U0GA#8MY=;3>DEqw0gWITr^C7#drW>GH_dMN1`R=TFRRBF+h z{*}2JfywBxxc^Kj3$IaYd%72jOV)k=djx(m2+t^(KCPfvr#ToS#p+F~&3y!2vPk(1 zlU3U^$SO;?V4Ys#ofNJ9a&^fE1JB}*Q1JB%;)S(x^h54aPGbQe*^GDjbTB9x5Ds>R z0d%D6z}9^*NczyiU?bM;A+1Tnv2j3krS{3%Uet$?{^GhC*57em&7xN)zVKjvj`}p< zXQh4}I@1hdV8CNT6dG;krp6O-o>}-jZ;@x@w46$?`xF_vx3)3y87cIslAquu$Sr;?Rtftn%lA z?RdECo1S*LTR^YaX0pV^;b1jqR?N>trvBE8S>`iVDx)3?Pdqsm6V)A=0x_sePZP$SYGf^fNBq&Zec873=zPWT^r`~hHOXBvj z!m)?bUAu<0_$FtjQ}nWuH5Qt5-q;N3M85jzD>BqGsyEq+*?;<1vBN}_>UBnuL#D0?ps(vI2Wi0p2xX=%Dy$o=kGdd$u9;;t= zj2oT$h_18SgvQt|eWiW;226 z9VU*pDV~Y!hoNbsee6WBs~XXB_yAcddD}=F@7RDff@Nnqd=iFRSDE70Fw&ef)YV?y z&hb3*(UB2lK#p<2w{Q-F=N9rDBa$b2J z9HFwth?$*Kq5Xt5z`Ru+KNXIm`Dfm+wQ|t)@+U~a$(gL$?pn*QUiUmyXl>~rup;7W zm81lhnWsoAXPgt$S6iz^!w2KlN7n6E{tywo8y|XB*Z4I3_h20iJU*WwZ07k_@tfoS zb%ev;Ixfop7x^)@W2{+<43UI(1R91co-gbi>`~Fw&x%rVX^DyRtv*c9VKv#h7=ySC z!KAvO8(-%2YE>!YpZL^MC*cIm_iglL-VDN4o0~tb{-SPmNh@{qa&{=XnAeBp0bbF^ zgv1))0;XQWp)b(*1_Avgw>cld-ZN1l^$<{|UHXR^dms$3Wr$9Dbm+j`*q^Pm>#o26Q1Vr_~AF20r*G_$#Mq|Eld_zGd#!I302>p2mhtS&PQ~vT-XESy}#I z+x&1SGF044tV>=~=~R3;Id5aqdhULkzVX$7%hVl3`SKd4?J($JmJ50E+h`^?#}+-f zmB_RzSok=i(iV_J84gw>AJP!Ya5Xf|>E00Ea8E71$$?xsR~y|aM21ih0O4;DoP26n zEvbEx@f6RPUAa=0Q1ogC)3}G{8)qdfW|yxjF3#zt)^YgxGmUO~ycW=RMjDV!fxLZ^ zi=zp^?sl`m%?$SVfe}HYk8iLpw zV*qzUhU?fP?JBj0ouwjSJST=0+!a*B+y;bR$xH`2JXp`b&eI$od_rr2Q0#TG_Wv~a8n5~g01u`tK{VJv?e%ar#Y`Fk zysCTkS4sSi{l20+BXMvrnV|6|>bj9?S<1h`~8b-l4U~y+WYO zOv*bOpY83j%?S`V2;Fb98O$%)4`iMOce~!BvWlba#c5W^?^QB`_>Eb$xy{W-5;4$J z288h8-9L3SJTDsS4{vg%tOELrgUhp;nqmV^V~#_LGHuMVW>9OOxCF=aC{(LeVg0JF zT&erC>pT87j|ZNm_I81s67xpSzBvulB1;z15wl%^@e&eL(s-5E?q##cx$4o*o9WQQ zlw=lt_HuOK{CIHj&#{PJalL1$2HYk_`Aau1Dan8;h)6K2wzjz$EEv2o1LSkYAOoh~ z!>XP!XPT;iup(*aCIsf?vN7lCJbwmLB=JFR ziMh}<{KQ)-nHiO^D?4m6AcIvT@6bV=3O<&-T90Eze*tliy6latnx9iiGM7bTUP4b; zmPxFby8Mn`y9Hkpk8uCT3iH!91poIaF`5p2i`)M9R@m|Ve|d6G6)ZSB_$DBN5rk&%Xw4T4Y9)}1 z4AE5o=gu0YaAi85Apk}_i$t-B!!~3yz?J_-Q#8T_lEvM%DykVql4*pAIGn1_P`U?;PZ zr9M}dv{-Z3!i^u<99!SpMxKBN>jf|0N-dN~e1hhUMAZa^g%>KG*8BZ#xwqD{?LM&8mr#NzP* z*z!<4{=SBCyRxEgle?^`n~IaX=68)I2I70nZ3%UR-EzL=J^8qqh9dr6_6-^K)Mzwy4jv*KzA z__pnXX|9~TXH(VNqU05$wHp1-{s&o1kii#-f?^Y8iK{XbJ}ie(y!S%|fQZ263rZq6 zUgaUr{FhnK0eN$Wb$r*P5@RIRIEr#CN5h2$UtaJ<9qbI+O~3qf9Ie&AE=Yd!tlL$% zxvJi9NcHqGRp@<|y4Ly*E@;|H&7&htyF?0u*a)~LGIp85MAu1_R+Z(S!Zu0M zh2CPqpKH=h4x5h+FKX`BoOlfC0*RnJrq8$0LamLIfc~3U3g2Ev5ZnSDu$UJrIPw`> znD{5bz&-opglO0m*9h!ce^Oz>d{rH3OnElA7bF>YQQg%`mxtXm!*qKbmSES2d7kCLJ@kF zcS7mC*@RBOA&MQ8DYtA4v+i$hF!cQ!r}VIdVTcauy2Bt)blI7om$kW9; zuh3hWDJ)+`&zenjF}Dtz;rgEz{&tWSMCXGhM>-JFKn!$@{XIED6rU;>w3vVW@c(&3 zjQ;gcr`epCed_-^d0FY*V!2>~;CG47cczX9@3R;{qvFAU&`A}K-N!as zAM>nVTEj{>nTPvN+%E{R`pb#8HyBzIeZx@|;%Ni$RWoGI?Ymc24y>jAWS8=IyrSBi z(Ke$Gf|Zch{6%7H&jkfOY8$ka%_M0hPvkh&EC!>J0?&7D{-?I>#4a7KYu6$J8Pv4tee=Z`(PBq zZ|Ty*qz=pL7%jBt5T}&2hwm%ecex9>uLEI6UY@QUhCl3;Cow7MNenRuKNld%`Q2kB z#8FNqlYzY9m{iXjG^>6y^SdLy^)=4js?JX{^KVsf_dJMi_|;@~MpPuW`JxWt;c)JN7-$j-~r4 z{o89=lX{DCJ0FmMTO2HBSO3AS(@=-0r7POe5dw2qU||7y(=n-sEpK;d2Qy9|va3Tf z5=<^7Vc48c6cKD^aIv>G-20ILf$8{NK%KZbfSX z@&&^IcsFi7`y*BdUrokp%N_j}$tvltoRxvP#Ccy(3DYodFif+WRJb9!+cO|qZYczH zI|9anLKUou89B&U3*I%c<`O7Bz{zF2I-$5VxYb>>0jO{tv(EE8UL^%Q_60Qyv}(iP z%A3;+&khnhM4Gs-PMqP;NWO%(#Il4!(t3-KBEKh?_NSz8{#NB%)7Q*mKw8Umf*2{K zDn`W2txjo)d~oStqW=s7$a|vzj<-!58Nxy0e|1x0zed!`t0=;E(mHnNv=g{#B zP1qqLtf+x_sO_Cs`t<>S+jthFXcl^Wi6YjtE!yoqXJVZbJ;_d(gj{q%=!o-qKPoi$ z4LtOz?_t&FZ&8Qh)oC{>fA!9KEX*BezfbqSA;=mp2o6JQJ7PBOR<1wH%%ZIe{D8;u z!YolawcR<)m;45$o^0X$t>wYv!ysGJ?2+}PT7v0dC zq-7=gjQqHR;f4I+Hv-$%5@{2~JQV)a+XQE0_h)890@nh)!V&Q+Voj4o0rAAN`D2~V zYiJ8WH`qhwqJVpV7aK?s{zI63OduqdegnXJ6aEmkIk%5ZsFR}VZMnZUJU`OqGsoSv z?qX1vAUQxdP7=2~GZSWXcI~y$$AehO+-qz3I#gCRK%4i@Y(j$dv=RchO+C6m3mtAQ zL@jhWlx1c&xeS*rdS7r;o{F{i4!+XaP%z!ac5KpZlOAevP!#4m!Na{E?9v_o2a@~r z#N;DAwjs)vidZUp5it&mL;yhRPQaVnWM0Y$&fw5`GKM4eYASxat2=y7jPX5u@pRUB*UA_sO+A!Z+qwQ#*%E zSC?JJlFK8^ppI;k?e|-uS!cXUBJKi3`aF1n&trO*MEVJfZ?onB<^1zMR~j@AoZ-(C zenUbTFRXCMfHs7{8k5F>RL{xxW>I{+JLMCSp_ij{i1g zLH_yvi=AI?sL8@?_40{qA$FQ$^{{y!&V2d6ifG}ljd7N(Ut-Yf(j+_Ie%c9s)qT41 zuhTA{5+NMnP@b}~0JOU&v%M%4r``z0xe7NYHs`WZ0!juN%4?tZ_FQ}f-NTi;Qp*5W zqeKJyN%or$Igq_x62-vdR8bfh*(Ivs<%&EQIU`| zF5^W1FbS!@ZcPR!2-7$7l@c+uH4^~;)@kJc`}NZEk5%71#qmdQsZrA>@M<&^_hj46 zx%zH?N(aFiD)xMa%^wYU@(InJSXkdmqGJRJT%0rvxc}Yc%?1(T*_~-(=LF$3#b*os zVr~Rhb}B9t%}>4?W7$Zf({(qrc3W%W6$b5Ri_AxeS6JY;!n)E4uFzG*y@&1VUC z<$E2CZ21EqrvO4AkRDV6zG5Z=;)_d8`w~Y;d!fOg$+7g5`#prjzz_L=`afbu9OH&; zs*eMGp3E9{z*fl*ieAJ}@3;#up1O=S&4nGQz=CX-LCx}VCR?EFR7^GAyikyH?h-Qo zby}4TdU<7GN6TVAI&>sDAZ@h6)~~^1F3A5{Q*8UhM%zTrPfagquNCihx$&_kNW2!V z5DzQE;_?rfuM^LAdwx3Epn$r)fr=}Qn^)b0VwYGwzrN#~vubbwC=NR|2Y`|RjuZwK zQ6X}NDGZ>4NgQTG#gehy236Oib->Oa;jPp++ex3wAX1l-%bHK7=M}|wCNC1Ou^)y8 zZ07le6Y8Yy9WsoNOMM5eBH3^Xc|B%jPSAcMLwt^@$;}y`C*qY^zb%vg9eTN9dA2!7 zf%%!G#q+xDsx6V^%K&5gph41;@0!|{OZkJoA00*ul~uZ18=)z)X2c%U8|vVbLd z$My8wM5RrRb#1zHy`O9|{nC)dR7w}q`sdpmUo~7T3k?sf+vy!#$$9BNs1HN+4r2z} z3XW;rt*%^!o-d5=z?`}cww1-VCXK(4%!m_;mkuiudy5X*nP&mAil2RVPnd>2CtPmt z6Voo~W68HD_WK}6sPQpk#4lZAzy1&}vdiz?<{F%HI{xew6yTnJQEZ?$CGZl@wiVxp z3@PJY{>aZfs4bNGS~y>`^;a`n{ND?H3Wc-N5|`ekROo4*Z1A4=aSP+|t$RWIf;2-Q zS5;W=d^$JSir6-iZ*@#z+K!P4zVoCRH9RS=roZc=;{Thpw0g+!zdF!4c|(7!?^N;r zhv6W$^ifg^ZR%H)in@1*-JZSrP&f2joPdF=MJfFaYwUr{SPvUA^ubI{4(%Ru^U7pP zBR*lZhBEt$?>5YCVn)V!1pgmjZyDG0_x_J>3`R{lMu&u?f`Bwb8Wd2FMsP?sNY_Sp zhk%r{beG_O(GsFG5>iSjAYK2L@6Y#l_y0Keys_b9=bY<0&$`N>vZ?Z2bOfQe`&@Hq zJmD~#IfnmCFG#{&Tng`zC~!AEPM{L(FQAu}1^@_lD9ZP>P_0ZP7!~pcFv3Z)LgN?S z!p|UB%<)1DoB+7p7E4n>YceZVEHn@@h*>CHJiwR&LU!86hFl@4l=Mr?>Irwvm%s{Tcd4hJh#pXtaX(OMji$kJnh2l8lYiI735I}I&IvA_ z1rCq21c1V>(ga?I#=H0Hl^#c-g-&|xEm)zOl0p*^eTbkr2hQ3WVaC8hg zJ}Ce@$|TBG;Qe;t{eM{i4*B-z9RGEZ%N7mI+Rl=-H70>y(pil`XCu;=Ckgv?8Tt>B z%5A&Xpjp-HZ$T>=Twc+H&&!?BaaBfEw7Kr69KVwSGEooEl9h%&$-MK;-{9|OF%b@P zMvdbYTo3jL^+*}WAqqW|pGz{e>HbXN#(Y$Sv|_Hynwz-a6%xL+(%Okc4*;GVb}S~a z<9-Bo8}qa?5(7`6%3%z&BH$MbBGqE5 zFZmUFeAVPctB?Dv3oC3e4-C)Gvo915R_TQoq=j7I8&Pm`69-PA{C2Kuu2`!rU+(2di1`XE^+`bhkjfA@p5={tTK;=MC_Y7$6=StO2(&JhP{~5`Cr-jZ&Q};@qmAs z-I*-KOX|a=fnK%@yxeVCzV_()e)>(lA*=kaU^;|x&&mf`gKA1tV9t>i1E zJ;%_%vM&}vJ#H{)tcvykJWZK!II&P73Qjgu#9;padycBQc!zR|HjP2Y5}Wo$rW~#^ za|s<^Id=NaH7<6)NQ^jsnGdXd=JEc`r6K7<{ge(%(|1VMG|u#IsZmXyXJ`Sj61Ffm za(l(9YgXn-I+Jc;fi&Uh=~qU8)?RV_ndK{*?TQEy^>Vf8l@CC#&RQtm_fNs`RrMc9 zY2=_n0|6M#@;c~l*ar5320~pO3NRmm{80M5FgP68#%ZF{4mo`&3s+tFR%_ITH~FD3 zu8xQP8?<%Q_?)C-u}i)JdYT}G0g7iVFH2i>*CpDMy0?H?2a4t$<>m==2am9dx#i``G3 zj^E3O_~{4NGC$*ju4^$hV5^$p=FjCJIzL5mW55#i<~WenoG_DLcU@d8pe-*tV+eBR zZD|9}TrSrKNE*YT7$Gjjni@t-#!bLU#lp+lo6jOvqGy3B_DiD6nYAF-6fMG*$0Ph9 zVKF#$fvZ0#cTt9vZ-1^=IkVa(NH_EdUM}s4ZCPr!?Fy#ee`>g)wWVtWvq@KUdycVw zoE4APt-jl?tkO$2Kb`9`ri?}GyGk8L244O+cWeeO93FBA9T4-9gu@Z~m7N=7UT>HH zXVt&|c$p*a&KDV8YX2mm?oiTCrxlVFd+~nhvq868*UhiV^;BfyV(;S!bGKL4l`oJ; zH1;i>-u&|XBkw3?i_8(79-aq1V5EG39?$=vkW550sUrPXr??Lzl?FFQOpGORm=EI1ApQ!RAF3e!o!pA@BieE0<7rj zdl;W|3mi}q2@FZg-t=?)gHoP29lZEI`Dxw1e<++{@t!z7H^*@%2zxH~L9UX3LbMsW z^Cv9_?{dwIb~Ye^f8~)ucg(^qKa*{(nD-=(>-%yD5e~#rpD$Y&k+1Ti_X_6ZIzg%XiXrRooZWAW9 zb6~m`x{<7z6wl}Fr*M~^oZfz&SAzLFy~_!FE{a7c#e%`sk6DjD#B`l+DEi^%{(4}m zfCTX~#-Pb8Rxb5l38DDd3}LUm3p8zO&~WiN**^uDVxA_C^lLaF7=5&RG#=Z8p?QLc zFF35|=@^*0LGVDwx-#R6n~dcA-k-{CQ+Ap#R58c>zwAy*lRPL>%bJUf`=`jllgfM(|58G>{EqK`o_hg8)nh9!t5`@&u->V2jd84JNO+GAU0tV0qzr{%F6>_+RdgS+uB<8%4Djfo`^u zBb^EAX;yMmVS;UoMSPBv-zWQzPo1jjj2b_u#4@?%&$ov2!h9KVWA`kfFBGlWXidWYtFAlvaTr`#khq=Jo@0zBj z6JH{&bA-QY%6UdNy+6^xr_&Q~Q`zOT-d6v_uul3?K{0^6t>3mo9buxcSv~Ll((=tM z!f6E8RiN;5Vhe@rKw0-JX*O{owEp{`RWN$v^tYg*nJ zaSGXw@Z_I?F!v*0Z58iuKRvqH*2M{x85}gb2oPx%T;ym_S{t*04PfET|nfO6cV3itBPYL&iBlniILAN-Fz# zH`q2>)|k@YAceX~I+iETO@ybV_Vw$@Bn6V;+bS2d%CDd_sU#Fv@Z45-lR(<%L*VKo{N`l1 z>P8+6i}7)6{_QmKlg|*QO9qjhJCvYv?Ab?)N#s}XI!r|1ae47@`MI4JIs!wgct_J;=v!y3089I8Qe*yO_^_KKFt;I{1fQdeEM>)dBMq1 z%!%>l*N%&y(uz@@|NBh#Llsm(iy38ibRG2zb;}B0dA$vmjSJt-*(Oo7Gx5>GCtmb1 zXmun;Ku=_qWH)-`oly3@lLuVwbd)k;B_&_uWow7Vt}=d!`8ec=zT!#j3o}xdRnYM* zxyOvgiB{8yto%m)PYc!S@@AEb02JWB=*>%>TY-*kb%Ya8MJVa~{yw zPe0MDsHNCNL^q+RSn;)K429k{eUe*n{M2TVD|0K%UBq42T$L`!E)BXD%tw6Ez=ik~ zV*4tpjl;-V@8?d-?uwh#>zc}(%Nrig3E1l0>q?gTYJ&_!rfT|65cP26Ik&rBpj}+4 zXzfQ)4#NhH#_4-CI^q)lZ||#U{8Ly5Fk7(N%3V&$?QJvU)pDA~c^lfU&8x}^NA3$O0no6i_N!@XdSK3)pwyL73rs$WU8FEM5qx}ekiXgVZf~l zsXR>DUL#}UXKv#Q$i$vxQ{Vi;jzD%FF9s~v`3$`MQ*J`$;u#ji`Y@~*6e``iP8NCh zNbY4JJIYy!kjDTqOwq zF;V^-u>*)B@aETPAV=ACaPKANKs&EU^eIR_zL2r46$NO|wGm7z$sP0EuY-jZ#fJ0{ zY8FZ)+Vy{*mVC1e%hj*yES~{#HX3%IFJY#{LX{PSIa=ZJNv78i2i&$$tbU?IweY2cn z&BxppvumH+@2B1ocS^WcjS|CNs#k|zRhN~u<`!@3ax%pvH&3lzI7o!mm0EJ2iXRaN z>5*Bm0hO$evc4?a+(t|AXG`Ao zxn=gXTemN<<7YkwZ7Kyef|**SSHz!5Q!2f5Y^S^L`Ktw#6=Axg*+g6W=^c3XL$h{c zQ#_k~=~PsU8$wbRyd9TR{i9O4Q=KO{pmVNV==mP`qA{Qc*%TsU7V z&3f7fhLnmIv17mJfb^6B@X(uWBu$$XaCdYb$_JAw!1znQf>!@N7WmO1lai#skfXxG ziISW-TMy&?ffKAGXb2P?KMj{&9Ya#bBf=Ml{;3%^#L^jj1^(6M$E~E#62C(x7y-39 zkgPe*k?7Pua!P0p!>X{-e~h|&u29#*Ra_AC~f)C859hEC%`?73!Vc&PkDiq$-53KecG(J>g3ET$B=u_&Hg8`u>gHt>?EU zRD1qCr5V$m_V$kL>RH1NI7E@baUW_Y?N!+bL#ZaMlYecTT;9rTb$D4(guiCb6d6<7 zU;G`o;lK59%YRv7%V+7iEZP8qyoT%ej2$CA-T3X_RfQ-bIU)ZpF8s@UE}@eb#PPlD0*EPn&+rUpYb0>j0nYX?b19(zMMb%Y!8@ z&9dfag(H>1-3{?8jA05OKC5(9$czGs_PVXgv|X=sbsVx)j=c6h&RzaS--_f5g0xlP z)7Xi4yAXb#FKcJv@W@?4p?o+5-(`RQF{~{8@56woeB@(6HX`w{(ggzKQXl3|)}CnF z;!?nLpeMV~T>{Eigcl$EL+##ID|!pLkxQ^5Q8%p5c(pqJG&l347H9#|2lgo{KBWqN zQI$HcBONWBZ<4~#vK#mvA1$^GZVGbgsWMMeJgsJJ^(Y6&=$}wRoJ8C=t~!FvI=t$* zq0P1mm!HEq!CEkw#*-V4`(R+9b4+k@;qXjovT#&t_1i&f*Nb5zr-Kiv*B9utlMIQy zX4w}Z$LDaa6#i|D-C-ux&V$cb!|aG>G_VHGNCa6ZNR|k1dc<&=#?YjH)3}QF-ZQ!Dl0$6jY%QO2KwIzFI~ZQB9iciQ?&C@29ph6P7+{%i zC1Oa}p^wQRcq*_(@9aqQmV=|#cR^*Ci1rc_001&Yp{w_eF7sF{gg`>I)rR?u5DueH zc(x%(ByC?)40Mx!_aoH9+!LysgaiAA3Ls*xd|N}($nbug*g#;_=YmEx@}Ylqie86A zz8L-QhF%cCr-RXlj(OLvQIx;mK$?9vN*>*MI101&(PE}1RmFa|FdIV zDP;`yG#b6ZJyj{Bk=S`hrWi(mbFM=5APXTSJJ&GGHRUnaX1)80_S3C)wm1|Kuck#o zE9JF#6n#BIdh0Mc^o&N31wW6h;k7!5&WIM}%1$emoNv!h7kz*>^boW~9?Fb2r+?x?A4DreWirh$2pV+r> zIG7adxLwNF)e3rPLrm*onQgZjFsAW|ylGcN&NM$7`&^ z;kvri`h>0L1p2GPMXIZwDRup@dIJ$bx~j>IpdTCjTWNWSV*U`{ZAd&;K%FVcv{%Df z28nQU?HmC2`|3vq;>?zsK2FR`a%p*?JZ&6TRZsfPudH)zwodN_Ggk@dRRQi=Y%)8g59ZYIJnICwbHHL74=m?T})#HDA|G61p$4>(VQ*aAVme*^lP7Kig zoxju48H*<`@f$)DXmDL-jVr_HegBRD%%;0EK;1X+8|~jYH#cl3a0vMC1@%X&VkjYZ z+4b_uGf=?7c&4Mcp~}iDgVe0D`00uL)Y|s?OM%w|dL7p{O4H~me@VTF9yXfatvn>F zllh>Zd0K1X!UK{L!^0x;qkx^SLBS=85sMJZbcH|u;GPy&B`S6PHtJ-lq2EB^#VoG{ zo5i%+OPt##VYDD9$i?0v5DyDVU*9F&EWE2@pI7m}KVpmn&7=SWEpa@=+tJMW&VgK^ z9XEEre?Pzw=Hd|1MnT_$T)FycC6o`66*8(c$ZpC8sG>Om1K2t%)H9W@U=INceYNWj zYt3o(zF^^p1_rK41J?d<5Lijm(vp0!2K46ZOCqxD4BkhW8X64Pptt1#)dmo8T{WS7>UN7Czxx>n@HelU-if)iIt zQ(n>h zfgGkQD-yhsicj|wYZ~KKsMwnb7}*=i==yq+_wvr$VTr^?TB9%Rm(N#O_R7y?(zRk$ zV!D!}GD6AjYMtv9J!Pt|f__yoLnp3VJQG3G26iyc$pz=OupR*T!`)y6lZovE? zgS_Ty=C%h>6d|mj_q~(Py#i5+HWOlRaM}`Mg-$CNm|E&A_#C#2e6xiuQ%B!Qko4qF z_lt5lJPE+sRiJ6>zD1d>m^5EKcAHxL?7#c*f>;Me`oL5#8!P#FJpk8YDg;NkmdK8*}J}X|LTZh6U2W* zAjoWxo3^Bs2oB+g;viYYX~-aGyrFcvUjUS+Hps%FM(B++=P2GeI-&Rjtl5_o=B9nV zUNVADfBUi7E`M58+xh%daVUV_owji#^QN`Urk4D(%9l{01}6fGjl6+mi2e}}a3t!vVCoFGN@^{UP^j|L&d9=U z&)1#3Z-w-gu2kwCSmApKb>TWzY&;A@(GmuwW$1PG89*bgwDl+KzyFLT#Vi{Z^`w)^ z0)fTEwRG9c+#KQ=&pe{f?;N(J`0aqjh)06^;NEwTE1Mmg^W)Bz?1)&fhKOWhG`Xe0 z=y3@W_MmQ}=x#`}m$wudgbn4B`OD)kCFIC;s%M4hr(V2NI)pUKf%4A`bJWn3Iz8M#kB2m1YnUJi|p z&%0}+=snZveVyF%qd6**JVk8~ocT-=i2~F;6E2ZB&m$D}TFnieD7Srg`SN5Eydf!- zyl4eR#15zZ{NDTmbF)<7r`h?3$BB|9QoNE|Wgz_>X|;)==s+l(9NA%b|wwUynz!x+T|(-2-v~CS}Z)mDE+B%tB2$lGGc- z_J;%RNv<3;MTGfCFRgFsUGq*yn^g_8W+s+Ln>9_MJC_c<;UZ3TtP(#n@NzAWD_Q?g z`3&(tMwD=%{P^)asuc^1nwvlOlUI6AFCBZ%7U=A*gm3|~ggkIDn|&{AdIgfWF3x(2 zmQO7*Ae>7*G?vWKOCLohM< zmaNFf&-F~*y>6@HMP|3r~2Xu zi-~tI5Bgn|1XQnPWuqID|7+=9{A=l=(z{zgLO+D37adQ2BsZD{4e*Is6WU*5Ii@?a zX6!q$AD{0KSS9<|9@?+ggr!WoJ30LfY;`BDG;8`WX*5L_vsK?pZC6)*Y`-V7wLePV z_T@wO^I>)#+6GcYgap@)YV|~xqJ0nR7^(%H7#eU0TnFCv0NF$d(X3QL=JOe%;BPHv z0PCOOr>|rXIwUMspda3vZvz;B%_Xpy`#|wJchqt)L!uD9Y;AEq3dj{sBur%1#RAq^ zr)$Bdww4!;nLOJzr%l=dK95Om-;I+a27SE41_cRb(|_3gp)pqfb*U}y#niKARR+r) z4@4p#H>>Bpn4Ro*7;BVEB;>o&t-9KSq(98$$LihBuG7LFA;djKOF(!-eBn}g_4Q8n z@QkJ`BaEp*U|SeZKAvFhGos%l4~gpM56z}B$F;GTM_n?@x!EllmJ|c4e{m|vwk()u zvPP7&Qc}KmE&pqJb*^mY^iuV_=+1k$cEr@1 zV15o2VYPC1n>B;t8s4>{eCQh>}QsGv?3s!AAHRGatRW>Mm}8GY(b(rOHDgk&s7<0$CoH) zB<+;DuZmu=WXocW*myp1zezEFt9>h0Iv~HcKyu+^Sw(KTLuOn3CdCJQneEa_MjCY(YTy*BaL4I8*A?WqA)Dz z%O#clXo)_5*j$b)EmZro@7Kel|CKj+ia!8cPw=w&m+kb;h%vF}jG5k?^S*KSV(m~5 zAr1*;?AtPkzqVMnx^%+xsMO!=1}32j20aa0_Uk6Oq5?;nRi6|9wFI9TAoxkHtTS}i z4Sh5XBBp_~NIUOb5^NgR!%>7|tJhT^1G+n2;^r?fmLMWn&9leGVO01& z!+lD0^6pBoduM+(a9Lz;{~AuC`cRF_X2v0Xn4F_8U4fI5ZmpTWTHx@Pna%S^5K7U> z1{vDz5t8{#m0|YYOp3 zL=Jgo?BlaE5*@u>Yz<1;hxte?V(Y;!2?xp=^~#zDGlt1WG=d=QR0{IeM`f8Kv808d z;rE!wohyM^sjJQ=={Tq*oHwFY&M(|6fO$pta!WtDc_m>ZRFy&nJ6m{Gho zAa6avt${^x;TyYBg3Y_vAEV$siekd(*!4QkL5JGRH4D#U%hGu@=R9-QtC>>J$R_`G z{qL)lnv+3yQ(U54&43Lnyte2!u6K&ykW_^|rSV9FUeT9evfgL%uo9DH`iov(sb3R> zp6A@-wIQc9ElVQikM!_~(;ETDiO=U;|ANuy?8de9syIavchg9!-TN87X`Mq^fPjSF zMM)%Ux?lg8RGoQ7VC|O^Dj_mQ1#*b5>S*W${s4TCHVTcFE%0RdtFchLY*OR9!$r`Y0C_mc=nNZ-n@D35TH>bU^r=a|Gq;rHD9~K#_&sf zC(R#j_iVp^r$f@LgEoKFBx*_=4qDqPtqXqO_{`BzFKqR&}^5*wTX4ZuuGg zo&kwD5x<+cxck8K99^$R=S8zl%jQT>@?AOcvp+ZQI(G0`^e)T1Y=f)uwX1vn2D%Uk z2UJOavs2k)spFHC{#v3t;!5Kd$7(Uq9!W*Ub5G)+ptDKkT3%UnpYAL341t|jo@W`Z z2-P3*sLb9TweHAcjxfVFZCo>c8P=?7c?L6S&1P4tN|)D#&vu@~Z7`{1?-Y*-sgRW= znZEyi%*??O5PZseZ4FoJ?C+yJz+xU0ZD`F+|2wVC>1E^N|3eg1{(I%Id5msJU0l2+ z4d2_86KJ_)c5Z2gy`)1H8s4=Pj(VI#u8;D#Ul5YX0>vUYaD+fhtVmW;q5P)KbQrnx z9jZv{V#3mNtLIX%E#FH1mi{rxz;^*xrhW!YBfp~IM>+(AhTMf#{ZW$HuvWp^Wo3D_ z%l~R2Pz{My%_GPlIPQQ=V$WvxrPmJe7}8w9jo+xfmEuR<%PR@^E5^PRT9TE_D%LZ5 zxyQAAC38T20omhfQi|5{p}+hM2ckJA=UO?)t=#5>IA%^1J90#?c&|i?73vf)-%d;< zE1mB4k@?P>YWMJat9s-R9E@T(=t8*%C!FpN{OYld0$-Vh2z1uz``Mu15IIEOY?5G* zk==kB3koSk_=Z6evF~=Mo1?{FKiDkyr^;>~K0jN@mU;OiA9l?~V-A;#Ag_Z7;zB>{FUQ@IZH$T9ht zFFvUA;Dkpfz&SZQ+v}j-{0D{uZ2lb8iaF73?cVG%v0Ucp$L!)YRNi+Jp@CSqyeNuN zW!YFJLZTQ5aPd!ZsC3G0i7|D!ZoEY^#?lK&+IOCb0apqtKqAc)R!7xP3haLSXF~dN z%nS=+Iqyt^i`!}`;@%%So4l@M8!KDfRjlp|_dH1%t@-hQNU zO5tDv9wTo`QG4>5D zT9F<+^?f}3g|1%TRqF5Ll}EG7s;{5rfu!+)QH2NcX=2#W;A>V~aDJcA`kxGD&LyST zn@1&rc3TJ%|HBlOg+?CfyeChp64$Sl2&1ocoZ_isjV<}9jgR#L7+cG&b)?>yT=LX* zdGGS~_QJ^^4+WT|f^`7R*EMB;i-FqVmu%fWd6)IQ{ne9+TxlSY{{6&niSp7K^V1(& z*PjB9WjJ|Esj|dQB2GgB@EY;_V{oM%h*Wk_kZh?9lpFHF+sHMoP+fzLXyS zY{?7GOQf7oZT!Il(6$B^!Hk+b|47=e&aKR?hJG_SPwhE4aHl|t%oSkxkSmwtvmT$` zu0?{;4Jlj*m`Pw+=T6VB=?6yBAR=D14)obQ7S8B9QomQ=P=o!utX_phJ*g*mmZp~` z15NYoLx^)cx>poJT0(Tfj~`*U0PNJjfCC!eqgjZ)QK>EalmX8dVTUqO^sjU3{cM&t zx=z`4^E^=EUN9^jtL=wY@`1)SKh=K@^aX;S7Nqjn4StJ&j(J)Mc@@@P>ZCc1k%RA! zLctBbG=p%TUQ1ivkYfUK0X^z;(*$KK?o2ID7}P%PSSA(TocW*&d^=1XUUIzI>Hr|cMDH(2hOLzsX5mBAX%OBZa`Q}sHnm} zuKIOKsa9)s0i&t$WKi@q79G7`y^q>4Yp=No*L=pXZA$J>n^0yWh&SUho3@zAXQOfa zDUZb@MH*4Jn6Dz*=7DM_djlPuC?Bp$y{>rM;cUc>Wc1eQg zQ^@Z5QsifTe;C{MBKH8Tyk!>bDj!;MVV(5|NrTM)oVCzE1|i<7R(Xg;@K8W@y*N^L z1f})k-@0kh_y{rcv1~mbHHPi_=B!oeBeh^3kLMR>X8-MHuhf5l>H8N={Me|_DgXsD zW`pkgQ6Tecn34JMVNdc2D1zZGM=H~g1t%KPeT@qkDSD7{S*G^1%w`sOfiqP0{4x2n zoDuT;qmhnfgLvcu%I=?qa+>(kaj$@9t!iWI_}72mW1Wf_(}E2GaqUxAz!)hLVxftK z9Db-L6o{f;4w9^e+oZ_JkwX9=EJ7akWC7s!V7$Q%U?DP4GhTV5lM+Sf`tyT|#=S`J zHT>f;(_*_^4>#U0iK9?$TqGEO1m}as8e=9Et9=jM)nuvO!osO@EuWy&2+3?k&oF^G zLtKgDevgvprSpCR9s8? z?MYei#qbvdmqG=3UoyPj7ALT#X4@h2;+x@WeHbD~iC`jGGvW!?;B2mY-K57=5@TlD zV4eHYR!g?&+opg+Q}an`G1Vs&=!=J_hslgn+#2yoQqbbKptyDV(_Gda_j{UV6B>U6}JUipU8z)m~jX9 zFvxsW*y0_bKL+$jbN&Pz8o<|p%}r7S!PH5*Vly2@fPeZf&Mek9s15?u}!0+q4pw_IaUR2zUu zi37M?$u`$g{s*NS%L5nvy{38v=Ll<|l_+o|dYo1Ox(zjkJ&-1T#6@_7^^5+Tk~+T(`4VV=oIhM@7U1^1TcfA7h|u!>ef751$X08b>nJtdvaajvzQ(&a*mg5I1t ztc$rZtiR!AoGlrmIVY<1jQh~xtPlgPUjPWIyX{?fGk@jI%L{NywG_*-;|H_M|5nGc zh?!1`_Kid{^j+_ITuO`^j#1tJb{@~4AI}zz^~Yq0&P6H+3W29v-<rc~BN!EJnDM<-Jp;DN+d@MVLZ*m5 zP<1GMluqgK`DPTj@*+l^*SIxIZkKZfShXYnKE0UhFBX-W$%Np^cdO+qU=x7K2C1&7 zmytB>1nNJ=3C2M?DZ;2uB{=kdmIBjh3YtAsS+|wd5EP{uWA~XD-l^CwKj=yuR|Rs% zKr?vIL8kED2twb~y_dH5n)h20I&a}pJE>86NucBe$UfyL#&(d_rRmiR@0+OitMLcy z>O}J_?2#14ktm{(Fes=wm43aM%jRL!a}`cjoS#;iSLXH4l%YO}zf~jOGGYCGuFXe$ z3BH~73UaKe##`aSxMqnH8D0$$vyv7*W1t`e7ZzfA(G$hT)zH-178#)xl-txZORsB1 zx!^1p1%0{mb^Sz}nYOddV(LZ~rWboZx%_#T@=0E7^Cd?ncf4~ptq72;22Hy)Y?wHf z2fiz^NK(a48sNVcrY56|Yp&*WAeH%>{M~awN6gQYPY;g>_jADA96eDI|AxG=u>S4Im178U;Srq$L?v ziQb~GzI5GqB`ZPlgvsB@RfTZZBLbS&xFONKvdH+L14!g-(Y1*k^#PKCmJQAC3ob?g zzG}gK1k6Q-6}o=Qf-h~@IOLbHkU5~)H2%`<{hmxGtcNvh(`U)|;S)V})C6`4VJ4Hv zgs86sEAmp+;!K#Gw`MRD1WKqviN=P5p2q!cVXXjr;pF}ux*Nh7+@VQNYH)|&q`tfB z+{|lM$6ZQ*DbwzkHl@Dq`*M<%T-d+lxb4mD~OfMqEwgGW3n`QmxGH~vqDHSzN0+XfNAx9qNiS>B~N zZ~hu|9J;H_C#l4R@&9C<5Yl7FeAibvXyPao3C~ZJe+8w4$gh=$b@rjWICXb19cLN2 z5}l7f_F)8<61&b89s~FBEY0)3KHh}?)~?NecfJu~BtI?^%`L?SrFS{Kk3?XCBf--p zf@w&YO+Yc92H(dYt8863$b9@5U?NzzYm))&2}>}Xl{v3*p9(VCMloFPMkBP+I2}GX z_4^+H4Q!WAj#`UI@Y1UHe61e)sLAEX)?T}@b#^eR%AX^FMTf$bULaw_1+5*mZbYN@ zey$TsUm*o}ie*Q~Bpg|SNj2;x?M4V>{jX~_=Wmxz8jr*11&re5UgKwd_-xGlmdFXj zV1-XnJ0ugq4kbFvPUzRsl#EE{@6hMNcKDgG1jl)dcm(;{_)Jb!;Ah>>liN ze%FMATjH#UeCc)F5r_>ZD{FMV8NkVIurbrcU^zvGMGx@*y$`eW$o*SK4?#b(?3M00 z$JVzEpqAY@u>!&EA3n$nd=KB|K2?@L#!wxm+5E~d*5^*A!W#r%l;8;H>snTp(2ri- z8&`NjL*k#RCRB*f^^L#qO4}!US3;Q@Oc~;Q{iZU#y7xWm>`rJLSBSd(OS4y>HqUQw zPFb2x;>(JKLv=RNL@n$FZ+=laH=KTS4$2)7%ayty2Io-<4W+_NGw(gTQ&gYoRB`g$ z&6SbEUQKNbvg@}H;X%nz*APvC}n_DvsIF7^LwOvGr)#>f6w$0GiR zFL`!f@@&S9WPSA<2#6M%c(v26V$8OL8fGA}s{|@Cit49HrA&+V^n6X@2j8`1+c0WD z;E`mz#jInS(P@3(K9W*CpUNN3c=x?%!vm(u6Cj1&fVgme;IO@sAZYFCn*4vP&Ubkn zDZsu3P$$PybV7;0UfMksC4=NiPLV@AnjZgo-`uDOBlB;4wD|hq(3M15S7r8lB$yZX zo)HK127+AC=R{&0dd}24F1C9CraKfx12^~bK&~(>`wVS%eKeB;LTJbo!1{7Qq(X_~ zmM*lR)QI-4{GDSbITS#On@@0#XOAw`^+THy>q>5>`cE>l%jq@y3dEf_qz|9S|8#n_ zPRK#3`?!j^{T4omeAgRs)Ze0EP z>~f)jZ!c?yxtV+GjZv#VZ~pZ?{ML>kY9qQ=ZGw~1s%6(Ftk7U031PKt-iYnYt)*4f zVvoj*xrT8dv6>W6`&HSvOpL$(QpptX7guVpF;nkF)J{<=0V6P~#_d=M{YUVAM$Q6# zBllSqrLGER%jhFHhz4m!l3z77cTW%2Z!or=*6MWb(We`f%=w!bkJA+{Uh?LCA&JXD z{L_Ynper(l7eG+WTl$r3o)S-;E_pq)_$6_l(;l}E5;Yx;`xMBIk&l>Vx|tjY3Zaxp zQB7}i;y*Gjj4FWn{|ceeKg=PDhD>N;pxxHezTfHm8i|CxF^Y*1(oW!P#`y66cvi1- zaT$enQh}LxKdv&39SEr-q}tS8QCE9)2TzQr#s`Usn!P;$t~c)(b)ehn3ukcPB79FRRh_d3?d5E8|P`%yeM-|x9|QnTDT{nB(PBKfgG5*)FX zrO#o zQK97le1e>Gztj-K}M3zi@ef*>ZNKf0Oq1HcF;lQmp6Z{J`=%W z${QSX@1TAee@@c|ZvsNF+QlzQyH;oD<4eCW*bP zhiecaUY}|D1Xs+JvymJyHx>;sI^`PoBA#a4Nqze9n3Li4`Z-{> zTw)Ac#>2TgTu@y;a*E7%{Lt;){pHTspxaNg!=i~IxcKQYRY9%h>81x^Un>ikd+yHL zMhW++CN?3oP13Z7l61Q_X>Qd&R9jtG>uO8Bj;og=C+S5c`pob43b*@v`|G@o+)dy*= z?%-W4o;;(*!e97 zuwMzj|Jtr*AQuqeUM*IXkT9~(Gkx&Hb3;AI^Bh*u0ijx83^ z47>9yxewFxz7H{!Hc{Xy`|tZO^5xgnp^PNk{q}eI=)I0Dy!XV`4ToR5|N8yexN9FE zy8!v(aZsN1(aX8z=bT7ZUcM-*EpRJohZZ4O|A2pL`I8R}15x&X@JnUxlZk8l-lGP_ zJ7LT*YwvE(B?LT2n-XTPgNz;9W^rRUm31_DN7e_EaN=7rrgyATNf7!XTVzHD1+3yO zxvik@;DcSLP$)~>yNOvn;$bCwE)}>`ErsqT|`(+mpp>By5 z@(4j4Pk3q9@=<>5GF}&Y&u~AGV%D;`p-3{w!D>GodPbHta`l{`$!FaNXB0N zCey<+zS(cz5P5r$bIAlqw10&9i|;V`&2HV7BP5Q6oBQLtLTxJ8iOK$|Vqa8-bUk{? zi6ejceHCfA9SLg0md_N^Q78v-oi>1R#!pSJBh zt;Wui@Z6|Isg|d95w%Y5{m;v){SIP9Dwt+Y-R0;QtSAX;ehO-U=)yHUqO(EWBiD`}LZq$O@|oaU;EB_-C1fSXs^N z0THiJo0>#bD~6aX!aS$RmQLY`YGHvOA8A$d>APuj7U_U`(R6njA`^aAfrv@d74=B! zJiuPw2ZtE))QPT zk9xWzHhS<9Gvx16K&2tM{Og1thf#Qwu&CrsanQr=h|&a8bF-_@xKgW;!7nnZEIxrI zF`TiD$w$H|78W`#->$7hXqKuHpjLHT^LgXK1hf_~as9`F{U8YU`5##v$_+m7csdc{@k;my0;tNzWk;<=ESzLsOhO0R{(NidKHc1{K% z^~xaoe^~$x{7iE6_>XZ}`ZGFFXRxd@P1S2kTvPEs&z^u(fLYo^H`y)1sH^?4W3gso z+pXO8mVlFFg{rQ23#@>uwT0*SHSu1DocExf1KfhAk^TL_HhXxi2q%d93C=8#dG18} zo*(y!pB!Rf+D=g$0@VphlFEOZrZN)Awiq|p&ztt~KTK1bP`7Ynd4T^VNYf0D!n|l7L^IU&bSO>T9a`V8VM!GH6hnaXb z_uNRFR!Ba;1l#Iyv*$~#`^X`>0_st?`&-X+d1mj~FKasnU98z%{$`Q2xqsgtaerX8;Z_ieueeS7BOID8BqdE<{GgR^L(3HLvyjJ7g~UE8BCNz1&fK z7?JG9`&-j)n=V7ohV*^ZH+@?*#=B0+1P+xKUq?d^da84~g1>9z*W6xgjC?fQmUyXj z9Tg|P_hO%HD?;RaQ)ZXo?lI9uIh1&b-rxEEqv;zP>uj5LS8Ut1)7Z9ctBq~jR%6?? z(>Q6&#%OF~uRiy?^9xo!%yrHj6sYLc8*+_)&B^q^A;Yd227ppe{ z_A>^qXprUO+emuOR(h>Fa3V@RmKDe|1J>K||IV4VwEjmbNI=GIfq?Ao;N?kq>zQ4y z{mK^W3eP-vMkJUNHzy@P>9&f|ol;~Lcx#NYd+Z|B@#9;tcdK&4P1`|cQJY7H1Ig}5 z8=!!%_dV44qIth`%}NgjMl6}=`OMz)w_W=_#H1K5gC0jI7Z*z$I#kv4mP){8JzB6q z?f`Shx)Z(FwT=W=N0ahg4m6mC*w1}#&>V}SRl6A zo&K5(bunzd<3eC42=-aMXl&>uc5wBm0YDE7-^RKIm|4DG_gJ+}--?if6TPnrgm4hs znr1RX{GZU@xK=uPc2RFh&H@iEOPs7sCo9m|G%VBCmDUi<#!*fi*EU@mC-Xh}`Wby5KtRmp18OvvRlv+;|BHrLOF|{g*2Tut= z66pKY&@cez{a@e$R|`33Hp?NbZ&Q*At0nW01_7Q?Jv&Ctosm-B>o04Wm+h0LlX##!?HN`tJ}%rdFZ1 z7hr;a72$>#q4}T8;1j8`U#rRSqKo=|Wj&3}STC6r$V&omF%3+5j=*DV(W;6l_EO+7 z*@X6I1mJL-DjlQY=(3Wu&vBlHJe4IHk6~O--1&x}+#NBYPYBP|RdXYjbGqfs-e=iB zcL}OIcW6m#YKF_TQ{QVXvGofi!JQ-mguNt}WLkA8oH|`#=0|{cgpE>;Y~H80>J|O0 zCx_;=GdrAknkd(IN>bbrnha?!nA7uVit(RFWkAKUv(xP_2{}*~0U#Zm;o>{mmGMvL z70sT(RQn%cknryfOfXr4?WhLgvPIMrtae><* z^4vTu6bgkUd@G4rff~z$UrwbSH~;359Uuo?q?CSX-B#(O@sfIWzUMyMO!idQ6s7}; zd)!EEBn)3~flf$V1)45~n1X3p{iP)h@%CZ(f9Jg(C~p9^krD$c*u{mq8~<=WLR+`d zMJ5j%MJ3BID0FNDAHWDf+M65XCuC=uCO}IVXs_@pvzPZGU=h0B_3yX^<$YM?ubvsf zhK>jX#@5<(?|VYlmL^g`!kViU0NUx?Wk?~J-9;&t5rP2oiSWXj3(ht=`#xQ_6OnG` zBsf*kbx;Y38r(Zpj(iJ+iv`8vfl_P=0{JOH$pjJ59;abqAZa2@Aii+$oxrpExBo}o z<5?Hxz6|xg(6KZc?ZpIBBzA^X%kzw)5Il82<&Z{)CCoehR@oxvrAGt2sBh{|xt(g+ z5rWshw+?T?IU`+;0l}9N0~8K zy>%GtE4hFn~ju53Ri+dabNyO3Jq> z`dnl49tcG+>Ae?socX*jd_Av+U(EVz%lB|EKH=<~YZu_2z&B=Yt_?wVM%UBOqm#C0|xq`>=rJ7Zf{ii95y=e2JlSWcb% zFaziqJSlG>(z|Qla@ycC5d-Xf3$!U`T7CQ44tyM!1*UrfKTsV6(IDy>aOUhnhxjx? z-1j!r6}=>CaIalWA9(0ArqNP%f#k3I-F>TXahd8@(JAB+ zDhLuOhEoE-bMro|fn4afyvDt83XkXxsYR$tNtTiG_1U?J3i5WhN>Yn2i zM~+qwTIr3yF<~LLCZ?|Qp?+g1M~~jx z(Po)3oy{P>Uv6h2qsVrlAOQP$z3pgY@bDYRggAVD z2}8o_123z~GCh3iu1drN!j%YArU(-RtXo1Y8#9-XCc zX3)pYu6Tk;{6@C;SglQ%ISFJ4iM`sT2>}oR2d9TS$27}xN2pLi$ICV~eif>oi{&j+ zm@NBgd$dT~bvmDX(N0DQsC33))#~W{<>&K3_E^?8*P7`i`)jmA023sE>EJ{(=ur3x zlrE0=3dBSR_klKq*x5{p6w)a;B5+h)Zj2-UrS_N;(7VK>=QIrPg#h&AVH@S4v2T;= zh?IX>E?qUXwEAc-_CCZyUHpMEY(ls=7sc~mEDs`ZKKFQA?#nZmM>`1zCq}%hl~VEx zpN#%Uw5j*mxvEdDHotv_h7}G9NmLKp-le`O(#z?2k6P3Gd{BHGD>|!gs@g1!Y>%}+ zZ<_sF`2E<6G~GBcfxzd^m#%kQSxF3TABD{o(U=|qA|E9Sx~b<%ZY^-RJTQdK=fA!W zG@&aveXepO0raPVvmuoxkfm?%j|Dl*n$!GecS|@v*9)QL0-dYF+Ncb%E^x}LWSm&j@xlL;50WH-72x6zC3Z_1A zzUEbWFv`~Vh5B1V4u|uYGt!h=N@6(BMaUEldQ`*xHbCUlwIm`CU+A7#Qv~<9A0p?m z1(M6SD>!K=c|ZXuDjGYUsKzkK2P&xk4Ef@uP|=O{3lf=M4W}yE)@-)z^dX^-#pZyL zuQ_Od<@a9_{s3NM7^>!O`z#y5buL1x{sP%R*5zTSw{d8ZX1ti+lH$O*_@b#uM1XH9JYL$FkzqPQrF*;VehpR%>x>{`72v*6oS9;TKomIlo48wbRD*YKZ6j2;O$Ku6A$pPso( zW^#wx{@(!?b3ztv_j_ZOIn%!fJXMkIYh{8?DLq$%!H&Mco)p!}iuR*^vN(QDL#C}( z@`ENz-Xajgi7*%V$^fuiEUDTs452IB($&cF)-f2wYX%eOXb@fN)HSMee0oTMPn3V< ze`YnvWqm-xyF4mIc`*Hq8Ah$^RUhUrb{h?|vubsqQu#VZbzO7b$HDimzgTxRTVdd( z1tgp2#WwHH-M%-IRBI4e=id)8Y8Ek`bjBcvOj3?Sa-m#9{Gx4B_J3r0-NlSL~~ z$9GRfe8nHvaX+bCY;?6#j1eGw{-V||5Z zp2!93jZ$3}${nzBQuL6Fc@MF7(D7_FY%*0$3;}EFp{!*Zevw!I)MuSGjc;hYR84p2 zq#H}tRG^@|QXO$e zHQ;=u?-Q%*qpeN{7_bL#0=T$i>f8F`ID=kQ@mHJ#Z`9yvPFy@7*)V1!aM?xBVRn~+ z0%O*A#HXtvli)IIn*t}jQfb1vsFjg`-uJ9n1#-mJz4vq`)@AIap)K<9KAZM!#eTX$ zybdG*%{2elD3?h;ce3&(~kOL zgkJVipMQn(A(qiPSG4=l8*8)>svF=GGVStShG{sQB{0avN0a_`PwUTp-+sFpdfZVZ z2ubNr=XVrv;vT^Yh%p&VndOGg^5*ISV2p05j5uO~ZMNiLQ&+d#PMNx0@|ptIEV&SD zEd(hb0R;O#Y~HDc_lgd*p$V)UjrbxeNj8&`J2k7u*_`a4o9Bn3`q0=8Z))G^P{i ze`*;rdZWCa{|+Cwf8H?(i7BlGDrL7A>#cAIq4ufQe*X1=C_=y1f5uRitiBL-%_Xrj zd0?ShA#HAd50fJ(dc1NmIFT^8$s-zIBX`7AMZVcQ<( zGxYi^^;k|wsROy2MV7&2O6(iW#ZQ(k*Z)80;0_eVl0X)l=g5T;LyA0pLjiN=`@R+G zwK;+^g=Ip_6fza){EAr#$yJWk>@AH{CyoEi+pW5#jjM9-n@<9u3baKVuGkuW&4;?} z{Z_4p)%*hHg5IS(bpYMa%t8es40Gz3Xz-Q+VbA53JJCg+j87uUL6d2RK;@vGk)}TP z(jPwu-05ozlGhO)2qV|=)C4p`=`bJrIP8Q>eGW8Woao!S;d$IP#IR6yYbKxcaDT&N zT+?Iy=}*D{#|UUmg;Z^}5C?VE{EJ1zxD*F(PTK?(W5`Eq#qoSaZE7Z{>ZHWYFKW?a z-rNtKl|y2oj+9MAzm(n(1A-$!(UTYw;RdG5rBhUtaT-` zkej=G=$7-B)7z&aQG>cwuO!`1y)4+#S-62eD2ZHUa0|L@qaur~WL0()txe;xo zkbt|TJaZ_N5q1susG>UW5`t#QsoL&y8{Wrqm^5NyN7^iMXh#O&guG^52aKg`LVI&{ zQ_p(`Rg6~zTR!jn@*k;c^f3!Tu?WrI0qZTRc+6k&KZvqKqZlbxaDh<}}*vBXm# zfd#*Gh%`q?VRkmre-r;)q0wyt$}kg!empTlcmBb^c{REF+3x!l9=~pXS;|yPrP%+% zx<{f$ym9wsTEn1jfl1!;SOLcmHVsl_H%e=SbvZ{^ zwq2J84V3nRqpZ%^>j+?7E->S-Hl#YP3Md5#*;%M126=GK-51G-pv5IR86b)29J(a< zHJ}v5DS>F%$hUH#-Su!8>b7F~-2_3n^{yLZl_{FLB!Pau{%B#SNLk0sCeUY7;K|Oh z%=R%}N_VI-G97YdoHlC5g;o0a1DnK19~!cLljq`q?ChcuX-U_VoAAdWroxp$54F!N zst4M?Col^+w{P)3sIKgPQ(H=Nn`W_vIXbA928Oac`J$BRYQEQ6J9!@OZ{4u{?%C^F z{NsjgtG^?PLTTJbIZ8KWtfqmj&5U2hXwSi-=YqY#=s0iQtc+0E(iLONPCh%LFkoVn z5lR8oVhcY3^yeuCm6sVx@t(wY|L<*I|L6FQrTB;5cVv%qJ>lE(n?DM!2walRmhF4z zZ|lLO#Vj*iS$;1#W~E=(o|0t2ll_s{i$UiC^=T(QG+r%tsW}MI-*W&P5lHxUx^%n` zYQZ`j0EjH_>1O-Rx%pc7aeC>wj7JEkplJwB3rg%P+qS`@DI!D+yfmU5(%}W}8rwCZ z0BW=+3fj$C*kE|ob00AT^~bnx=Ot(t5y9TZ!@Af+VAv}xJ9>0N`l7jbk5Q(16FQ*A z;f>hTfE08Gip5PmyMH5nG1HaK9UaJJbwQ{KOhLXzptI_IIfnYF)O%XHAN6y#H!ia z6^BVW?~$OKDg?^~_x_BJ3_ut3#H9(K{S;%ft~h{tJ5M$_O=1d|FKe?lnG*gf0y5I^<=@ zvT1nr$nt&Wms}So;@Ui|kDwV7#}Kx?dbxuI>Q60gc2AvT)r8fE)1mFWRD5a7V!oFq zW4@%D(FMdkY5?~ROujb7Z)6hHU59Axy319m#9{2ME%oX{U?bZY!R7U5i*X?4_ZrfXb z+7La@?P^&r5@#{qlAox>yv_UlU`gEu3E7k@PGA!^OUy5g4O+ZAoCx@YPF8>}qDND# zYBZw?^>|q{wSj zZ=uptsxzG~$`7k;sYmu8Q0H5+>h&(JRNx0O_n*<+zl#ue+KTYRV0msZFz9c6Kk{~hzWRqDlV(J0=xwznX_!lFjVMl=QE0Z4=0>2 zhKne*)k6a&fdMkb@z`L_=Nu6rVFYkg5^2D3X_dgfF4oVcfOf{r7Z^m+h8u>V#hZ1{ zc$jMCr|OlsUZ8P%SN5!;)dU&42+zZ|TwMf*g)u^X1RLJ{ek zue_ftd;5{BKS$oQ%Tx#IC5%8EI?#{dsT&oox3k*F!JqJe9$+RA%tpn~6;Bf#bF(Ju zuen8+tgLHOU42hCaO#%N3!=-#?!^J=HOyGC6nuX{bGzDJ{+Wt)MJ$nH)r4=s!(EL8 z{FgBXFpy&5$Mx5r5l6}{8p(RsQ| zIV^#3Ok4a-zz9o&rZiVA#@|%1DHN#IO*9KbZsR3TtDctAjgAlaWUJ2D9UYxX>1ULc zX{SdAqpez46sJe6Y9pvD{fO#7z%qF{Zm(mV6Sx32V(0Jknh0Up)7X7IsqUag}X)B0>7tR#0edg@F|6|S#{udY`G_S@1 zHK%7M_&gr`*w@DQJu%9c1d>u47N8dgRcQ5R)YPi**ugUiq#Le?;N0M7$T|Q3jrXTR z!HfuAX(Z6HQhIe=DMk7==5LD>8Q1k6PO!sKL?lRMUiv%zZPWfGY zxbEP~&)I!bCmIC5oOz6fIj(<@_4sx)uxFQJqGJFeP2LPs6u!DaRzP4Nj-SVD3B$TV zk~tr8r%eVuMWwiNZqRSdN;m%ic{l*l5`xIiKr?Kl-|)P4o2hNaAn0+&-EdfRpUb5} z*(9zYk-^rJ!6&Dbjk*lXYe@r8j;pF3E}tyq3Gq%7Rd-*~1mg7_4&)~(WVsl1AqYV~ zds@TCV_g%H-;U9Svlj%h4blz=8YnU~6luC0>!Of=RXrBV&h4QAHyg^W9AoDK+WE_i zmZZ-yjBdAA(qSRg&Qam-!G<4ZbxMs+4#UMo35E1HPrM;5LWY!qsY2YI2gHr9V+~uc zooO2aXs|$EY|jvI2c$h5VnD)u?C~{!yvrhLGu-6<#X+7$oQ9iu?@)7BCPn0If?IiA z5{2-YHUdB+xtt^t=tMLLPz-FxukE})rvAJnTiufiE}UDjc~hWknq=f2h!b?mR@bcb zAE_>xK2PH{Xtb_)aV)^iL$3(0+n6a@Qc0Yo0rwbL*ai zXSojPd3(ow`xQ-T%u>HdOAKi;f{h+%4x3I_f$&Vtxnig%3G>L?XMEYFFh8DM^qDXu z5=?wpM=!m>zU{wB*zTTFV_y-N9cYwv?&z;(klEa05!X6|m}wPG#IlCSRsS0o&jeY^ z@m*QON$3;eAOIR<3qH0n_P(rf~HbbzSlm)0_mtjp6-HBy@(&2TU22ifllsJ8TjqA z9U)u@wHdde0a%RK_MypS+YY_c)>6XA2f}BY_T#J?8@Yru}Nlq~x9%_H_g*~|pWzHrQ zTCp%G&nLH^;d;Nyf>wxZdOEx)iSMJu5YQ2Bf8|nyK*(Y{34H`w^&snMIqrPQ1UQ=q z`Q_-CR$P|24SZj?Xu`_-?k!)}>cTVrV%)sdb+NJCH%sW@(sDQnvKkqN##I-YEP&{Ms0VYH6g&T2rhC5K_av#?4GUZBRQXV1s`XcBj%yMch7H+B=(apNDvDU%XN;{?++>6p zazb@>)$@veNX4X5{)g5$cpb!E$i55T%Iw%g3-?+_@5(mIc%w%aXd0|=-wt`;DNph1 z@7ehjx>$~nZf@Vl$t=VAw@X6{Yu!0y=@e&p|D*hOwhNRy%WyQ$b`Ik*g)7^7(aFJe!wB3-7~21P=Q@UfzdG3S-$353HGTWv=n8 zud>UyrzVdx3uPOUf?gpP?n2z=L%vu#w90?bYP*t($UIZnF&sad$VDzx`$}g!-O)Ed zScsVoivt8;#rSdOF95Q`KsEV$Ez;$|!ClxmFjAiy*Wc((D!}hDGVp@zhktsG;Xi`m zWn(OT?!P;6^50aZnKwUJT74%kQDR_cxwY^;!IY(+?YGn-FVUVY^n!S10z!gFKRibU z<+)J$py=xV!b4D`Rqeudl!Ymcl?_M&JPTp*PB0BSGchen;{Bkc-5Dte9{v-J?9`A3 zUMRo=veh~GWrHM?sp{nx?#Sy9{S^0WI=z*6mbec zhkr#~`d=XxQLv94;GZByq+c}pY_n#u^a9N~&KG0BKW;4Jz3~9OnrUUg<1A_Gwac@A zsHmpe$)ykSx|Ir&jgXbEAP0XClo&n$U%ZN2&S3$WQP&ADm-eGg+7*}~wHWzW@TAaO z+Az($H`!5&cX5br_k$RPxehIWDP3%W@tNB2wDPxN77!lIpaIJ9yJ+nUUnWGg;JYpK zrEx(yscJDI=m0QR*xqE1fkDC|7tBigZGX%s(l`5_(sR#b7p>Fp9o#Az!Ux z1VAVAhE}`?862_5Kz3SMIpA2B$3GwPW}AHp~Ax7O&MjiOs#ahZ;D#_IY1Z(vO!-NR2#fOC_nfp>i)9s#O=>E1ULA-9H<} zrs4N+cg_-aMqz`W5=I{` zZ_r4}H_8g$xNZ1TvhX`e=l;rI&`oW<`ZxjU`bspnvXC>fShk`;5vaY8DG{-9!Og|2 z=C`5}AkhYsg3I#(npmzp2miPV_xPTZsoI>jv&)Sx>tt4Ao+t_n?t2|pRI7E*#}DW{ zY%ZdJoaUdlWnccp3_?C9@)RyLT4Q$iO9wL6$&caQ>FZ(3=)Z{B2iXr~9h5iaLSrM; zGcrbhf~umJ0D_Cc=f6t zRN;R3Yd}{OXOx&+zo3|FL-f+m;&uY!s-Yo~jpU40him#d4pWQf`I;Y` z$j>EtXNZ*IA$JFdkoB4Q4Xn>pHw{9O)bsDh#9LIuAK)h2IQ5RRq3~}~-5T$?{}V-? zbHUgE1p^CMN0KUyu%@nrgS>;~bF^J2)m~lK#gWTeXr>5v%hH2ktW&eiR#Ekj@I}O< zdr|E8rydmoX=~NI+LPZIBA7th{IF=09L|hrkbm@+ll{CP(W^}b+91e|#R6Z7(Qyvf z0)oW{(lB!;T!~ZTe$0+aLeAXi{`X>c6@j|}So)cvcc3y$Bnn-uk2vI*+l5&Y&CtgbXxCtN+>rmwIzdXSh}T#9oYp^e%+6eaEYE(NmA zk(JJpE@vhC%ewj=t+RYZpx6m^HZmtzuEjwL$?~r~CED~lA>`jvHT0K(-9CNkIiBx- z+~!eYIb8R28g)U1Hsr219<;P<@~5^iWs863r=1rsU0ebjqQG79OxD1FCADh+%lyW7<`w;>I_=^m;+10~q?f(90-u0q6yB=iDC0)4*#(=P? znHYSzGe%(h+wzb{YG8m2_8uINH@S0JRfl%s6->}#xGM0R8|ilIXiQIiWP06%*`_Hi z1_jI(r|TgX;&DUr+j8#r9c;00GGKAgs@ppRB~RJ8rTrLK_8f;rP`?;p z+w}aO$h}OACWCG*VQfQc9Kf4Z&&`a_@c%gEt+E6N7tcu9GUXa?3u=OO# z8@Rb`G?YrDh-z{yNKJaou`N_-KBq@Qds?lks-XxdH~a8a<+sej0#J+Sbh8PWd0Qs=sNm2*DdA=AJbx8>4_B zxD7<2Rl}GV)fcz6_(0xT5H964x4Dq75>@jC`IeA=<)YlkaNIMFvWhNj7hXy)-7OeD%R+%-I|ESSI;u z$P95QX166IzaZkx4I{8ze-hVQXT1T73#T7{K^<*;Yg$>C@yVm>x93y1_iS!-u5ChN zQ(s@w%NyV8CC40sfa?Q1kRB9$+;TG!^Iw~jDd{1gZ|WL>Nv=tfan}dZWzbKywdY4u zD}`e4+{FGdT>yMZ6d)5043fy@ujQI;YSc<^R6fk%Cd$-;Rb0;c=KoHOSNUC`aD(;a z{^?e{P4H~1DWnE55h)}QQt}}M<1~yqR*=K!&V1^`0`U#PC+2{s9@Pqj-g<;zK9sh1Og6uSkhYmLSV6W#V>jwMgl9D*z!t1s%o@nuCIsSrk{8btpZ0U6 zsyo3MWTH0F(JI+{dk+)(d4w`(Et=!#&7}OGgp0(tqLl{(3T=Trk{^E}L01Uje}6lk z8zW?uHq$Gtf=pT$F-od6zZB~QwOMoeI1KnWyO>(ASY50z4_NnIM5^yv&Hi|C*jDj| zvK}_sI59vM|9LIl+*qU`PiUH%B2S)2lR$$;EQo8P?mR%~@0H4by~F42c=^Nn@&M92 z*^x%=FEnjwC}wbpQp>?*#2VDg&L!;z6n8?~5Ms8)6@T40P-iTSYVP>HTz0Y2=ldr& zuWSAlXhkiI7va?durYdFpHrVH?Bniu%1{#7BOCzi#c&VW%#8COP} zF9(&4ell=q*LQd{(9kV#D&1S1`Nx~={&%r9E+mSjD6#&cvHy^ zg=TEq)2cg&&^7w2ku|SoE!k^}#CtWR-MTH{h^O9!>p4~MUE{ak8I34Y2&(W12~>7y za2JiZMWY62!vlULVj%XtW}mbTBNtfq3^M1galN3V4$Vkp3^fF@n$2O}TNK4TJ z)03bU*tH$`&uSqdiA!sc(=+1m1zKFc`J4p*QX+bfv!3&qPPmha2Jq6rGC>VMCH!kkn27WK<<3*3T#g5v}tm;%2Vmbr^fN zH4LKd4cv*Y8qi4+?Q`%nR4{%a&zI&VSs_{Oo~K}CB}H~N`5mwvR-k8ZVnYLQ`- z>RkUS!|KanPb^C-dT3E^c@4p9cV=-6Mz9ifphhCa;)wK057lN*bm-E>mOeW%g5#Od z7FRo8r;@cKJ;f&G%j6*w*4b@7W~K9WH_g`$w*MBKjwSKz-gM9@)Ui`P!2+uu(UauL ziDX~)AET`Ipr^jBg2{@nS>%UP!ABs#_Ej3`RBr~~3DS@%FH?=Qoi0Cu9nickn?3bmf07Cv=%Qsj0>jntW<6WCf& zF}qi_hR;Qj+x4Z9`WigZTd)vugHu%_j!XVQZ`gN9m7Mtc-d2@8N(-@gexorS+HeH|J;UJ9^m zZyGs3QHxp(xpNg_X1=W)fs79-v%S9*3tJM5N%S&8GZGjC8kO|o@jd^{I1xv7dFbZp z15{T-kKhNOmRXAxxR+_B=hah~jC z2iY~-1eSMBxgUImIdf{EBirBYh4Sm`yeBf*;+NxU=JwLBO{gQnP0oHaD3Bn42Pip1 zBAfJDBSj`^&-yBYb4zUaJ^2Kw^?9T zb{M^T!VxjM2shwvmm3zF3v174s}hE$Okt0r%K(-%tGO-Qb*OB|3aWRSfQ;(bU01~hj$;U+nvsmfVg;UL9D&fzW()#e zm{N$xqS#2p>G_ZZ_&t?266$-IxtFW%s$hh%xMTG%TSxITmXqEv;*Q z3;zb!7(V!*>c{6Bn2rdcOq!^Q+%4 zh5J6>T!mw$xAqg`l=c!P88ou{rYTIWQBX~BB=xdXZH7JY82(rcpJy{NoNyCI(0gaZ z<6xKn<{8aT#jDhF@lHSgd@Vew{tD*+Z*QC009^s9Db z?@gaOas2kJqinboQU-L-d1(D?E%!Ozt~ogZxIKE5qpLTY7z782nY`hsXz~+pKUmm8 zfiA_u23);eq0>=~-Yp57jlgZlT+M`doGDHvs)@$(kz(xnM+6v1(@d(`MlRg^?(eK= z;TE~^yxYGc{XYe}LvQX-d0B0K{g@}P^m$3VxV7G}xR+@5AQKH&3luf5Z? zaaCd1p-A~yu}D}n9iUiX6T^A@}md$zh1HDfh0D z8^rvG7Xm>q1D}la_ z@Y^mGq<)Otj%1dtn^NE#EC#NE6a0B&m0fP?WTaGXbVuZ*6W-R1)*27?mG_3!`v4VF zTvcnwuf)3~WI2TPRpyMtsiu&TbUDcQhMN8{ZVF#L*0#=X+9UmrJmd&T@e~-+swd>T ze&52pL^3uw_U99Xxgxd1i9v%fdPkb6hKBTWtMOtKRu8wXdWx?gk1gE*Nn0AwI`XnV2Vzy%6g>P-x<&3sbcUSKX7}51P|!=3R-v6ec7;n9`8nJx~vO1!h9xqy7m_G+8G5L ze|4_1RXV&EAA!Uy3=G|H<|+BtvFH#k$`T1PRD8QfF{RsBw$SG{%2_F!x!~aC(tbl? zsV~8Pc)FuGlbatyF_}sAX8?;Z*G~J%3w4_=V#^ftP#1~FlEkwAHdVA&%+By7lOqd1 zI}t8}m>DKWk)4)K->yyNeb~j`pMl8pJD6i}0%TI*N0w7QH}~_P4i8NZ=@f?3Y;PEp z9osqHdQ7)SW+<3~-neUvHT^tvke=!7oZ3tpw907SwX}zM$DkGh)-l zk@B&&zjN@m#-d6ztrGRxW{T%ASQxn-wk;|*Q4Dm3!(zF$@&!qzEg)^ zZ;OB6DIJE@5HR*+L)9oG9Op(Jij)qp%B+c|rlPQXmH}yr)~_^v<5-MZe{{evIQzCK zcsRY8!TI^JNdswRjgnW@p?Zxt8Jb`Nd1L|#b^V6)u$LZB5K-s1AJ~3XrZ@`MMP=gQ z!oR$7rfr1atVOTU1^tbx-#=07iG!fVxS2zfo4BDF9)|pdH&u$)%!FcD8pGJbS%h3d zSRWOG%05g5O%tkD^+Y$~+cxomt8{7%Gw6;1>d;j4dj$lxhSlR%wq2SA%dK9$^rEv@ za{InY#nxyZF`B(SE(1Rpo~Bo|E0z zYb0}1sB2TLDxYC~D24klh)zqEv>%k15!Uj8cfYAS<&H*}+i@nCMh)(ZHoLz@IxNyL zGsN3Pnyo|x6hQT_32iR}16^@TbK7u=bcY%FxdL~`4G%>BrXu`7K~mTz#ye#St1glT zCE@5q@9*#V;b#^pbcwWD{=qw({*eT1$XYVb+|<~d7_pB!2jkFsrr)sAZer!h4IsKR z%%lZ{R{26f3pQ+>o}D=T9w)bM(hUdJzm8`|{|w<?lc!C-2_?ewQ^u@Vj&76CwyGW3C2hO>9;v zi5ZC%5Aox*Kv&E49)%MLM_HfSoc$OnhG_5pW?3RmltM)Xgpt4x)oep2X15CgTt&ei zCPV`Kcrd8Zy;Ws&?m4VG$6wJ;nERG%jc(Nj-;%=744Z9TZGf#3HpW=PX*E?QTb(3- zWF<#&x~L(OSc-m?Cr_nKr7umt%9!0kxs!P?X;ZhK*cT1k{z7Yp9@z+Rrd_{4NJyW) zAL8iU54Zwp4^q-=qvdkjbAs0y^9gcoToK~bv`V3RZghCn^(cA+eDP50lcj1Hc3nBV zj~^3Cwn(k@*U#3LG@nrAM2GL~Z}p=78i2W*l7mxcf6|0AZy=wp!CL8O$kcfaSaXeN zQnmB{CH3AkYk-rb>0-)VZzlxT%-Z(K9>H+jBJh@D%yRf-QLUQClGJMm()>}T4j~10 z@YkO_@f*DWUi)5Fz)WvQR?DnE7^n5qOueZQ7*T{btbB>^j_zKzubqW623TB|h;x&w z;jW@zS24B+1T;gBjubSPB?Ap4ChXvhtIl^3A~o_-hoThqQj;USzYUXZ*mOH*c6aT`*0>!i&%A{#1WbP8MKw6=yKMKnlm*b#&Cr1Zmc^mufN=Ae-_0Q>_EDXx2mor8wo8{^+*4##{nY_ ziC2Emno3Ke7re16CEc53rKn8W&RB{x#vG)Q$h%EgkOOV%%UehXH|2jdLVsl6ac%Baba)ETH;0!nLVkr|q1`~oPavU?d0nkueoZUisY&ExHxkJAcR(CPqJPDaT8Kr{(MmK z%|p+3B&_{#)OtTow=UwWw%>Mcg5&Z>Ia1mws~JJ{jLI1Oe&|kX;3TFyX)%#c3OEZF zboJA>9rr<>bCdcjGXC1g`u17i%HKW)lW_|3g)96pF3F@MIVRN$7KIwcqc%<3HlO!U zwI;_Jgs#56_EdM9aHj)0Z(k)mTm))kU1FW>l+pN+w(!RW1@&t&$yxGItSgjdnI2ka zquuJeD{_D9a$-%|SbNQmPhbRl|5)IZBBe~<9kLb!PxDb0I1Q2Ct&q=ExZ-Hfws(wZ zRGG3|jRXtua2MqUB%TzOU)P^dLaje?%eANWK9xmqDim~mp4!4Kt6!ok9`7x=y!$ELZJ`p6hiSHNu(Pg(+7{Tj4}gZk+{K?PNYfTpnncrod2FZuZPy z^+q`LZ-Ix86NzK+noO9SaoKUlQXnpU<91+xCs5xFrNL-k@u)~x&!LDj*8g^B2cH@v z)mK)QPlMJThkMm{XC5UQhN3l(B)`Likkn51e3`#afOC=WVN(F!Z-8U_iX3}t#Jw<_ zqiIZzty!FEpe61--C*j=`mFRtt*=AsLusH@8E~%L#;8#szj?qmFoc;VF}>{OU`7XX z-4Hh~?IX7-^(3z|B{kchl}=TC!o()z9gvkCz@x#G*k#_wqylqot#uXXx2#U--hBvsn0&&W&5JO zUO(*cPj@BY#51A^Za$vlKyCuA3RpTO6C6+44OQR)r6u(zB=yDETJ4NZ{||~lb-$*Y z;h+4QrU@#OU5m+1m4&`^gE{tZLhn+p0iNuK?;h zZ{d{`7G{uy&$*=K^5f+Kw32szC2#BfybWTKE?>kG<{^zYQg|dD5hY^z&bbIq&X7uM z(h8AZmmm%mxgsObowzRC7N>4tYbzpaLEJlVVVi{)#E*~9_wIf=fl3uV@z!Fl@I@zf5d>o2Co!Zdu zq%{02`5`b&?+4&;>saD((o5F6t?n4El#j&iH*b#L_~1KZ!)ngaV=dKkJy(lQPR#b~ z{IabMxw+_3=WK&#uR?Q#=Kxx-AUgx^%eqHS(SHf@q)Yi}1-LwKpb)F_-RxgeohqCm zezN9I<25Us6Oc8rQP2w3()mpJW&LWIthreamIiXmigQ10a0WvWZX1-3xSo}cL!70> zNu>F<7_7-76AxgKOb}@Y+8)0J2U9?SCBD?$zu9H4RFOshjzNU5L7Am%EZdjr0pv2C zg_-@&E}${c@gU;Hr}oUmpZ~XC#la)+QCQKow6X>eeUtx=*~ud z^T}gwn$y>>!WAd77E%e$2A$$S^x@7#TyfDzeDbcV;>u0Ku?(*mBkd8ULHJ9&-?X6P z4Y#Leuq4A7(v$Mh8~XPgDF#FuiIso3U??2)TKcQy5{&7k4LHh>9i8aM<4?a7U-;4w z;`={%0%buLq3o6zS#crhux>@rIxSOz?{i&z=rgMip-qd|8dEE<&UQ&o5@q7`m1QdT zW{PG|xNE=}3S#QaY=E$+6wt~$U6?p>PD4S8#_hy{v!w`Hi(-I!va=zXO)Lf!Kx-M$ zpE-sl_lwc#??x$bm~#ZKjJrN`W4!0)t8s1OmT&6I#NuuOXV4by*3w(XBDH&L3krM~ zCg190A$;As7)K~~A6oyX8Te1rDlE8R2HGeR+6Zt{&`FkQ)m-7O{@Ggyxrr39ajU!{P;kcvyD z0h>tRq^9_GCWWvFV4G`c>sExk7g85@2yl{YZUaX87^|oU$|V?#+%62fTxK@e6QmEw zt_KwJEQ#Fv(qugN%R}+SFF(i`1kcCr!wApWwbB_`20T>`KzPZqX#W*ZBYXyC?cCNN zez^n16t;r$=r=JgD@_AXbMPt~Lj2hdjs|d!I?5O|akXWM3e>GlvQc%1a&K90VTn(* z{`A4mxKO6 z;I2Xdq2S9`GVKR}<15zm6XYP(%-_a_+aOu!-j)QW+OBHDZtUroS&$FHHwZUA34 zfw|M6+jMoAphX2A5J#V>_>jXjALxcI2vjV3Hi>=EpuWw@s>#XGodxn=;-#O=4W*t{ zj71x=e*CaJo>ls#QXtRb0GC({=$5L}S1z!m`$K00WATn_mc>8(*oN4=O7ZZ3NtRx;Axq)> zf`Efq(njB*CXCMRw#lTE_`CB{Vum1KZ%qmJ+=gCxpNrN4yTwqP% z4CEESA@Lhxu;fYz&@6>T4}m4cz`}KrGzAk3XK+Xkf-QI&b@@##JaR7P50+e^(Ty$` z~KBK8ohWjK+2%e8oS85GZ<`PC=~N;P6N@x zfFnznV=w4A6JrcY`(C@Ze~y9)2l4dgq4tN1wQnLy$Q?LSD_jOX0(-ROGe3 zrig*%*zX1wPqrn44YJ-ck+TXp-?DZ{UNKh}d@4^!7MYE_A~AlFch`}$QSB5l#|z@| z6~k$vdFrpImf|Qwu3K%80>z{g%u*?!DG7K(OwrrC4X%Yr9L&`pcFX%9FoxE~-)_Y#n>V76lSH&1q2Lil3JP68zPpvFB-U zK2nweo@d*I4Rjf0cXwtC`n!zX0_@gCp77Z7Gx1-(@_c;vXUF2m1RgWsnKT?#ej?A> z!x(od6bPi}1o%iLrp=DD85wMEZ>+-Y@m+Upj^Ft^Z;frsd${eyJf#OOfcx+!?%*0j z!f-BDora!>mvfVyL%^RC#X#`^2hadS*#ZRwcV1Ye#SLg=vEZD`2UxgBNMHIB@FzX)tnkb`Xna| z9*2>?lBlE>wbHOkV6wCP{&-$aJmoNCqWzW#EyfL{ZwsNyh|C+3g=Mz0RPKJ+;#E47;JwO>Ck3(fcNtr~c6UHar4PhvkOWNOFG)?r zC#CmP-009o%Xbd>#aDi-g^QNvcG7O4uK2K4DS%t3fHV7Rls{AHl@=mFE@|l08 zt3xuz6|RVr`pQ%hGc;T+Y{e7dK%8VEah5;!i@9ZveCT0dzH6ym@Eywk>AwcF=WxyLp#tSw>(1xMb%&!g+TKH+6q3hOCWl>4_eDJu7fOGTmcpXRG@sw znNIk8p5LAL(eW}fzbcQsy@vc|>%_Nn^UG3RYkt*td3&vSSOLC$ zt#xw#RwDpS$vK``#+o>zyAbhAmT{ENL&K}%7;e>f>=}za9CSaE3R}i2O79f5*yoj* zn#%z@P`oJvxGW6J_0>X-QRuK`FC9MoYS3DGf3_j8q!>8c5IvrsBwce3se}4_x6HRx z3MieF>cGdkd#MNCGXvkFJDnzUsgstP$MbnpJ;|_~6f!1xox-umxzr(}rLA0rMi=Ek z18ezI3{*Tx%7J;VIWMONsc_3VJ?SeExXt8Go%MNm7n8K2Wv&t&t|7f_sq+z6x!HIH zeXbjTCTUFmrVJ#i7pvPlraY5Q7{J7^D+I3OI9ZIKcpn-gBrI%leaf&qB z)jFz5Wy&g8%G^-H^UT_uLxoQ@d@WX*=IdCI`?M`}UF&)!^_W}moM&rU*Q0)Rr)}Y< z^~TG-6V{cEIDSZ&$X~An=30MghS`6-&w3^N+^t{HxlF6q1Qi1XVs*K5^Dv(iLtQ6g zS^u9{;+&M(FLQps(qjVfiw7dUa?jrQ;y0g( zBb;lf%&N#%T$7hEcLD;PUtm~}+NRMtF!h|+BB#ROb>@ZGwDw^9=KC+>(0Giv8I3U;^$@R#wnRxd3Bk}F;KN9!c`>S|%2Y$n+mZ8DHElg)MN(6}o`7+4uJP-D4 z;>);=%a?8!OCgz8-nAiO`m)anhyhfDvX<}H5Eg|G`JAMKCxe|UQQ^wY*CM+ELmkrxsM5aJzNyI>0vE@7Zo4XOeEYVz zV9h83SP2=Wlder!Zb2*pW=o(xR)k5w$R26>FdVXJMLEDbJ}ui_(G((>Z8Y}t-Cok7 z80cZOJ@FiQ>N{Pbto3!mwY<{W6jEA-QChp(xZ^mUEwzMK3QqJVheG5}jxE0}CPS5N z{Zkk#thH_meG|CexKc2k{@Str$7g%Lu@bA);yNgBA=JQaP(RkvZVqgQ;m~4UOY$PP zs-`pYPnT3MZ{msq%N7cR8QeCtI&M|x?135Z2z=akU?v`VbZ>m~o=4)o`yY$vb{%8q zz-A`@)nM)l?$m)P+g%qfFgzeyASNuRuWiT)NaA7r`BQMvmuEZJKE{RTa-c+V{Pk6U zv=Nfw+dU7#PQ?KAz+$5b2jf{6EzSkluzn0&yeRH^?{#t84O?ULdMrxVY0}XJknmzG zG@8p0z&oL$pHF229hWYBAfQ#-T)H>#i`Y~N5QixLF!*$s-3aU=0QY+X6b76}&}>gI zR%LQzpFlO?BuMH@robz4%1GW6xqxfBzGT;a-`(4Ioe>p>E9dNqXP^*{A@tMu~Iwoqk-q*jDb|r(z?R9 zL2IPJwo}}*<8Z$fy>YfN!=QC>g9g>?fv=^LPSMPzsKpC`#6QQd^Oy50J9Qi#&M#0% z$BFviW@iPv*jW6bP(=sC@T?}7T-cPk7UalwCY5%OJGz_`iFcgMC*-$Fih=onYAMYE zK*0HG>5PE|0Bn^dx_sydJazIPDAQrGd6RfolkN4BPw61-X zY*==}g~#M4t9r->=J4dVP$(&LXl6R;o4dAGFKfkGT*eM5M=%}n(l9^p8#&Mth)i($ zNBK$>J&&6dLp4iFLAe)&I0ubQ_ha8N4p+t?(v1-sV|RE?cgVBlpIE@@ip6Fz-S>`? z_j=C9>mcB7$9~v02<%rRM~N83bKTFNNa}P==wm36%J{<+1pkk6j;kzI9Dp zFv=;U$jJ2Q5}Y?szzN1NUTaS&i+R2~2Z{lZ)Wc&z)>?p_mKM?=ak1bd7)eA5xe=;L z=s@yGn6+u72dz#gcJCYKP}t|=Yu|i;T?8-0j$PdtS#>#7VO<=ZoWVs2gB(O}G!Z=D zuE#@VI~|;i2)b^%Og?d?^yd;&!uO4N&!y*OFNdTQh4WKca_&j7Nx5(lzKF=T6k6`vGETmBs z^be8MQ3SIvEiA5tfpe$g-fXk8oghLRrYVi;)vw?86i2|U}+C-H%fG1dGgAeNO`gs59c^*Z&V?kgKP8Gqt z3~GT>f;1bEY(}Yp?|}OtedQNTp_6G`%x5dHpI+YHVEu+ssA2IM?x# zRlE@wn_3B1{cURo`P;NE8nqN>g7O%5EaCIHe}w)7|GFasHv;l3y$y#Q;<+ z35VQUJ-(a^N?(ezsVLC38RrdnxHt)6qQR>r=4Ad|zi3j@$Iyt}mJFS6BuhQBk72@d zKog_5Aa@3U`Pf0x<147p&8s&$zg&XaF1new2Od$-g(6t56IK#lfT9xbLSg#KVv8$aBP!Te019 zz{=-u+K?zf7b9QNzK(8Zoy%Dix}w3FLl!UbWe7Jlx7~1Y-2B$9v3v;QDR|x{Yq6FF za_$CY9`CRtTVYB1wl?Dovkzpx*ns*P6$3d?Sb^y}l{J^^o8p#OcmV^i95>Q3*WipN z0a-U+kkro=l+O58<&o=WRwGAy^SnjWoK91^`2IIR>i>Tb}UB-mWm73 zw6DJsr>ixJ0oH@ks4?oM(dXZAw&ZR+MNG5CWIsCaD0HRJ8)=O+heo;PN`A0@PYQ6$ z_6cW=Dtj~2an;4EB`q@5=Y`n6`S#VnOR=1Do% zG)9O|?l>5K_3ek^&?H6z>>%%=v>q9T|7A;gF+}z2`2^B2-j;WIarwp-ao26v#%5ei zt87w`J3t|>vdP?BHVPhL%BqmM$b;wVl()(x`Y|yD^%`1%0;U-U$D7c!19ATYkHr}E ztnsmijN(W@u+)VLRbyy{rDUnLi}uV+V|WOEKg3y%qj(6|ym4LJa?_=8 z>E;m(88PXUAL!w>7};D0Ja6i{Nf>3vLx)t7q zgXCF{j*~vfaAK=127T@YE=v{G7Bx91D|X#gr@2bNUQ`G;>SQ& zV>-d%4twzXe$V%xL@@h6Jou}FoEW_tVepFR&=-@M2esFv6}JZ&cTgw{0>1??d-~rW zK&^e~51V5z@teLp_@flK2fcU=>2d&?$>8qsq2VX1z$xh~0j9j#@Kj7=T}4Oi*}+r&!0jWu?=eIfMiLcZNfn>jxK z_dohl%)_IJkyQ|?WrM4YAZLZCl1Hw zzxYsm_q$KVt^=qJM(|$?!`rgInS`da!UxaXF;c8zOSa-oAvDzOED?lLDh8}|m&w!S z=z5BJbTL`z64!=NT{#5qPw$WEu@^aPsu>@A-%XrvaedtQ&P}mWiv*Bhh;ci_Zi*Dz zGVv(L4&5bjMurT8a8U`C@KPZl&XZnsmAfGd4)U5enONovMP0CapwZezif2&VJ)7qb z4EpRYK!E5jtTvezlmq_$qaW;&lf!JB@9OsyrWcvJZ3~UbI?PszB(E3>jI7(DQw&s$efC3E5HQfh0#*gd-~|60EE*lHCO-+}uh{aX zmx}}f^rJYdB0T9t4iM@FgPLxnqzS$k&vQZSSm2!tJwlna3hvjRCeGv-D5EYD&ht-> zttG|4JfXFe>}*3|NilG?Avz~N$U%RcKhTCAMhh_vk22JZF^q5aA8W_g?|nA@+gE=X zFCE1|2*GYY7s1T3&e=&+=H&J3@CcmbpR@T@do`Nsvoltn&9&>q_~E$x@{6#5yE5K; z-Le>E$E!2IKJO zL+lXX&_>MU?|F&!=N+OLSUt2eKJ=bW{Qf7d!&YVKNkPy z-+nco=1j>3yYc(Yl{p5BQqwlbOKMD_D8AG!Tuh~9v9WonCG`}{xKGnB?4(m_{P%9-4cp5-B`17X@#{cu@KZ-}6 zAA?@tJ_-SJn;jT>Kd2==vqiqbgSgXb9^)*Cm*VDYE{H$+-8Y<&xKs>itf=Dh{8kJklaEhNjH6DNZ z`Cr7Z9%J`PdmB8_dW=|sMb2IG!*g6^%(1a#Nt$NvLfG<|4&$#X@V?+kI ztTP#tho6p*+_^S>`(xYU>TRu94PPa`S@-%37{{N#%Q&j=xf(+Gg7oG7hJyHn!p?zW zK%teBq5x4KTbM|RJ@A^P%jKce)o8a}H5l9jn9~_Fe?2>iEgD^R0~|ck!`J(v_{vuv zjC=p~k=V6=9N{(EW&F!e4_1Nn>#!bQ&Ta#lUYTDtxsb&?_!q%#3O1|G&LZnxswd~; zzq7-rtHe@E$3mKND3Yg4v6tFO%25G9AGb-XwSF6m{OJj_mNaJl%8|J7Z5PJ-?zkdu zzh!%D+Sp<1t_%kZI6gYv?xc^Zf>Kn9d@NgpO3U(O94xog%?U|5Eu6KZhUv9n|F*b)F!N3IdrK%J$RzN7k<;@O@U#Z%^}_ z)vMl{#4AJH1=L8Z1`h`AVO7xWLC9Nc!42KCY^1K+spn=s(Pz7s>{wygS7bC>cL-pC zY~8;k2OjCKFz>Uama_d4GjfI7r2$T;Dth`@4+;0tn3~4I;f2Y#??*4jz2AF0e(~rN zap)L6-C%HrMmB&ID`9v>xHIV_5iWhD%PTh;%0A2=L*>wryS(%TWrXfdGeI%Q|X#;a1lS^g~0X z3#6|Ovyc;BDp6>k42ZDzUE*^p0x6qL(Pfh^hFYzIMC>BfPU^?`12ec5>aoaYLDqo5 zYU!I3E=Q#xA7);4nR&M@d`*G=Jt4sN@RC2XFMKevj_|n-r^q|Muisbq`cr=Th5gsl zjTwDB=&z)>H7Gkc^tz2ZtJVfm;OZ=u0=Ss!;ra~sOIZc`-$@2m&OQ=OGAlADDh71b zlp*Udr_d66n!n;?$!YN@2CQnKLAetmJ0+u%w&fx3iCeVMi6G^}Wf66}pH9=X%@q8L$2o4r_u~uWq|dn^cJW2O=i&lnpB<9MRn6mZ_Bo@Bm|rNgLApiR2zXqS zbrEE=P|mm5+V7k^8b{)Tx2}&r{>=K=JcF-bB;TGN)zpvouUkm^TGP#B zD$4ZgPCdw->koNS=VRS6-Ec)ae&?eX#oMnKK{>#Vf*50mGgG#_A4U&FsmqPHe)47t z#N=NpzU6#`FW~8ePsmMi4~qLKc2`gHZ-8L((0Dt3^2_n~@;9G~Up%%S%jThIkFI1l zJ9A10V~?Dm>Iv(7Z2TG2+4)*!ySplw=^0#H3b;MH4dW{Wx2}1YH+RO3C+|a` z8jW=$tRz^AcUV|>W?YXoKpW(nJ!{G;q%eScg3@`|$i))QTrrR}w+%V;STQ&bvyJtd zQi+7S252j57+nsf^1w88+x_-b&#wlSQ+;Q)^4P3BnkoiZ6T5rUb#<$!VqkYF2L9mh zULV`n=t@Y(%%-P)3lvAeltr_>)Ia4E*VR@$^o1Ubi>0Bq&N<#oC3RbJeAQ zE*nCvJmW+8KuSAUKSHmpG;3TvCJbXW{_eLekAMD|OJd7>9{_9$qcK*n_c6G!6z{M-W^_=?(qbz#b%avemSwP2^-^9d?* zhTBJDq`xa}xpqzb(LZ=cT(SYn_!dfAwB0>+E};_1HhH#(bxT@sd{--WJ(GjIJIHw4^#u<04#wKy z7vjCQtcy>6__DZiLnoHg54mfJG)bADOYRnEC0(iTIq7^=!3CtTCpYPIzt4$c;CN-` z_LQ*<&;))y)_=Gw2uA1zKy%9vzNi(r>%U1CkDenigTIgiho|D+?>`)0`T9@d2S0rh zA9br?+7J}u&)cnBx*%fX6rH1TfU^2*Ps9C;cMs;^)E(ka46_qO5+&a5kbL^I## zB%h)|1|oGth^m%)NY^aXv)5&+K$$U^+=Z{j>A3caE%D*IZjATbaw&%kufc7Q->5iH zgN^$mm;;$oiJL?&gGi*1q6(!Jb$!a+Ny&fKv1oBCq_dVpAHPIUt|SIBb+``-e0rmS z?)7$3_KRr1c7n{DeSkH0Q)0@b+G;y-mwYVaW#M@BUiNCf5rsgJy2{Ju=OcF+$1djI z(+J^v`fSJgOW|v0_(IyUi3?$@2e@L9JgJ*e1T0CKe?Pl0s)u)+!QoTAQV>EGznMp#M4LPTlfAfzW293kDot;6+B9c zk(C#-2?S;UeCsNh68JJSwUEp{PXSrgaEf}Z;k1eYlw!RumiV>-ZSu?{2P$J>x4bhE zmuwk{554dD`0xj>i>t4`fSoId`@#8+=408_;*?AmI3N-TFDD*vb1Is{#NR{~;j|+p zGstwNHKtg7Fm`3Yn3VIJi$OVmpy3$=eNM*d?~Cr_ZUlJyDF^pOL$ER6p}0M_%;Uvd z(y8B6RXCpXbWd6DtmJHpm*rTRlW_5|2ZuESUiN!3cN})ztab>%Ts1iyebD#33D36h z?)V;NQjm5K_~RmgT)4zj$E?W4mDbi(>3ORQ=JhKE-~fzFy;u|jNhh;y)Jr^vW-Cod zUbv!j?y5={7@4HY-ZXB$?S4g|EWJDj5Kw98t^pUkIVVZ)(&D1vdn$>TN6WI)Ij*W? z5)%8JtB&(kB1{!Ao2L5a6>f=tOFIT$0YXc!77_wWih%`$E+nGQAp_HsQ_;cT<}l3j zF_eBkduA;D{J%XGzj$OOy3K8Duh&onh2L`dM`jk*1Sb-g1+3#D$-2y^POj2WE*Q9C zFjOqJ`v__K8i63>@6Jrc#$`w1&UdVgzxNy4}$Y7H=MU@n)J)m>wc zcqeW|Lv8o{R6HaGFB6*B@e?0gv2I zH>JSiJa6}z^cYJ4gs%#)ixp+^u&$keMH&kMM0cGJ#lC1yKNIi2ZF~IAZ(JU4xex&~ z-?@Sw9YTCM#kgf{t_3$a=KqQTtk6_pbT#LnNd*@y?U^bDz={-J(<=BNh1a$xg-r6d zvqEU!x!ywX%{b!}3ohWX0Kqz>0*AG2L)nKVIhNte+X%N-58+Daw&D2wPpTLgMlnFm zl4LAoKd6ku@DrYqqa@=ekB!Iw`xg(#!!NK;3D>|~gqXUn&7}d=a2;FLjv7>nBL#M4 z4amE6>CCN*X9TVxcK_V=*5UXUf3P{Wu5GcFRCrpzFDqGg4+w9r**+08_SgLAnO}SS zwyJ^703o&G1EK#Uih&ov>cfBx+&;xYt~INN5&0R5_)E?}rc!lx!m-&|7B4%?~x!k~+89K^*jQ1I#fGx5d0 zc^1XM^T3+35>tt;3+95WbL({~`9gWWkhnn!RKAQEOS3Gm(v~zDMn2e`#w!P|g!;(b z+Wn((%>`reJ0HI?ZoO$mu!#V-LMVtBi*4|zi4s%5WDd|NjXhO4oyqPEYqHpa-P^@r z)j3?Z%@dr3(`_${XI|>X=f3>T^IGdu=(g|@ z6{XugK(jH9b({vx3&0;dud0OmS{gsg}5SiwT8@`2@{z5|$leH6Aw zmLZhu$I-D#tUEXuiUq=RJI3SBKL4Y*=X+0cC@g74FXFIGG=wS!Je?cDYEXFGM^M}6 z9$F3N1nC=xNU1>?EL6gZWE~5sRFF}$vc7YwBBl~N$P9IelNp#8KZeF`BK^T_UpI)m z-+x_v_(RvkRaY#J$v>tcC}?=9U$SvlE}_B=b;ek~Q=P zp{{4T;;8DLV9r0hE!a#O{UE1Sy1@wyr3J)8tBYtUIlK=lxW1^?ScP>Ag`2d*ZVfs_Hga$n{x$bg=^K_pr!rZbTul zIoh~s(QQz_v6k`qzA947#boJ_#Vy;7r4*CvG5tSt z<|mA@zm3aZ{4pI}WZBhoMp*HaLlS4c;GLEfUUkUF%!8QBk{IufE$%bmjn*G66jLqy z^|jg;0V5QWxogF~24}U#QAo=8bvIC(t7ZdBbu#0u`yBE}A!V!+r;g7ye?#+e#mgFvc4l>J*jm$#??Yc_S-`8=OKr}E}( zyR_Ga80fIsG46ATEwB7hMa-s| z^ZqoCIsTUv1E+z`QuIPYU`a8sP!N{5vs*xcHe_LfdEzkJx*y*)gHqs8c(5^C3SES( zZ7n<6Gcy?@BO~~I zM=UvUG=}=eV$+I=xciO^u`pO0o4@N zsimuCWK;L>zJhFp%s;|64<3;2OEO^q^ZnnRxiex_Zb5$9C=313A z0Wq9=*R{*yfBl_{E$lpSXL}|;@sHo0@`a<;{H@?gbv`kN*Z7NqskrMyL){jibIphh z#ug5t7->P1rzegfS0mNo=i)u@+z=o8JD0>;uO5k2BhVbiBE663hH+Le^r^Dv_%S5N zXCdluP2ZTHPRnyQ-Sy|8!xP9ycOPlR*M7J!{tTt|OOu4<*dcbMFb27E{73xvpS&pUx^;D|UCH?^ zjB`hbJLSZ%f@RVQ^6=&#X^q!8#=vyFpe~Sc(0fS$j)%g0XmJSPS0F3lcLW1R zEe{$1dcdsJ<=I1C-Ac9Z;8cA3UJfVz#xLTRj~|YsQ=_RIK#~kCfP^@Kz`&}tbsLx3 zdA-B&gFE>_I8qpIUu9JaBFOkKb(4n+3xyu`sKg&K>!QQ$V+c0e>`Z9(IjD7JJT|Xi z8P{IEDSqSb>*I#EZ-@)GAw=YWG+h|z15Y1xf%Vb=w>Z-LCT$Tn+#R7sd8vW*6``zK z1s#j7LS4sH0A!pob!B30Sx@1$VREvt);X##2?J@=z6RH)R#))RUwc=6+{a8tSxSK;6F*xj`z1v@96`HtQi~ zTVdD{yf)n>fJHU}*`C%*5PC=*@zt^<3!$wkowg8_1rEBZESXsPErry{OqfQ%n?@+} z-bEDo*y|@K26A%d9g}Vo4kO*=Bwn(6h0iA0wlxFs*tL5+zW2jt;%~n5t9a;TYUBR*~h}bwp$M|A_e`FXFV01 zJ9Gr8HBeKZi%sC@$SL&_R^lsTq*N)ZX+P(c?Go--r7>n~iVB;|uXH%++`V&z@4!6{ zCGPb&oVdG}G>3s0yM7#Nl$|bU%#SN4bTTQw_-lE*fmbTQA6a%jRFNfpepJQGDvqk( zv-p{9p_MQbMOkV47`sg@S(+EHm|oAA-bA5XgZ13qT3)QDq$yUTFF^R-L)Z!(s|w*Z zTaHn6T?^ES5GPNpx5-W&q^XW?z7m%Ka2apL6h#;4NzUxJB5I6-8^3nn;rNr!Jq{Zo z^9@s2x#3C}(ogC8oxUk_)BYvTYJ8o#4kyNn8{$chHO6ULC$UJ%CXv7AN#r}*Yc5qHA&^4<#NDbc;7l_Y!S-`vC_P@&+`08lBp`zO324s`Ul}sK{!yY% z_qWg{=Thj#k}ILpfoUmzfgrG?7&t?~I;>~s7iUh#z5IV629gfXyK-J~@hcxTftB15 zjC`Iu(2p;Edslq*p66qtw+%tZhM1g!w{ZtAQ%;wI;`B+}<=m%=h@4^N&e!D5sP$Sa zDIyJ#_5uY!(L!0G3siSztB=>nD2;_MBH6lO5TE+UW%1$ntd8}=_>aeuz6HF4^%ION z7KyBU(j7xDMxn2A;H9S)39P8998tQrtaz%z-D;>oO?f{Xz&ovsdkETkxTHM-v$Sul z8DF_)cYOW3JLAQdR-y>O=Q;1%*dn#?vp+Qf+)$Lvx_+F^?9Kcj-0W$1f7XS%q{%T0 zJ~UgbbMR-~WG$9PAFL@`_^!X~f@AUbak22ecWsPS2=10+Y&Mv|MjSwT?pZzN6FYOP zQ-(a?qC%!KRSYo7T+0(2QDtpZ8dQW!uALm02GShGxGTzB7NWAT6efA`1ZJ4SFN zv?b3NDC>7u#yOy=LawT+sz9`aoA~1T0ReWgn#RL~vKH2jDhB?K-@i1rxMP6kd-;{^ z66Xq4oJ$PMI#c-Ys=+Uvk(3y;QC8C+KG(ZFiUIuh|EvG_bUd~TX%jokgE8V+l3nn> z^o7}*gZ*MS%`-9#;jp4}FmAp&;(z?~=D2naSzjzM8S?nv8lRk6zcO)G625KF$f&)OGXmy3cue z)*hYjEy-$8R+d-#Ot(;}V9`jEXI7zKBm#u9k3j?$eWn>q>eD z!{omf5ln8kzy!aE2s@3GJl@yzBo6E zftU438SEu`?(^J)Wf)}4oFsh}1riAUyZBP@rjWJ=lqaWK@%WPm9U9|Mgy2zwfjyAGJ9@YlfX6;BP6aA*nuem zQ}R2$*Y}$WfkyX8%pBdBKF+Scd~Ok=3; z_A2#e(FA(sH3@_Kbd@_wGtR&k(R%myIn;v6`p z(4GB`Gcp*n^`ms!X&EX!RL~T6MhaG$*nqoT;OXc3(bXEKBaV|_Z*mXY8~4XWo7?db zTn63!{%g>pZ-`ZBI<>+t{ZrbRU0}2PIs4;yD}7Z5apuHO@|cY~4w~7hl2fvG#F@bQ z!%|Vt92W|sQ&GpEZ@~fC!NJH~cM!ZtvYmW#jIqZSWHjE6%OtGkPFCh-l>tt{%{k>~ zeD%JL=4XCj`|GRZQkq|I+P<_;DaoBHoF&j7fO}XXwmKIhXt;>tR*`fCby-0>w6TGm zMiXBYO%_qZsf@QQcV2(2sSTQM0IoE|uNI49z?x^j0z(J9_o%19sYT z!n*9z^=MFj!K<~v4247B7VooOJStP`P9K3iX~a?1fcxRkzxT@{@n^WD+WpdsnCe}C zTN8Od+K4c`iF=AvfFo!!*I&m_)&O%6i5XV`ra;YcCST8P<;F{K@y5yc!+&r^+H%0t+zjbYF#TACei`IzYv4DX! z3&x#Yq-#f5XZ`5WWAU&5^!|8i_qyn|wz9aEKb}SBt~Kt>Cg&w;EJHZC$E{r*S8#_qIVO;ctZ46x zTdtpoKmOfIbST2!M*)0LXg1JYzssJ={ZE(17i}BRLTR7LZU)($SnlZz z{9Ggfj6y*zUY4^XG$bvxb1bso3j7w^>~`gryi?GRBKBx^I9{6S#801`h(G`0>auw2_I9j-Ul@|-py!nHbrqh%r7CkxRdDVW^ZoqC9f{9+SR{&p z*WRvK#Q<5j_)6t~Jq9x|4UwGY5UE2)r{bZ955zaV^LTvYo}b4{$Iz5DSFrVCJp`Fu z0}$F?5eLc(coa>#zBY)e%}WNVrJ@D7G)|3(8SW_A&9A5ceW>yyvmM<%$7FPwEE?( zQ>ab$!j_ObB>;-r;Pe5@LT}(%0{G@{qZDYgx6>6^Vl#oIRkJQy^w*w;U8%%@pckOd z-p%)1gf5&*kH+cdO6Aiu_q_+kIN0a;`1-dWitpX`WQ{yJ_!Qm;0|Op{mqQ$i*J2!MAyU`3STC5BOmBsGb8s>dHcPU!<2abO zD6=SD=68h^5$q}rr&+-C#5w%Sb~;<=CoSy3O%zsao+evN$i&NZm4oFROkWw>mSU#f zeRNuX`H0AOulo=1qZ~_GOp1Zm-K?bymLTvNA&{du7hg+?f!7GarO#dm1eO#7X9m2Y z7;w=AU#+#Rd;*K6+`XtU3wEKf%?OEb0eY0f#>S>c;;VnVFaGP-o{eYrt;Dqr#v^S6 z*L+&?$r+J+n3I{?bNAkvRqNL(wKTJhu~QEr`4C1>?f${IbW1P(>1VHvw_P|KYdP$) zqxFl57k0l+0_PccFa^CQb2le&I(~9;I3dBwFJI?x%9E`exW#`~F(6tX1ajS1D+a7X z8so@YPscHK0ZevQ#Jvw5jX(R+qw(moT?9y+E5MFl4aZWjGFxw;m4cSnS=Tq|=Vkt7 zo!mHrK<=G_laxb#>??vk4Vz<%$g{a1_*WKy9H~yiV+^dbr#Nx0YGP}7@+c% zVqpHYPYBFE`I)9 z$GcGs{EOc&iUGYfq)TA3@VtQ%m{>BX7%v(5g-51h4HEPuaC{k*iE3f2WWqT-AcNI)8;@)T&JQx zLhIZICoh#oDh5;ozynp4Qbpjdh=ymc(n=1P$QY;->AG1Ovayn;j#GnqqtO@ zSw|ioHVp1DXP4doRc4YK-poHNFnyYTMP6shGimeuiz@RSay8D%T!ta*2X5KO`8t=z zbtnhgc$69PRCLFh^Bvi`bIh^n%-3*7LB`I%ytAG1yjKjk;HrhesTAOMz0HU-H`1+( zTaL%4d$DWpbbRZ3kHpu$d4K%!QLN!T8J?5wgF|em*jnQOQiTUm1LuN-&Qc=iP*h9H z;-qX9wJV)65JDKXk)(~*(XH8d!sB@Y_;BGvGVsmX@9$vy5eF2{?B_jh zU7BnW)wg7}t7==-zLfd$Mlh0*;5#1toqgrqAH3o&xYNRmiL^nVG+@NrC2)M15wy=VAzSeD!w(ZBpXX243j>Z?i@*`Xf zJr*zQIL7XQHPKn-R>`$Y+9*XJ_Z@e%fP&N0Y=cCxAb^@GVDb{qT+Hjm5UjE8?RceOKIh$F=d6t5)UoqR&OV2l1Y5mDDZ$e0#S$ zxYUGlTi8(by*GPaTZ;@1Ia-$of>VESF<`HlzJUQSi#?T+>IIm(qwJ8-KfOXf=>gvY zi`+d#KCEd8;Fj^_(Z937xVi0=KPx;M-(Y3o&XpbvL^&rw8o`0rLtE(=cCG|xMu?NS zQ$T@(Odc+xRI;(?Y_Z+E7BKwZk{Jca-xnK1`J zO&XzPC-j&_REv2{mwpWvq@ySwKX~i<_~Xy8a2Vx~Qpc#oWTA%Xc?{2`s-GDIoR22J zv4>wg5`XgVpNa>b!#{aPJVZFa4zvM=0WwO>HhdPi>5|Vge#E_5CHH)a%!yQi1iS*5 zLc;!3ka6F!j~PT2wzkRl=H)!5uJC-0y^hoGhGU&gn%?t z*Qg#**`30Vylb82k+|cX>*Du5zAdi7uk~_;iCUO86|M}i!xz&CTol-K*?m>cbDt%} zFAFCmc-h<67h!pzk2^N|DhDcD(io2RQ#teKNCNG z_$UXWu12te;fF3{nHO@G0Atm;q%e#XkN5g&`=#SuYmF0Arpt-zdi(;UOVj$-17*H|b zjsdOf(PGRh29}exFm}x-tz!Hozor7&9Ruf9F(7SGKBQv%)QSPtl%8*S#)<*@14F}= zt)20%w@$_X^n2IDrR#>-!9{$ve1@qlv`olA+guk<=eeB7#1L}rJlKuTfAiV+>JOfa z12Y@3W!nnvhVOt!5x#sxXS1sTsGhGum!-p;|1!lnpKdy8;>qKRtxXh?m&R?^jc|4j zd=N?_ai%r2JPm|xZBd{smR5t`snwRxfmfvOoMpsyl>$xAl|Z(r`)m%dB!=0V{+ua7gsk^tt`W4++ImFHZ`m&*NlXa%@rj*&Z2Cy&BaX9Z419Raw zD`;k5z}F@JCciiB)-wfVbi~9|Gah(wNBq^7ABgY&;K|s%9}lG*1T(VYQe=8;vmt%g ztyXAtnlOsFO+@6W7F^yvd{$RLEi9GXV%wj52||4^uDEbT-29FU&VJ zpPg(Gfx+oOnH29D$f4Yw#0)AOGOqfak#EEw7LHnE<=~*~3PG)f{@Q9mN?~e9$00tA z=0U2uj|pTKKL4L%_rOksvS{R6XkURzE+)is0~wiD{xtjiQQe6zsUUF*Us+Ii=<*B# zSa$;qanR6EdlPx1$!=^X^=9g%rH&Ta5;W@$QG`G?oLptdD6Liq)ORA!L0}T*;4-%- zx&g(rFNBPXr%86O=mT*7!I`+{`%iE<@sGgAC)oDBl4A!hL)gEPwD?qHw}gUdFb5n0 zmu0GRB2c}czyP%fil!NXiV(WRq@ZPd10RhXDHPp_9e`+eY+2urTi$h9+j;rrB*ynr=AsB#@ zeH8+n{n6{85NP4fYKWZzCt#U+?1%_-V)52w$)=p zp<^kjdVe-=ONxQB3C*Rv&VL9vFV*wek}IL}zdz5n7Az?S&aB5YrZ6~N7J(0Z07B{> ze7Oq$Cf1|lnD{kXBPa(N@xxzE#OJ>7Z2a=s@fh!4fN$NEF|=$H-b;Q!qXCUq%+w9r z)qKsbrEq!(B+XPvgvDid626iH8ak|HR-hdC;4SOf9=|cRt@SX+F-R*%hPH5_h#S@x zyHG0@Yc}%}eph`v`_hLK5}fen_5ZNE++qR-P)@~R7FNsy!F(^G!8>{YrGm3V2uoks z-;2Na>u2MhAMNLNVAcFx#w`7r3jy(|+2fF6UAwR@ zb_eracWjK``pEj&x~h>Dyd8H=y9kGA_aIfRo?8gS78XI~)^a}2ONxQ{KWot*g>-v8D(PyrUOV*F#O33jA?S+)N@!vHtQAzMrh>qtWvm^21zAnPz zJ@MD~J{8Zu#Oyk<8Clt?G=5W|q8uS*X=HLnMhUN8^*1zyg4qG|Mz_k-lN|rtVQ#{s z$6GELiO>Glmbmfip;$ePp&`2ohTtP~>!jR4*e#ww2QqirA6BfKk6L6w4U_^640!Vl zP2C8kVxSYpz=7RI`tg@vN51r($2cDcxtSg}hBhEyD@wCjdRouB;t6t-`3FC&Kc4?r ziz}s#_F9;b<5d1>3Z*M98Mj|B8Nd0VjVK2$hz%ptIAFx6Vullnl?71^&xAm@1%Gkw z;rgaf4Aes4q8LCZ24kTxmEpu#f;eE&uJ23HewqWKCMMf?DD01Zv@^biTbBoaxf{lB z4f0hEwjExk*cD}g7Pk<{bS*@G@pYar;N7b~#unR`IBH>-u#L8eodo*0(^5s@@MsI+D}=YMZ+$ne46-*GArv4Am27FLgOd(VaJ;|~2=co4 z?I%`?OBMl*=3%O=a^MAo`7e-Gmo6R@%Yn=I(DFbyl`76qb<4_Z1w73rOXLm%-qS)} zAvo4K3a7Qa?nA_eIva7(w1Kz{B*a|{hxH5)<OdeEWp~mx=+Ibm3Z<#~P;f-KM

>lXGi#rc-?!YhNo*zCLk32IG6Vtey8r?wq zRVD zY}th30i0YmjCMTxn|$b^HWu!=+oFPB76UU5he3I6A)W2Pg#lxQ5ZMxNF(*LFBtDrM zM{OQz#stm|he40Y8(e9&adDOBU%Ws%cCpOt1&M0>J2Z?<9elTE zf8}{a6q|?MGyank$hlZ9U@4pq0xoXlWj#|Y*8^B0E@z9$n)ZSCyLWBkFyiHLF$WX3 z`uOmsPvp%Sxdr9K91E9K#hnV|CnPxW+t>d~T$2By5Y`-7JbzsJ^f`ko`E+pswhd2_ za*rHf-HR`OcTard-sfZQk<~HQTg!V4kod@56z)PvTmsLEYX;X%^5vQP>#y>gFbC)0 zCTq&>6#l&t(v1#H#Kv_;)k78VakmJ|aE z)fY>OfmerY9#}myRdx)#CE}m_qiazNjNp=sX_B!cg=?ZzQ=y(@4@0#X*7NSUKfuwE z-~7P=EXkjZXZN>b3S+k(28$Z7=~_n7f(CIAGM4`k#090xuini_iS_mGSN?m&JBOOG7ir zE#-5mN1rh(4^mvqFHD{0o9mlUF#w!hNbuiHqv@X%!D1db1uplnXu&oirs$CIv6*=O zxufxyU-)tS)i-_?`;N7vGm8Iuh^6P5dvt_8y$nql!6q!Dnjg2;HhKqRFuf-(+rBnF z`J3-S6LfuCxM>*8Bggb$J)eiB$=Fb)4to^Gwrk-vzYMkT+IKlZtN48R2K{kZWNjce zWspd81fB~4Vz~5u4+Qcx_B2Ek-_+5@=#bUymf)&q6|dO0?3nl zYCOqJ^@{#tXYhkIHNzG`+_4O?^}E$U@Y=qN?|3H8gU$LL^y(o!^hblqOHH^$EZsd> z*A%iUz_zYg*z7$c&&3}ASNqG)37Q!fY@mYR6WU$fTy>KHZpOhQQ*r+<_r@2#a({g5 zZ+^l-dds4{VjHQ~up?jv7l-aue#gwKzC3@R#e_e?)x=u9kD_WYy)QPcYsV*k<6ZHQ z54|-myLe?RU*}sV?)wEu)Tb&3QQ(CS?A7KDvI5_aF)jC4`*ulbq%7Z=^XJGVE5OjO&CSV7F zhZ8qxi;R+Jk$7!(Rbwd8Qhl3H^{!j1bRWbnfdSj@nry%8a8R@dUpHE8xkO2j+woA` zG&pQnw?Td_eUQMLyW_dAXH@}NU{#u{QA=G?3;>6vumpiO1_C+umlOkU46v6*1U}H3Gp$^fU%2Y2@8p6Nkq~;}Di{U-{{x$Vo*bTQs^ygF%=z%}0SdUCh13P&4PIC{2bw}cl|KQfR?eb+D3Mw@1 z4-aN!)+Sj8yjoE7I8{YoF>XmQ@QUDh9WR#@1FsIe6BPqZ6a!bs#he$o44Ni|OT$&x z$GNIy0QI|gDqt)f;gIQ{K0X$o`}`B}izk^EmtBmpLXoF5m|s2P5xF^QYCI5ha7$CU zGJN$KE!GsQ#E}>EW+q~21nG;elsIdl4+F6hj{_h7(AN0$M_0$i>w74=krUwhsi6`Q z15Ti@I2uKt=8gdF%C_|6P!t2mLv$mgM+Ib*y(ThE=Y( zHZ>fhE7rz@UXxIcC~MIbHMeZ0GP)(jz}fF^*PPwy=~#hcYGMM#)G%tB?(VquvR3@z zr>=`zFB{R3Jva(Kfy=Qjmu~agDQ`Wu`1htz47|Kcaoxi9AP0~k<#i5p9u&rE>CwlZ zehcBKI|~jR>c;o)e>}eY^&iI%e)wpNch{o5!GCyX69QQVT-Wmf@Uhvz$3BOidXUY= z^@F(Wrc2|uKJmV|{%YI?jWn^CK~M{8=}GiZSBg`^=XR{3jcq5h{PNl|+KChq-e_bH zCRKe>6Dg4aIbnQLi0vz_##Lw_$keB1e!wIW`eo+i^Wb3E;6N#vyg_dd1K|aj=Uue< zP_#S1%mZ-wQo(G^HYaNh{AWVewL&^DZ`t3lLKYYPFrt^9RBMvQbj?doO~6FEZ9ql;A_W!=&%d9WTGOUli2n zt{^8{`a`-<(}v#6a>hF6KIk^6y#?jMCK9r1MMV{OsfE~Jp#McI5EvWTlZk^?*6gc$ z`NcOG=?gALfuY9h^6TvWmG(IOQ;K~{eaa9qhOrG(0DnYHIxrLLv6vXd*X}zUfAYD< zpl-m*n&L#ws4lgMN&L&8g@;UKX@rV|5s1MzA4-XHE{*1 z|91qu?kaVLOXCbDdZ#|-vp$RGGOrN^`UES}kmOHZsY`&iTtxB{N9mwc(;SHcyI za#%AN( zI>z%bV|j5wbxARBx*mSL@k@$5?y>l{fA))b;E`U8x2`}bumWM_5VNFG1>K#X^mWcXVUB$D`YhHI z8lE;&si@N92y>TicThXxd14s(#`+PI19z{BkH2?gY+XHr+35_5N@%@?l29CF1GS;4 zZJhi3hPBywin&()k*4I@Jr&v1wU0Zt84jZC46lkYJfR$#>c^uPI{&9HKNdfJT$gxj zkY6G@;zF32b5kGXP-f`l2Va%m4j``TfO1lwcf+K}i;F7HyXvzEg@xC`gj{ptO32-X z8cEAYb2$qB}I68;OJyLhg+9>fACm*``)MH@uw!^$Q1Sq&6UaI zHW4rmy8C0*=tSIf!zFR&?N`LD@4S#hU028QQ7p0%xV0fR>|KJ{sRj)S0fle%pw$0) zC80a9$Iq2wpk|O~$2bhGLjSaep{@xjh+_)jg(Hlw68-`~Zd%Tm9{;TzOdJCQvAA^^ z^q)t_ihCChn9{wF?QXNZSONGnKK8Ws~BLh;$g#CFMcL{TDSpD31=Q$&}N`sZo81WXM4B-L!qF6JJlxie-GgF z*fMtD@N_)*$PU~KJr+Os$huGly15xF50#_Rhfci;1D_f>|)-AMOIK#)0}L7WTT{Du?yyW=I81 z-4+v_?EqX-fmiyt7_`s~eA*(Jrm znf0btay8qOR&vbWx)qrs@+jNkkIi)AJNF%kFMajtcr#XzpGnIDs9nB|4etbV^9sezqFLEM@wUYl_gev9)4bg#%x$rjHmH~{m8 zYZ~#{PhS;RZfWDQ84d|PsqpIXSM-6LP6}vp?OUe$XwRjy zV@nj3ESjPMDN#95qC|-lGYA4i&gk4Xo%??Owa@9k4RoV#gMGnn;B4UbJ@oXm)vI>dmOT}F@SD%scYnIWhBNC4w|5rXU5wmZ@eYkf8RrWw zG%6<>sN%a?*eGfnk9$qL$|E6_r9&i78kXi zAt!-PP!Z3jPgZi1WbHcD9oAYYg^xbk(~Dnmo(1m*)~<*?*2pbzbhK_S?k=--J!?Pu z^LSDpLEoFz8A|CbR(lA8wCeipNVZtRBO%(&PJGkOMCASKZE0p7k^-s|* zDml+FaNV1`?7mwT+nS{WzAO%acQT;JV}!nlJH^DlapkmC3^XPiQ({^XJD&*-YuUrI z(I9b$tYH-of4DTtM8XPbpkPlhvA*`rr|m~S-D3S1#VhGngqCOh>MpzC-EX#AZhn(( zT-#;cT?$JCM~Nn~00Wt$t~$)JCUMr^r*}$#%^*uzAgiazHX^#NS?V8e;3@jUJ0TWc z^m++bT}Z2)6vty_ynVrIKwXTV)i==0D9jQb6&XV?Yde?#+Y!j_Wl8wF%Vm8Ln&jh zB^~jb-ta$e=|(FYtRlirB&6sVJLyo9VA}hD%C=6%>cv517 z*-{MX_gG1WRAA$yFSV_%@sDHrE2(blJqENuCHSUqwM0q*=8n%HH8j45WZ&*Nz?_q! zFIeo$k}Fnta3-78=Jf#g?c}b#fPJrxmbdepjV-v8BUW)pP>h=wUK+B1uR$MbSjY>u zgHx*GM6ZI2#xQ0Za7{b1IsIZf1X%xpj@}#zEZN!effEN;ngyh zalLpE;N_M@u@5hwL5bju7kqfcgEBIZrzv6+U+-PaC_Y@_WhUdtXV}!!_jWNZzz)VR z;})fa5M_T;m&YU@dGKOqZ(Z44cFpAr?A}{8+s2jc)`g%w2fv$FjA}}q<2PP0AOj=u zm2AutKA7%R!4Y{)O0>V@aK*m#tzGumkG2s`i10z=l~Rtn3WX@fAd{gfut!{2=(D?SSZ^PE-wIpAKBfbK zToJyy;P~f{&5=K;VxUz6ktzn7fGqSXi(tE39s{lzINLU&80ge`hCytEqEhk72PBHZ zsBK^YcCc_T#-}vDk@(Mg}{WU^RXO}aYCLf*@X^|wDh6hMWRpFo6a&s92;Rt%YBh{cD?_%tv(N6iWu@J8b(bw)NbU>nYsWa1 zK#dIb8-!~y7*0>cfKQ!dXCVOdiJ3vyxcPNWunL0&^<=Us-^ggGYGo`!YFNCyw!7kC zUB3PJPi+7G{r2WJop0~I=^ca*+JHg;W(6Xlgj|YY>h8!sj?&;sxXBwulz6Yl+?3#- zNlk#M@a=ar{Lyv4K{uV^A}Zsr)d3$_Q#*Xrj)Vw}x63zG@g0F)g8trDxn(l}>S$&& z63ohSn^^DFLslvi>V{Zb5;V6J@e;sYCQE$wd`=1geHNfJz%m_zokeL-hnP_b=T#(3 zSDW-{EDmr^NGPm(llvR*dE<`dy)O7^v2_ioo`=nix-lBSjs7II`6q1 zWIZ4z9Kko0W)(Zn$0@W61oieg+<>1edT5#xGg;`nr-opxMWvOnRoy@#@d|J_$@)qg zI5w6VTYo*Bh&=`pT=0!P8-7>(=_b0AL#dHfcq{S^m=WH}4lpP8dUE0_IT)hoC^#ms zp5UROg)@U!P$st&E2ibl>yNjg-*<>%Laq z61>O&Y~*vVjoLqbbsKq^j#!xua8x{cy!WC_35s)h!kGzBhKe08yyO@WIEg!VbXoubPzH<=juC=okDW977c3{o3 z+B5j=2~R&6>!TZ5R%GNv7zqiy+|!uVfcNQBreDKs0S^;S@r#e`wQv1sr|mr=;aLwt z6ZRo4SP~x$4EP)2RiGSQ{$mUdYPjl5_9Xh9mg6A+jC`+)H#5o0J7|}k zTeH9Ty>o0+4~By>KE(K~&YY2=a|l`1&}aq&!vXv9H(s?Z`!J?!L)M~b4LLM#7{%!k z(RK(MPpD#OwdfeMQJ(bkyFgcntPn|1g+Sa50iZYPURKGLIhV_fSfRYrE;*-YzyF~N z?6M7=1}LFZlF)?pOE8!a3h$Hxg|@p)QAUiui(!=XFGM*QfrK7Kv;FO#9kkCr^n&f~ zgI2anDL@E3c%lr(&K@mAZC0PiG3oWWd_Zyw88reU@mnruYqoQOjz06b09&Bb%Ayf- z<8kJtJP3UKlWa>NzmP?(S~6fCx_Q0bdi7FUR4lnsMP89B#HhZ3<@8hxIM=7i6CKRxzxKuT|4z(cCK|EW|UQ0+XUtWf9l+A0DxnwrsZ}hYs7u^=q)sUPTN| zDnrt`po_$$@&e$$gm6`+p=S*D!DQM}r-n8sS1q-Nl0lIWANudHKTd#kPq=UFe9I3s zDPZ7%RDe}O8HV_86YR7a zusFDNzO3p(QR{RqgpCUDk1x&sS27{AD0!RI?uN0~&#{KZ%nPR+_jpDv74B-GlyW1> zIfV#F5``-VMuyx2N={s@>?5=iN&-S$)gwY&!5rl9T*(uLpicOzEa9v&$|ZoCyumyv zp8(l=s9Ow_-VxWW@d2(rnU$Q6dU)}8JGpbbsPS#95Ld)@Y5{KP2eK@ z5Tt~YX^w%}fpS{Q{DFXGuZNR>HfSA^vagEJFh?kZobu(MlHqvb8-W`|!;h>}F`_k}e*S5`l^f?5hB{@45Uv z8mD7RONT(bZmbvpk9_Q%2PX(Byxal8cYg25J@%DHU$gB87uj$fJ`mIp8;adJXr%px z8YmuJxz%KODqa*X6!t9I5-4joq3dMll*x2WZEqL9(1b@jg*w+y7fVqiR zKi)5H--OV4QTDLi^wzrl!3Qs}RXtMf5ssFZ>eI@SDh8&9uJf`Ow00Np7&s@g|Kk(q zx?;d{3_ybva&HjaIXIZHr(Z7F7arPfzuQ{1Qho(g5Ocb=Jn~?|7nhKEkz}|=!dl zxVLLP*T{`SqGeyih!mlFHF_R8kw_9QsOEPh!%k$6?#)pCsl zNmvvk5LEp{X2-2ZB3K5Sdo}33kaDjJ<$NA-ufE3$KgLeH5fe?wDwwEfxe+8{MAqT4 zbA~2{=BuBCVv>-Nzk1FE&Z>oHvbY*JVI{(A zUMI$?kY@}bJnp?BVozNa7CGe_&`5>0seNjN2AYL|F~~3%LM!>HLc?`OOH0Ch=*2!i zwY_nT9#2NB8o)Uz7BmA?H!tvJayT!GH=d5GFUOSx4#|aZlfo|w zp4E!NDZ)L9x5B_FM}o@?N}CAfiiaW?>9fThWn0mC01MVj?c%dLJkM1f0ahDvnUtPYjctXoJvv&m-@bUr{^3i%vRC#ku)+E|!ff<# zRXOTpctXEDq-EgTGlY~?z6Gr%@>22ZC=VPr;{9caEgasazoDp~T7}~MCMSiZoR}X) z?M%igIrg~|H(!&_Ct%VY-JCq2o^l=BNy0K!tKfo+YV?>C0@`-6FE8dJET0eB#jE@6 z(;p+L>hi4hb`yF5-rMm_|YTx_@32=EE_J%QIC?m=$e(G1UjKwRYkLf z5soDzTD~M>0=TR>!w74i+)}o`{>-cP^4=T@Ng1EXQXAtlLcP?rd7m(Urha3fFC}se z9J0$dnf<$u2af?yBaBj~!v3Gs!}i;)W&6Uz+wG^n9I$e3wM7_Z=6NmDoH>Wm7Fk1; z9E6g;1Wz6yA(-exTg0p>?70y}CZT#c_kS)ZN1>(26SfbA&KZzuQ`||M9sW+w-p>-|4vk zMFBFNJlQ5tV28n^$1We@rzX0GIuAIm^Fc8n;v4tDzclEg1G-PgNf9&zfTX{T*OGf? z`mH*W`eyoUh64$1$8^Q%f@m_Z3P{lSa>p&55cv^)B(M{Y;B&`i zYZz2ugqF=Iv^sPGS)G&s9d_6*+myFIy60@$w7ftVy&yjpw7qCu7+cqLZk$HV4(!5f z8vmZ2iUA>7BhLC@=|uR1OPtgw#uGvUKL>bxD%=yMzaI1TCazb^v5-T7TT~idd=eb@ zS8`1Vk{pLR{gL>Ot|V6*&!5WU1j+PHO?s7M+N6e0IHePU4c|VQ#xI7jKI*gTmDPEP zyRfj~R!uPpQZp>viuo#{Y}T4qE#?wjd>~Y|awaPV0v5+Bw8mOv8irdx7*RjzBP(w<7$2*XN6Ce`9qo7qRP0ElXpjGT zpFQ}`&tVCPQlPey5JDsy77y;bG3s}IFsUnkf#Z*GDZEE~so#gPL7oM^3G|JZ>ftu( zkZ?>tA`-<#5gR)fU~-WOnrt4qVg41TEgB6z4jzqzIxP@-=lwVULMQc+)xS(tV!@@~ zD+(mzD)AW1OQ%;dgeqHSuFuY2(Qlvn=tYEQ=(GhW7K#YyvLuUkUPMzE;jiI!5D1%i ztyYU0F^s{G%h-#Q%l+0tBCb({MM_}(+M%lb*MEA^e);?myOd=pn(!D^s0|r6@d?(H zYP5h6_uG{WqSN%9y^MM;@Qn+u6Bz4TFcProqXfOsFok9k&#mYd4m-Y@Dn4dS-TC@% z3h1w{IugWormc)m1E8dv4gOqkZH8TZ{o2@w4;HO)Z+#n@3ojMM+gh z;gBuz5)E0)%1I~&q+p}h>T@KaumAy_$sr`lB0P@hPcV{`0^}gqfoqmN>bs$69nn5; zRtiEcT0on?OOBlOp^?p7pLJ*U+AUXi+sAL)Y%99+%xldDwO5|~8pPHVg}to;mjUD^ zPrNu{fBTu=+ROV0jgni!RFlkrJs;z&e1%T3ycq!=XO3ck5IFf!!nYl;w{GmTe|yh* zJA0|D+!2BoBRk0Yxs{MI4?g^geeb77Q9^9Ox*X-D%LT$Z8MsH`qX4L1F`fx69T%8S zC}A8gxF?Yj>ptNOlMlKV5+d z$9=7XhGTFbp}&gvn>rPDKacnDSzQP0-uJJw>)+99z36PZxHngWR$+MH$|Eg<`M{g# zS;+v$A~AT4v;T)wh`gs}BcnU5tw3LLU3PS2F&+X{`|Q{D*e{+V8bSe@h|z7HP~DX> zaEke!#_)EDuzC!BK?4+E;IMR{(E;EgS`AEO<<1`;|C$o#A|nx<%8A}f>7|QfV?NVk z9zCwiw2tI{eJ7veDxLg<`YeIHlw{z#JV{hU52K1A$`s)jSd)svBY7OkXt$f|;#t&d z;W|fxb%OT7Ib=-=d?^?znXqI`V~RI!b>0a@aRJR_tu)|X10CdQy6Ua#?f33pWoP&1 z$+v9xJlgax?^Ng0Y9VI$Z%Z<9v!@{mb&n0faj)lP8#hpQx1)PYv z=JtFo%r)P%(+e$r&? z+~=MWuB?+HM)MWsP<48xfhkw*X-Oe4S0UgVA?EyCQw(VKXp5q$BzdG$9bYSTg%jdS zv>xyYb6Rs*^N({a;63yzl|V1TaWj9N9pXlB)-(_39f=`#LYMr#4G+8USc_b8j^p{f zu4yeFL8<@T&VKvL|MiOfdiyeq3Tzm(!6qSRy$X}hSZDLHRA%$VhBKqMzXCzR5KIGC zzZ~M-$$kJxo@YPV0`x!yLfk&PgNDmE61xh~7e7NF8tYXc_Jj`&PA z5g3LB$H*4eEJr*E2}g%mmWwuu*WST$&VKrApZ)V=FWbwn)e-3SGG}^#kpygNJV*lU zf?^#sApq{+HlO_ zRG0kx2`_rhUV*n|{O44!n&xF*fyTn`b3D=eRT8dJ$AYE4RpR5Z-#XXWX8j&750me0_&~|Ca~t;K(AYA$*K-B>t1Y)Gc@ew2pm?uO;!xajcGM zH!uqpp1Q)ZVCaSUEZzy8b1a6pGy{Q<$M;P0l~gs&ZLjO{Ox^(wWf(v8G$St@1Vtf) zDYFFOt@3h(?sEr15*IcJB6<#3xUva^@ZX%zLX+xv_vU51gGcY0W$kwLTYBx@o0r;( z#YD}{^jQb*sT0;JV+)Cu4(*iWg!ksf&sX5vnXhwBF#y_!FcRQAFmc5IYq;h?J~wDN z6dASJ0xQFZ*D+#h&+lb!VEaQ6gmI9NlQjcxfwpWv z=`Z)%&F@%hAHDq|!Z{Ue0hZT{8spny#Q;sJ0+*l|7`6ZMnWt^bUK9g_e9b5kB%Q1y zpsZnyKc)x{NJi^`i-5rXO@g@7(PJR+u?Va2e(0$0x2rZUu)nx(gRNUqK+ssRA;xp} zP{zLclil`BJnQxzSwd*ym5i)}i(t(JT0R*Tg>!n3zsu(<=b-K3x2Cizp)wQ=K{*;f zBfK12tBzSG8hz z(0>2E3+#&X7uYi869v~4mBAk+r;c)khKLzKjwNrJ#ug+knT>C?mZgh+i*_7z9;F<0 z**5Y;eEB;^?BO3Cv?JvXD|E4b=|(&t+zUiG6vhE@!ltP2L6N|iYHz_Da$10_MA18H zRgziz)N1D)l8w+`HJAdZSi%{`xwn$wlF^);TE#JTx}Eu3r~Tf;;kg z<1b;&V(p4p=dyJ?5c%#|n6>v`yT(5FZq~bnku7dRIiXM?BrKK!N}=EC;!Vks>HUtN z#ff4dX_hzQ_5Vo~0}ewG5HKHbH(wYDCXr)8^ADY2cM7htc2yfOpAee(AbGM%X;Q`K z$AL4GaTtGUz90D}zJa^bZ$hhnQMvx8Z}1WgSVad3jW88UNVmx zWvK-*r&>;rE1L0oP~R%k9mg;6`x}mv$3rE}{q@Hi>hO2#(aGBsDTb>^?^N$+Jle0YCrn* zp*YzvR$DHhipMwMlbolF&z;e5qF zx+A_2VXCa)wXqCEu+R|b4`-cE*W`-&?)ywVv zTQ^uQuJIibO}W4U{-1Bv=N|~0EHPWjvZ^-{n#k{=ion0bI}h}kJ@&Ib_Jv1Yv^{;@ zmgzXl%5`#`5o;rh30@-HpQM{ppVEsc4okihn1$2gD}i;~Q8%{mTm^#j3`+ct89Xtg zTfO=w-jQHW;G1~`lR7Jp0nJ|~vMW0!V3Dzn`Yhb?YnnvrvjkAGK$XBvwIO)H_#`S5 z9X%rEHwI-^9Yi5ewU6F$wq1WkkM(p_L=mirvM`tJL|&EEH~;`Z07*naRJn|hUCK}P zm^tt^DT&9i!pnBNa>xb+E*Pm-2 zyYnr!hHR`Iguw7NBY5QDDe8Uwr==^KTrseaxfuw>xMIKwGA|7fITI8Eg0QUHl^3ha z_SicwD%z*--E3D_o85 z7d8scPPf1l5R``Ks#9_Q2ECc@@dM3%%>0iY;yCkP&xdG*RIeezo0f~?P`)Q zkRe76++UJEVw=}j>=WeIc+he!^oZtbDD?5ts?NvNH~r=7Nb`;HaAXxnAjTDVi6#o-AaM;h zjSL~aGRzz0VvtfmgItdk9$mbl;7gGrMZ6^UXif8*xTXj+QV_W8&f5iSS??tK^a5<9 z7^s%237jehCX8~UP+vqvpX8hq z8Hb~w8A@_4`K|BVc)-NQ(`W2)u&{wC7cqC`fQa^FiUH=cm4qyO=tim-nD1km zwtqGt;G2iJs2I=&3rkk#CD_2YYd>qGcu5(vsEkv4t)FCr5fkqMy!c{#--H|W;K`Q8 z7dBf*(uSt)hZ1A`qW+D)O1zXx!c$GGP-n$@Pduyp=SR^xeP$~LGg?GHUVpNxQjEF7yFEkE?M0oItQ5w{%1Zq0PQ&<;r&pqYr%Y?z!~LkI)D^NW4(snXD^bJXYarM5?j4k ziHBntJB^KTIXpe9e^bT4^x%{rH%G{)?)+|h`vsAG>i!FC^%AVw5g>m5R|EEs|NOGO zuoFQsG_As#)z%&q;1ZBGOUJc7%5p=?ql(AZ_k)0t9u9@M=m~8#?qBN6u-cB zDN(%&%#R#lhqJNFiq+A3E04EU6+v5y0ZA`PmgGSfy=+Wr_%n zrTBLKWC8gkX={Q01CwTo*6fT6yahEy3J|@fPx=o%XoD6hCu4PFFnE`8hw@Y;EJQQ! zI5qdoU>pQk7LcrPNaHCcgbsU%Dd=JbJkV(8+ZPjEfjn023N=kGtMag~+l)%wCGno| zdLKue2#PDU1^n>6o$i(LAXbF)p1@ZE!`cW}pt-Dfb=JF1+h^yj7`6}HcBx%`*)s5u z464lAS}C$(JGhVMmW-_(_$d5bG0=jIQR*?^!|PZAz>~rDlhgc(5o(&d&g{!h)_|)l zv^myKCYQVgeA+l+PZ(&ONs8Z?{5Ye&6D5E;oe2Gt@5XD%bqT$b>pG`mUFt#vF$c)20D8eI>4| zvhm3gS5($l85rvhQntP4%3k~PkN4Wjjts8a(1VykZcWSLHsQj|i})|$rYxc+3eB}L zdi!a$SWs;fAo^oX($U!JId(91d1ePxb~06r?a`WeTj-0nRr(j!|IoA0)6jy6tq`f))?XJ$3;#4< zeX{x6au9~7MmQmPoiN9hKr_$UOfWHf(|KJenKs*{Yui0ERi}qgWo}A&Cp@K|dL6-w za7%6D)4DQK#ef==2rj`9%_sI7iqV}x@j-wJ;7E*c@~U(YF6rIZEVL^x?XpFk$NMg8 zXp*iq9;>e!f|(S+Mgh)LC{%TH6<$_LcrA?BnxzYD?ecD0*v3w&Doa&pFNws*TQHNi zHFs~S7?>VTZsE;%EGq7^%g(RZAAIZr!jKeg=k8Ja97=&-{1&loVWW)@g0IS4>?RdY z1);J8lg-jIM+VVoM>1g?AAQBx=c_d|Ro)B9no=kCVYBN*Lf@wEZQ~tk41~qkV6ESA zyEt3dCZB8G9vS~>-PRerbDCBRP$Qa2SGweFkoD@YUGw%HyYJTZ#x$^ndEzU%^P-w(L4hUO?mQ$Ol&1_J0baXVhJ&9JH>?Zo2}d)Sv(1 zHMV+Do8@Uon=8erO5Ore3`hx~oDV32JjcK+qhG2R@NpFq@o91*g-0|JvpgDJ@#*%5 z$rr;lY(8Kz;M(*r#5L38N+wwHolNS}4Hnb)=UCx?qu@UaacI0Qc7H?)kEme1(zPRPM6I<^gebW{7 zE4i^odJG6RToxLSiO2UJ!(Is!T+G0?Z_^Cft?j@<>U%%i zYhU={i?+XiEt}$HY|aYAdzIk>8>tMYb8PHn#jiXG%?czEv~XKU1e!sJ$qU(hB?5=Y zP1u=_AfN;dVPnTJi8qfI<0duE?eD-5(no~`ki^ynvdIQkw1)zYDiLZ>ph{So2wa=}mf}Bdk#8*6J38OPMz&OitQVQfiiv*q%6{p7H#~rQ> zcRJnTw*&z$Fqa@go#%<1`W;55;fYBP^~BsO^w!5vLZ}2z@YnKa;}eqP(oYE_Q49o& zNv&g=Q#udcAxH`HE_~HpNF^Sfb*_ZcUUMBQ`o$eX2+Nn*{kNo%E?&A} zA-9Y%n^g=r7Kn!XJQZFDv-Hup2j0`eUTWGq0>zh#%)BO1!*R9Ad#ODX+Eb5+mE|`ctwo{SXp}oB;1SE{r8pmvL-az+EU(|2+7~|O*$?A(FgzX_2@m)8suv^}>*48Y{ z6Jkq>ZC(Ya0niK2Z)76q(m5}91$nXf&^s1?aKlB@2ui_TqWH(s*_ zWg&DH1!h|wN}Dj~O}yjO-jX1eQ?tom%`G)FqZMEzfqe!+yYl7afJIIkQ`WT-OzYnM z$R2v^72CF_U_<34z*KxevS#T$G2S_>S%<)ndKA_=dEIDz3Q8*Nad^(>k>q${J;iH* zIXoLl87qDhPuW~$w_S2}+5X+9-)ZZ5I#?4}>$pGf;f%Cbq;(Q4S}F=3AZ;Y4w|mubidK@ zO*B|@9OCQvnBb)FZ=C57p$@2-T%V7?foY+S>Ora)n2+O^wt2Q85H>s7n9E8}0-w3y zF+g)*M1vp>I)tD^+YDLoY4TRt{1vgna;9IFl(HOR1C;4l?8*Z!OenKSv1VGAn%qqB z`>0$>fsCZZV|;)P5k=}eH)&7n>zYV5$J(1J`BvlY&Ae}}+>#)mE>{?*uPjbba0 z&?yU^6V{a&@MZ)2`S!E@_LZ-1u`SzjHZZ!1eb53nKx~GHovXx)8N#qcY`kP87iojU z<|>3`nSR7Y3uF~vDDpC_w5r2LUGbJfcv+F2n+6Lw2uUi z`|ZL_CHv$1-)x(g6|EC~tOyvDXuFOzVm7mox+Pqh{vFdc;+PvW@043$pgd|@_GIl} zzQ5PL_PyOUR9}LjAnygQYT!?eye-zMXjM3vC!3L7}Y^ zZ-@{U(A({eis^!=4Fcb0jRr)Yi|y)f*(w#*BffLxJ$CNeLA(9>)pje&fo||$w&iVY zz$Qnc8aga*pFnY1(RoqKl6$=M*E{W(FOS;af9@rFao0ku*}KUtfW>&`C}V-A8=+;Y z71lKgxo4ypP`~jiAvr+?exM3LFG%4_NTtr~VLNMC$v*j^OYKc(ccF}8r4|ncF63KG z3tE9gsxu*xRd9tMN&J>lK;sxjQMsm+k*LDCBgo-@@^qj5%eP*!mv;gq5_wyGv6Vcu z5Bo^1>5g-(cT!SoemGyMJtiv=^TtD50WW!E#8jH^xTrA+Z@?3|+7KQB`|N^^!}cHk z^m5y@w8Iuack}F(@=87o-|BlNO`Xn?&NAwyih*Q+7?g3889RA`1C7KikH!h! zHh(VxS0;yZADTeoLM9YvXC|CUf20tYT?jPdTr$t~t&+^+WA6!9=jUH-Jo(W0R536= zM=)*m>_Q;f?94gE0JAi>K_A;+t(AOaW$MZUZE`qd%PwI|u&(DBP4a|vO?8}9J=OI| z&g+yH)t&s9>X=)SCipXx)Yo|4`DpG@f4syGJ8KZ1lW?exmcTtFTuZ>Q0&&jMk}3w0 zl@<|&23|ZNh$Rc(ipCi$H+jK~kU;O{J!Si=&p&HVzgWV1U^y<`J>Wb^VI_A!A)qiq z5O4YBth5Lp(~cEfo=`;+D@aZPbBhfof|dS3gsp`oY>XG!@Cch?gyh;F(_#9UjE@AF;v*)^?kRh( zdnNeH=SC40w_{}7#V|=^e876!ciU~(thU?UwZ_g}RYZm)MNU6sIKbFp`A8~FUOr{r zCwoEjuFA&y&~S-ljj!0lKR9aJ4&x~)_ z(J1a#AgnCD2nx;6Rv@pz&|&K!EZtcAYY7s(u%Q>c=WSuMv0CgOL7?5X+(r@3X^twc zL8Xj+cQUO-I4*j;6vm35jX+0=S7UW6vF0Ty~2pMQ@z%g}2?@Icg94FsXU7zXs>FU$<=1TD^3qQsn#;a+}Q^4ubL}_ z8KO=PZOL=;IMn(TV54>cpRp!tt<#zKoS$cvAcR}Kw%;z;(2ru^&35*(c3S{a7uW~p zr2$~g5UqAd<1Op-*&D6;XRoA+f!Tv)TGNye2vcAp@tE@F^g;@O7C@kJ(VD9IX6~8l z*|~I{%{&W|W?iZnm`mf5w&jh2fU{u;1LvAzKy%cEAk0^7Ok4ozGdC8?t=ylH2I@^1qyT-1mZl_P)iQpljDzpWXATPpVsjZ-l0!sgd;73AW ztjG(+1>DhM$;4PIXZPStR}2V;1I}uzu94QJU4I#6en##RlCi#_n*I2xgZBUZ<4bmU zv=?R2G8-vL8HSKdf;3OQ#v}lVYFODyfEy7KLsr^~+0BKf22R$GE;uOfW#fO?&f8S9 z%^Qo>p$&2Yclj7cO+pbidpSCgCuVaF%h~x_1o=^{0+9mPzJpbJ=A|Le<50`>GRqJs zWjcW#{d3r;mtmZOpk?}AyI2>&XD&O41wK~znZ=9=n^%(R6)HRIf)xYyC-+}wS6{lo z!@y+m{2=l_Z(KynB*+RFGX0yHzeDq`#HRYS1B3S0|MLm^?o&{dt~Zfavw*cJ_0Zm^ zTA;nMW)~hI_{b?Cth^)?YN`1)Nq}9e^dTrh*@3cYVMoa>y=bMaStfxQwbPbH<)<8= zW>QWC<~28aLaQYJd3kHWe*1jCjUuF~=1A0tP|7`fz$lN3?N*eUm4YY25;t#5dJY0 zWVIX=1B&GhULjNx{mEjLtx&KT_ZaB2CBY{hogB;1k? z9XM?HHhH0FEH#cAD23T$-Z{R_bl?ydv&?3o&us;0Y~<% zKrw_G1$kZR)J)0@2#)AOjd?Ug6v5}WjM@uZ2NB#ZBD5y4-wTVFO|sAy-m0kL0E?uJ ze)SM0g97TrpHDp*Uz;${H$ue3pq)b4{M&uI7L6{25jk)M1?8vb$>E_}&3~=zH4;Nw~y{U8`+y1cL&GCr_N8 z3^|ot8IE#5;eoYtl{huT%J;3G_t{^5 z_9fU0EDkcn+{GF*SP%jc?)NYaTGZl=oiAiwDGOCvQV7g(2+R+~076J+rRJ%a#wt>d z3WCT19<}D1MqVEu9oq6pOx@Axw^GIms4YXyZR1+g_HhH0PZF)kl1NE)JZFjNh zl?}P#Zz|?z7gD?~ti_;Y&9rFF-IFQ?7+ayN))K~5>yt`N2#uw$+_uY%`)E0`$A58v zwP=U+dq@NX%wqX^w z$u8a8ju1qfetlRUg=(}@UkdWo2EyV+KTk1GutP0MXGV~v4nk8Nd3?Kl=f`Yxt37yT zNT|DzTy}~vETJVgj;-&>>^w18oyKBqnImCg4FPeKC2l&3fgE8DinRl_Y0+L1yT94q zbt$1B2yc;Rj!X5IB?Jr^2~J%3NnX{w8wJO<9vHU&`cKc>_n#_SscjQ>f(oAi5UPU+ ze+a=)rSG&Mqu9xKJcLAyGi#F+nc2E5+Yei3=Ad2kmeqFGEoYOkk$MGvKq{OPG*u*y zm`Txa@OVp$<9riu5H4v6+H)YXFF*XM{p6|rHj-OKGR!4RXA)w%R1qsmELqicg_ZJ9 zTt3d~g*p>ceksK1T#|Dx$vvQ%7y2s;{m42A{goNrV(-1O)BfN?n`{$`fld?;S%p*} zlu(u7il|4}D~PwQ%+O;%^aKo7s0n6#* zVJB=-D7JEm`9(5l#o1Rlssh&Ik=8T>+o5RebX^)y4O~Kb;>#!e!Xh6$sFnK&akbA@ zE*`e`UA@lUckMD;+=T)_t}No=;#yUEC&WV`PiBN7(037Z{0n6;doHws=eg)9Fxi{gz>lLVL-`pcW~_9F&AA^3@}@variOc->07 z{{yRRQ5OPb1i*Ea%MuXy* zV_>&ku<5A%hfiN&XZIFk#Q>fmT07M^)=f`*t#0t_iRzjeWG0-x2Y!N;-;^bua9Q({%{tYw10-_$Jih;R2PHEdtB?J_Qv(aNf zAxJVAT%<{WnSlfBus(awmAweBmfA|(g*(KoX)}K8@-@qicG)OfEQ!g~J{6pM3CdBl zBc+=C;+b9c^eYEZ=Ap3TTy=!aiymrW5tH0(8M}1`O_Fj_8$GehK@ckjnN65Bo5Wh~ z(B1}1V}*BFy13JBc;_Wph!Rew*+$K=`%=X~*wZA!z+`=@$yyf006{iTP-CeFK78+& zhwVRo=2aVH^Ce4Lc?%ecTICrq7MI;|P1wVHVMEUW*R(;JzGyopt2i6pXX}=Y*gdzN zXE$E8*cP_ctW#PyDw8LJ#Fn8bxRBHk5;-PCM+w3=b9}PTO;-10=T!f6=fx9{#E@o> zAWVIAZ`nTg&)0{sy3CDbS0NuQ*zde7uVa8>;HYz5(G9y;Zg zixT>mtt~oeXD{AsfBLbD?b^#aNT!F76y-s=g5|yvO1EfY`@Ez1TMv}%?>@WLzV!t3 zrDGk6CT--&Zx9iNp{m%-SU^gsB!y&wnD5Y6VOO&yhv234fkn;Mfay4>F|*58zij9bFU8A-+bmt z+jeMym4ruSW=cCkBRsw8T60-vWwjh~fiTc0xPuT{Yo69S&9uO;y0npb90Vm{O{gO+ zE+7DvkS`i~*>1jWiGAwBYi$#uy%+F&R?0!$PxMzpa^*58 zkbt*P+F>_cy~aLx(^^~CTQJx$6a&m{{%PGNlL}Q4dmjYK3tz*_`I}G@ojLYc7{)pN z2V6V$x+-aWPPdX27+NvJL?6JS?FUaDum>J`)(#9UB!>*111O?vS%suyeo48dGDF2c zy@m%HkLOTsMtED)5X$FDC5@SZ2Pj@aKn_#1n1TQ|!6WweppON4hK4jD=!0aHpK$tf@;IqOt zX(S~x$%13b4J?AEeTvo=?ZuwlI&5D6=YIR_Ad2XXR*ncO1k7P~Tsh-jSm2-bX(3!( z0wLy;zf6@j&O@zn$$F=EOEH6YZpW*qb=F3c~K50Nr^^(R$CGFNrW*5m%y4mT2rwIfa39)c7 z`KWus!59z48T;W}T=3M^W(zDEeNk8Dnqok1uqtB~$=c0KMIQV{zdikvLg4j5KxpP0 zCKzZKIVB(V5G0B*j+Kxr2I@!cy;t?xpM89JtQcS&5+~N;-LQmLih1q~BTSzrgsi}Z z5QOd@so57F{hdAho#$;h>LwmL8y}L6iTQ77InkV)?8RYPPj=3y`G8iO|6(qMWVoZjf9Et1|!uj8?1KN^E+$yz`s0azkO-g`YVeOt}J0AOh_R% z|2{3DO>CQ+?uNVOm$2eS!xs@NCxb#KBQJu=K09yuA^YQdFR<$_?}GX=&k=@J%6Sqw zB8+bl%cXfY%+S4rwcme#aEE>8Nd#GK%Mko1EETY*9YQfcK7<;I0TLi*u)56@;GHBD z5M2gm9DgQ-Kujcs$lRO5IzCt0V;8MA``B&k?Hv~`u&zwm7RWO}NoN%j2P@O6TZ`wh zt_8+3K`6ba)g|syGp|w8hbm<|N~o_NJayDQ|MgdF%YG~wiL3c0VTnQyNk9$!krro346d{F(XDpl)r;)+?p|Y?d$U+m zBDj;s09PaCZXE%SyiX)VX=;@sUlnpO=#-&fa{9? zKZr24omIcv4h-h(kss``hrYeV4h}D}QU=cf&MV)DY8S3b=_X@@W{U4kxxWt0QtbY0 z9sxTR^4Zc+lyv*;&TD(@z7MRkr3(-u!;jQxM+O)awa&F_UTAo5kr2d(80sgtNip!0 zz4+=v>mMb_G>QRv9c2k+qc~3TAdxYJ`Ve5&*z<-)Qm?KHXM``3g6Bzm+g3kf=daG% z-8ZhYYc5}8i;3`8KnR_M{}E3hRgtXd0S}(b!Y8k&@g;B2ang?DTg}jM(&ywjxvulT ziFs0Ur9cVXQGX4vM&Lt(mN! z$14Uj##$q#7?@oKDpd>s(z#oNP#S!pSAyWlx8`$l%ze6*i8}5^#>^eNF64U)&^=2+924qbr zVU05`&aASSIY-q1?|3M@^*WA!&nM`oZJnDC2nnLtToC(Fp$$9%so{o8oaqd4?Yjv7 za07~gKm9l{H9K(EW|JUBJ8Z04)F<%U_bv#KBq)*fh+;>I#S|mDkC^LUeDoFj;y1Tr z(Yp+<0h9u?Uku@?rc;3podq~(POHGa><2GAap9!2JFK1!}fpw z*_F0=We1zjz-)^?1R=)pw8Ja*%Eyl0@Pjj6G2r8+u?pj+Z-ug`u_i>U1rY)c_F%3Y z`1TX~?XNz!-TD#MN)b@Ug55(RV8JJgwXm{Lk7kJ!YR>m+h}p=?N?oYMImI~F{nd&# z%0bYbB`$CwcgTA3JMG5HdhGTa&$F|Z%c`6D2*Z#A7lTkyv6h`)RA zHT%KSIUCI{bL%~YU;sH7X9>2ja2HSFf;2ToLTmahp@|o8HzqYX35=j$3VD_XCnU@) zREZ6YV0X=uVY}m|^@QD6V$1Oq=py_=$deLkQ8+m9W~wX8d)e}j<5>Kr`SK;NuPSTj z5b>!F4HWEA5;T70u`RZ10BhSkv98GplP!Qp%)hE)S1Q(z`i=nK1yVk_G>3&>g0o;O zv8MnXBZN+af11Zq0v2qK-T1aH`_x_QY!ixs4$XaF=t>0Y_K=r6JGS5D@!2mYuNcT+ zgaBZ`ERY^kR3)o)dItXGs(rRNw*#e8uigFbb+)Qop-j}Lqz7XM$%zTy0@X~4;2cBU zAB)j49LE)To$+f={Pvl=dFp#p#lY0CX}qF%3@5pmIh4pj1mO) z@Ruma>%mo%OQO>(y3CJjSvQk1v%9Go#cRFF{6V=|LU~^z!^n$!%J%J_@3DV*d@F`CYY4Bi z(2AXSz0s(uB-jp-=GQNXvp*t1ct*4ufq9njIxD*{A|Q;?y|=7_u5(R$1M%V9uaI~% z?0WNH(pa*-2*&6^>{s#_c;Fd(VcQZLtZ1#K4di*e6-v+obyr{E3$;j|R{1}aqXRj-VsCMp@ zWW19`>9>w!m>hR3n6S!&|B>&#m=Asr>xsffDrXJ6Ob#AMylRzuhwx6@bEItFdt#q` z_RG&;OtG3(X*tRP@+~CEh^aP+HF$6GYCmXP>yow!da56Q@}0wDK%s;#TGwa)=bu~& z&(vn^8Ztu4Y7Go4o%T!Oo0+rBI#(EYyH(fhlvFV=J8*1KEf6%_suqV}J6|b8Q8N z`E6LQ%i>k|+Nz?>SeOzh1|%eq6_Pe@tjQIa(cS$h1|HjK4?eQb1~aR%Zb327Dk)m4 zI(clpn$}`%#67daP;5?xl&Dq|n_5C3T(z|^li;m-)Gpt+3nuv;cJ}g4LXZU3J<@&r zQxaJ(Q;~`}!rPqLiUC;zYa^{4j`-3TA;9k%yIxrlD;cadUIU{w`_9i%3_S3v^;c00 zc=#+O#gzpy&+1{Ga|N@{OAWB_K=TK*suSnHivk=B@mnW5YyUINqlJJ`wdTJo9j{PADzw=X{OvTfUs1!B9x!2nZ|oC~HiDT$CbB*ElK;9p1h-bU>G4NLp% zk3V{$UGwI41iE-_C{!DY0a=j8@~fG=s;PT5bfXA}UfEZ&zX7Ly@H^;get8&AtU(pR z#T5duBaTC~H$q|J^v4M^gv!UCaTo2;W?bQt&}LNWSB*H|?c_gcD<8BK?S1xv8_u@t z-_>PnSLR99h}}H+n$@OWeWf0uqxNaq*Ja((Z$9G_0&+YdYRqfpl-RnXgn(|hef=lf ztS`INM)5vTzA9PAR~5fXGDx~B``3whB><~Tf^52^+Y!zfLX(c{Ub_*GlRv(DqitBi zoF?gq6pQjY1H$mT+^l*uUt3mAPBEZF!|vUL=R{402@Vg@E#VVuU$x&BXLj2sK7hx- zyU((f3y(=Y+_L`6or+V%Kx@W=848}U3PX$Pii;w_HghK<4;uvj1>&Sf)v{Ib_R2Az zi{utqw{Y0*xpT8!b;UyR3e>F=-dW1?jvUOfXe9TEhpWfR1;oWPUh}RMb5CvOBLtxz zWyReu6zym=PnbAjzkm4!d-9nPs}?s{soDu`MqWI}%0cjenp-&;i8N`RZL54gu z%R7$Pt=F%xdq1#(y#eM2cpqosD_nrA@Pn=Bvf8XB&;^Fg23RwGv$bUZ?Q_rBbK84S z>XUGpJ=x4vh! z-TB_7wj8A-dTkWnJmUEaFsNdDGbm#+9=c8E`OLYZ1*4hLIAD`K(|BF=0Ym;u*EGQP z79B5jUfnsdbGl$E+HsXFR=?Ao_4 zwmZ%=YwK^?8{i;2?QK0EO6> zk6VUe&D@21vAh zLdAeK?UE8oF%Z0Ke0FMDE6y(OsGDL8GkLftk41P5VShf`VWUI%9B@xtW}mHJJ7OQb z^=!NO%}YJma0H%pG2d$l9kdY+iUF_A=c3o=bpoh)%qj~y6@=kAxA@dCXHa}rSdVue zsoGZ&>OS-s3YkhT0*4-^pDde!`3&OxOsN=%Pz)@SVgQc;R}7R-y<*_=4T=E`q$>tu zPk}u6DI5X^6$@W;$HM}MRsn-Ceg&Epp%5sL{WFUvge+JUn|X2OkX?UyuYLH=wYF+G z;gRy(LxSaYj308uqV^=Ns*Bf3kS071371>Bx~T1~E5fH5^qT2If5;I+-0zonmF#n0 zd&PeC+<*<#R}h=I7d%s^@r9G(Tku7g(ey-$*NQR4Kn9P2x1bofYg14R5dV5!CAd&JBYx_t6`?U^hpA-7g z%zI{fPv{A3m-vIEi_F<9%JM9s)7+aDi~MYaaDC{AtzKBOyWg|XZn$QtE$vZAE5bS= zAeK*Ffi<@7iUExWEs=L8>usy)nL;PkpuIT;t5Sh?fR0o+?yuJE7cUOl7ryqYJ-f9A zXR{Pu0zSY)90{f~fopS$fdYzw+^JFwFkYaN4T4!uZ7tj1yJBD|p+*<7te_YWjtSr8 zQHcjvm?JXv2e%m)(cZ}w1JENW22i-RM|de5UUUr1LCiw z7!aM}q@U;18CB$IS+P;zJO~V4-dDEId})jQ@|i*AGs%dJ@lY5m#!6!%*h>+I&p}gA z(i}|`1DCAnLox7HJGVhGAg@^u<|G#qP&!o%GzHev^(GND%|aD@j}ti&N|m4>(DJ40 z@x6Q{cLpmf{nGvVPCl~Ul8fd{mOdU&OA3J$0&^GwVg$5pV}XKUkd!g-oI1l|#imrA z-D2_B%aQc4Zr}QOA90;uf=%e6M@*Z> zZiVf3$tZQu4!^43Uc!kC8+KmA8J$m_pXxX~+1$NT)zNr=3^C0QtJo^@^G3BRM48RJzVqizA7-)8gPg})69JAFoyV@8@)ezPq zOvq3}|%#&%{UZjKV4vk-5|=gM`#T zDNrB8tEtbfx@3`k@a9c+!8si$1!JgkD%mvTKwmbX6W1HH0el3@~qYRrQwu zCHENUXAa{rFo|M7IP6M%-xF)DYO=PfoP@^!_;Z|MfT@^~LBM2+f$Q-YSd@AUq>6#r z!eP-bt!qKu!HnfMvLEJ^lqV6n0}!#}%(UN@w2u&9ex==i>p8Y`F~MULLP*{MC=J>P zU6Uo{cTfx@Ya%O)6bxQx>*k#+23XG(;zgF&HH5R6kRYTrJ6ehCCr=+mIq;nAJkUl$ z*p)U)9v$Tg@O8UsFrEgA0Xi&$4_6Gt>%HhBhARc3(&>2-wM&Vt7%HM`q#}1SG;R)8dFQEv3 zWtT!0E@o|)ha7N%u~euodFP~xfint8PE}`*CA8v{LUAoKhe0u*`!sR+*2LFOe-xsP z0K_e=bRkv_=t%d9opKj%ey1gcKnj7=0RmypYmUzy#ej%WV7f%0M7u)Hfnd?#L`wwA zH*_)a@-Mg#ozt#*%FUi`RBu%pkHeXHb7mHwmZNu5Siyl66cSE6%9CkdG3Fv6+!Yjc^BHVw>%HRBgH5SC!MPX$O z&K~!U**hU{$XIMTkAYM%kcJX!3hT~P#egj3q%6ovF#sPdrJoWLGvAH4`uWOHTi!Wr zH($5W?z(A}E$YbI5{xzj56pU`@GvYj3M=IE-Io)N5(R;PuM4dt22Bm{$=^gTT`?e) zio)CE6yAmoY5zcub2ht?y}Wu){i_lMFMo z4^!|P->;qgkiMZ$YKjnnk0Q%#V8R?MqX6kI746ZV9JVhL0`J*vgpBH54i3qp73{FHj)XN+nLW z(hfqty=K>4x!OMRfphJGvpVszz$=P`s6~Xs=+F6(T-?YXf?#xPQDEIvV)fQ?%AztT z`ZsqW1k%FPF zJOe($B!Q3DGG23r6?p)RfOG65Gi|nSIAaG!DkQ(&Zr}d#LF*eOv=a%im84losRiTI zW8e%!kyF!MW}X-$m9a^foZym66vXcPOlP8tREpW>8pJ+O01*W#1|Sw*na-=S@CizR zvC280mJ|Xh1m-scnCZ-U&GfmW7|>Rb#nRVH+NQvXQVz(%%Slq8M-u9|g&vGdAXmCi z)Jpvcbjpv#=q6+hBJs4uQ#y7rB=N&Pxe`%c$3y+Lr#X2>Ui z6>(4uV6{jLXb)S%`l)<8ota&B!<7r|&+cD~$3WfMaTm_yBt6t7s5K>349Jpls!&3y z$AG5Fj5fBS8KShOT_~XwcnnBzD8+z#!{O=1eAV)i#kNZ!By!OaLMa`x_r7hVedOki zwr(ljK?o8$i$O4=5JHL0$%Clxwo`Zm#2}rD8yPDp|TSw|s3UgivQ; zz;cz>Y}Mj^yXTI}?E1I%lB}_YAWb1Pu#6`bcOHL%9M+JczWL*$gs0kS`-e$cN^-_Jc|_zbP$Lvf0uK&O zT=Wvn?^H2xVmO^9S5w76D+Us(CBj2dvTKD%)9P49xTz$)@~A7|kJ=HvW|y2D*}Zq3 zZ8c6elk0E;3Le-kF9P6F{P$?5gHik1Z_1*Gis{ap*`8EOIO3+<;b5>97n zyXPIyx<)$(2^)BzoVCwBvdzBx(_uR}jE5~fbH%o|wwXVtnPNbOPugQQDh5PTIVVG@ z42prS!a@7QZ9R7T^~-Hhdl^q@_@QBWz4h=Iv|8f}kFGJ64|RrhtvPO>8Flx4J9-UkkZS7 zfT(T^iLsf;B!!TRAV&z-+*?4xB`{D)#iX^BOSCpddRUq3v&3Nw;RnQ(s?HD!#2H;> zR8LC^ffNF#5d@g`b5b!N5W}QUoNkF>@uCg4V(~$rWU(m=MW=iG!QJ1(4f%PoAY+x2R7Ih=PdN_R9$UYzPZv*yfE0rCnu#e z-`QmSITojaEacQ8&Mdx7-Kl_C@)(f$kYZqGsvwwluUV3^=Z0;VNwsIF(|+_!$^Pf( z_S?QeJO&C1*$Y+O%F?i?|= zv5uD)8hEI%7fLQ%S2zY)UHUu*=&F-ZPzgeo`HWN{$AA=aQHAwVyc=_U^+;h7S~h7 zK&ysPMx!D^Sc#LvK_!CrYcA$6&?;2++XZXOcK7>N**h*>Y)d*3Z$hh>&CoOn;1y0* z*5<6OvKZHTp#M(SkV7GW&ce%xJ8M;mpuJV%tBc=Lg5*q<=zeg45Q@DROC^Jx0@{AaTSSB z3~-X?fRDlnff(u{xRbS;1ly2^_KqNgZ@&3rK4(%C=Th%bVl@>J=Sqc55EHnLQlN%FBTwMC zoHJ9@4I#++W=B>pOmrAGC5x&{kuXI@^_jM5Chbq}O(Bp%pp_7S4$LvdfEGOoZag86 zGbZ$3vcqcO-8?^x#dS7^QYzPlbyTVtmxj`|Y z4J?U=>j!ONVV~XozBTrt_pY?Fx(OK;4R9}WKQBve)*WA0biY#x)*H?wZSHJj+J_*A^;gOPkH>)JpydY`hpHW}FSf0RJM2IG=iT=FYdllH+S?c8>3e^A zCG`o(*>4x(@4U2d}ig2(J>{aXv>v z8fpN{&Xb|6lE;7x0Z;%Ub(tQhbM_7?ndGShoDlfC^h$kZK3D1Reu97h?8QU&nXkNL zTMjI?N_HK6mtsHwN`N#?=X4u5n<@sTfzxSnIaLg_W*|lDCFHH+?UW(hnY^{Dqa}p? zP$2T9tRT$Z2l1x6{e~sh-CjjlOc*rgDlD>3RiCYz+fLIs7p6JuEmsg2YfeiM8rIX+ z^dTk%ya}2NQO%-!4Dx$~-W3DwT9Ov`{SR8s)t#W#{i0fKf3cQ zJO-9pPbYqC)lv8+_^mQt86ZdtHR~X>$U4-a1<``E-_qp6O#p1Z-7D*Cz=dZJevUkmS`DGb(9nP_>h4BK5EBE40_y?pFjNELW|;JN zlQmX3_OetlFb0bBAcep@g8&N{yHhbzb0w6J7CjN4z;MBAV7;J_4=$i}lEx9=vfi#o z2xZ~M>XCNRZO>=^O9?C$t26OBQCo5JRDOq>^puOkqiwPyP z(R#tZ4(`tvIbfsEsv_P|YjT=n0QcpJ=DNlN1_i+-lH&2?!>MARITUnSDJx}YEg$i5 znd&e~uOoKdo7(M@cdob1Yhg<_z_#$ML%;8RF%DICBPTY`L{0wI^WasVPh-M)wI?H6S1U*Egl&Rtow1)x$9 zo(9k!Uwruh=BzietPO$!`A7=?nuF`{mCl7T&=+zk_=JfB8`etoUv!75(g$AsX6qsQ zTLf9pZ0oji{yYTyQm~BAscCzm`nWw+3``5D)8d9yG0>V}ROnWD^hC&ovIz5)lebpx zx3=1Vb!YqSw(HM9c}{MvWd)Q4O0UX25uQ$(swz&y!eR2;!=R!_4wGJ@_hdb7xNkNO zp#@r-BlyFJeWF5VXRGQ6&C3qB*FcFi`cQp^{quJY*nj{0K^r9$UQL49<2o=^!%la_ zfYvpN_C9qIO4qfP9kG9X`+B?Mx+S(`0U-tntC;7X9NRJ&=}9plzMu}@#Lk^TPy%Xs z!Ew(SR%$W~U@pn1sRpjOV&Ksi?P0>^9V)FNKMEcLzNU+}(!!+)luV)%11nVwoESdo zRfhl*(3wcSy$I1XrS*|ujW2%7Q$Q|Oa(~`)aKN5^VY{{ACcSCHN?W)PhP8vuABuyb zlmOhH<)d%MRqDu+XhcH9w4@M7A#l1tK$}oLbZ4S4MrYWxu~=1{1Qe{qsiBd&ee36a z_LrZ1iKV}n>kFVMa))E#=ROHgW$CYlPB{Pq{eg}+-DrN%lT<>RZMVL2rGOX<>VX(3 z5mKH+S9!&Oul2*Y@-C{b)MV8;pEu7mKP__t0vR?jnLPOCIHlxeL$nL#SOOsMu_JTT zu6x^Z`_xA^+cJ`qc7glyy5p;5MeBH~7*MR!R59S2wKSBFedp)MYI|{y-);Bajz!$HYnaz{>k=P~ zkR(iO&2D|P#)O&fytUUCZ|Y+HI9SLf@A4bw*B{XuHv3xtBSNJq*MO|xb5%ZgA7`>7 z=m`dGu)e@{^>y0+^Ea>BZ? zIW5zdXjzz;5+!+&T*>!_$%**;`giUExiL#HuTUM5!zWRKV%-oBAgLWGc#VgTh4907(o z+=~Z)B*j2hAub863LG<02hU43aAxhxh4Gbm!zOMhV#R;$VA&pg^d%Gn{dTBKPK(@f z?h5Omat-~eaLLLh~}oP_{0n$M<}m0v&tScj{-F#{h;hY`(Oy%CH$@ z*9wo!nt{hzp|*#3$vf@7JJ#B5*RHjt9V8jYW5`o$$tz`yw}!`d*zx5s)jB0XuBd~~ zNQ|p>NPPG_Ep($!vRGFP6i0v*sfZEi=Auq3(oI%dECUB@h%f}Z`V0R*dv6|RS9RU_ zt~=GOxk^K6o+Utx#s&ihjD@i=I2aqxcxaQn_@!;9Kb`ca|LG*}<$d1!*Pl+D#QDTY z+;%6n1$5gEi6@eH#()P9m>D6Vc^+!6TXm=R{jGgY)h(%{x{~WkRp{)hbMLw5?6c3_ zYfo!l_W%9)OSWYPf`LpA&DMTBJ#*zXBN$LW)BkDq3+)l&rbvjAPBmG1bi|s99<58U#n~-HpT)yN;G&E`!-X-Vz?ngi#dw{=Ln$;7n7EH`+D2Q;(2^Cw z%tcN)>mM=OvbER#_Q4nJ`F(8&m{xM1z>E%|aVUkNPW7p5nu^m11~mV*S1Z1QSEf#8 z%&A^``s)bRSX+(|eDdKf1^crvJ#PKw74Xp(`5002;(4HPqxDFAo+g-U8W)8X1WaYd zlF0j%TkfENnuXbh_I7t_pMB!4`S!kBSJ;v+#@p#D@|wGw2nJ@pOMOK`fR~0DTwz~S zEXvC0am$YFwi_>NMG@voyJAfqX7H%B%<{5J0(?LN-a@Hki z$ni!@2jAC%U_kD95Z#p!`;+5I08&D4lPe)C20n?!z`Hjsum$Z1jjAJz z1^T{>1&C;HS%7IDq#UiXsj>tE+;4P$PuErF_`XIwt2Z!^MTPKzCfjwmXb(KR)gF3e zfc;>Zl`{*0jbIGyE4V=x&glG(coLnu((0Ea#=xoJ)4)4g$8%-)_3`3VZX7 zSJ|57?F7t1K%li=BOGli1(nHg1XMPLO@K)v7!b^BQw$$nYs|Q*ecRkUuf-&0ODk&o zPIY>%_n(M=4q7@}ECw9vkt(Jn?bM83(8>eKR+eAAK5M}r^qa2evX9)o8ZA$=HvAnH zE9CL+dad`FAe5xWL4a|_5Xy*w!dXo>QlZ)#_h zYP>ckC4zxOFpvZvhK%|RVho5S>)O}MXA!$%0?3!HXtSou0sQ9fwh!IC3?I7d5Det3 znGHp*5>i+nfDLm9Ddvch_M~7%O98$*D4*Ui$6deBj0%DQEq>MfpcSyvE8-p}Rq3!i zmtB_|1^^z0ZU11}{@>3%Z%=GTFpyphh|XLvAl^Y$`!}u$@|AvD)6-|4`q<@m%hkV;{VIsoilyr?sZ~SensxtP+chjm*LZe7z3lUOECr(*ig9(LB0e%l9osq0Mnj5 zT^&)MU_fr*f?K>#zGoHgq!xiI5nCcPU^(s0vXIlhFML5`gOas>rEs;El2AYwE}$gQ zQ$ceGSjaw30iJgssn`SGn-C0Cva)j3xMaRn2k8fLrWDgI%$U=GOLHv|44e)^GjY!s zicpXSb})a^02da+b?>}*CDTOWvN#8liaG;}Z=EZvI8%=0`mgZ3U#GkEOq4=yeNJ49 z@9A5`)@1ivCqCo#({d$Y3Vq8%tDW z`F|7%@#m5Y#a4#kl{INOs;ViRg4yfI( z9S}jmVJ(2D$^JvI5(dx0>3tC3q-MJdfVlm7#`A|!B_hgU9^Drl{gveN;(ad0&xCh* z5nf8oXyl^G2~UML=qV34%0fPo)MwG5dY+U*DJNZ?Qy0Qm)Tp0Tf&ukA|I+k`T{rl= zLYoCW70V3ow%e}lv_JTrOKl!eMrGET!PS|P+LELM0>23ae0AVMiZs#6?aPHwg;5x0 z8OB_2kA)=xdj&?d&Ik%)^*4F*sh`#Ib|JbF@*th8*B<8xtx0Lv6vt{}45*V(UdR=X z+w0fvvHvTv7&!GHs=ecT+J$8?ARNNAv_KqE6e21P)jf%ritcb5evM&kuCbNT({$jp6 z?Vu^zP_QO~fjYYGtgm)vqQKO8Z68@SzxCmxWpw z3>>xJy$8h!VlXNAa6UCGIXU+z18w&T`;-Dcv${eT$zlKj_XQ~!(C(&jLErOIWuN=}!?yDfTSGg@7Yk;Ymz7In1eh7%*RU(3xR|* zx+~&P8d&;)q@X15#>t9?DcDQBN({J*7vlTXfW-} zo_t@>I?wOP9XQcFjqAFJchqsFy=?@XhcG;;sy~Jj>{3)_6~vOa3I^r#WYiml-En(eTBi){#1Bw_UT) ze*2!awq{YrnxVNe&a7cJi;*SzgfB1B-_wYXL@>|@sH)6FFfcu2T_~Wnn)N0Pk0>3{ zP_hQFbSLvKC!GqPURuA>xQ3BW_zHVtOXh$r?L1<)-?YR&eCI}+-xZ}! z+I+xT3At$bc*qp_YbiB!nWpHW3 z7T$dUC5=CgH4$uTy4=C-JTztxe3#(Ej}m;isNlnkxhMDodnu^^H8C;#dm31&UlPH< zG(h^zZUbU1i~u?yEE>q;D`j+d+ZC^cl+We0ql%)C@9^#tOS(K&E+*=hZzXrcYkI zOa2G38t{d$inV|Q1IUVzSUvIVQTxlk`FH#N_g}Hr#g}4YC222{SqlK~sA5`_F5^#h zRCHa;A^p;$R_F`7E)g?CUSvgAebq&EGzZ#t^}+AOw6(tf%lbpkaeIo zjz}<2m0)16ed_%i?VZ=nLoh%Y!okTOu#I@xM3KVy^v*3zS4_e;6;1&KpW#~IS^`ww$jW~`{NOLnsaVt6knh; zVwJ){>&_jsw_mr|?z;zzfkh~fKywAb0C^a@QabUqfYKY6Xk!v%pdsK*1Os(~RlEr3 zR=JK5qg<(?JrChP;8StIr;>|^t%KDhumUdLNFk)xda1(cPtnXOtf2xRu>OVYq*XJCuxdk{E0s- zXuvT&SulXx#T0x<<%|Ub0Z*MCP8!jPU|@PU{RTN0(Bn+M+J#N5VoebKg|w-s9kbEI zp|e3Ue1)Xrox!Vd&mzHxA3@VNOa>PoXz_^35;Iwo&dcQ)efw{o)bl>5C`La0Gu#*B z-vt9yAdl8ug|ggShZWl2p!%y$uHh<%3`<|2FZ^+cmz+hy~G*;0NM zlh7Q8{4a-Ed-eUp7XucAdI!2%e#VIfD}_+TVeZUXCYi%heHJb=d$=7*Nu!Ax-V-#z zo3+=exkl*F{S}I&V zxDi4yFnqu|36%NvH!ZXKK5&sOUl0TX!JUd|1ks98bQ2ZQ$dm{M8U@`%Ffcu2LtyKm zOe)1XdAyJ!Xe1pEUzz}7W5`dY6i>^CtrgAiH(cInAGl+!U3+mGab+s-g5)rhq{&Qj z_i3Vw{f7jXbxzdqL_tEIhWe|FqRi-kXHd1V|@BUzi{oR*-WKVA$vi9!vAYOU2)-kVQ(X7yBDodTw%B3B7 z+y<41L~o^D0?%+12dpJmu-9!|V4H5f(r&)t5?i;r$GX};eyKwf%y&08((WSU*txBg zmzGpoFlbP6hAn-eB!LK8OcJp8&!`%qKGG_bZc_>P3O!Y?hQD89`bPP+<>|W2(1lEji7gjH{Pcs{z@5Gj(S&BBl0O4XoIy=~-PbkU(Ype|D*{#< z_S{Y}bJ^Pw^?}n#QL{q(G(N=HA_?AQ%`?t*)2~Z#A_jaQAi{OO$ti#8oN$rHfMMj` zN5Me#TjNe}jZ?TPnCnc>Drv0JZ$4(jxwvg|OJrrVyiDfHDvSIg>?Bl@Up}v2c)!0( zd9+So?Gel<`I?gn$T+-drq2VQ<)G3Ba|Ku-S7a3DY?MnwBUSs}<9+toue^-8_X6(2 zj3I!N6I$K{61dQhtV^|8n(lT@>q8w$y~PA0CkJa%Vlhw$(2^{#c?f7qB!Yp&VjyuP zguXR<)j%N;3^Z!d)9&lZ@gi_C2-{#WkO&4&vKVlLDZ*`_cO(?hAv`F9ulsyu7lMJT zedc4AAsEP5C%Px1wcMImc%*Pv$C-5=C*eLSGwKPaqiXNR`R2yAS^@Rt?Qu#A;zx>X z!p=wWeK7#-`|K;n>9j;JAkQG@JI25yi-ANi5D(RJ{;mBk5e!TL_Sn706t`y8C20d!Ko+#zY3Tza0bv7a zh;cGeQ7BF^m&6PX5xHTLb6d>z5)19fXvO;bi#9M+vO%$G_`_qQEw2^vTLh@%z}KTL0EI%#xanlG2DyxA+Q+Y+6X@9`VbI|*oHMdcH1ql zvzxA6XKPnT>=RS|N|ryai!RGkw$E-puc` zwPIt}(gOVRSQp^7NpgW8P1i;$WR!1#g+t6_5d=Zo-D@7?N0dF6lbWWEceEk=2;*S9 zQM#!4Lw`7ji~f;7N|))M5Z6P30pRWZrjo*#beM_hFMc!m1v||%ZGsZqxG;_jMg8X6 zi{$ZGXe0At7wGUUp^k(Cx`!-{b5)afvZeI|OMn2Y_F)cHbzKq44mZBASX;Q~jTMevFw#z0~*(4fUn_<*NG zFaQ|9Lp{d86t08_#w`3%^U>)F7YslEfFDY6D^u=6FtF2Zyew^>`S|6wwkKsBdEv>z zGb8*r#w~f%M9efnU%e3Zgb>v^oYabvOnzyPEUn#;8`N18l7xKy2>D*xejKazEw*(h zL9NT3R)y9oJ5y6QYG}M@sQBDL6I~B?p}q1gRv8^3=5wEQHI3QzuU~2Jz4K~Yy*v+% zj0-4_0Y`tjU;u?X9&9XR6Tv{}o0{6ux0I|kb0bWO@JZ6`!EZDo=y2Ng|W&v|3Z5;$_YSILT5t7bCvxRvV=w#-!=AipZpEMb# zuUrFjh@wp_1`>;b1`e^)7Om-$2nMDA(cBRXz({w&0E-$-+q8U-In$3uxrQ>|!eV40 z0P?4!EXklWSwRA&m0!XX5}v*l(0b@c0MIv3vV%towrAfFd-c`5wr~G{9Xvc@y}g5e z3=WSX06;q(#^@MA0R=*;XknE=!Vwmj&@9MuK~y2|7bq2B0uU5{#pJ0=XIHb$?`pS& z^E+(CvPHIP)e>8~e1R=n(qv1Q!nl@i)C}&1Qq8t!|CoLCfhXv?WSwi+THKG zp6}H*4<>mt2(SCq6euY*C5wqh3I?d3>gN5TjX=mb@8tsDLf2`JU`l_w_CHMHLHcN9 zwB!PSqen+<-+?~*rr-ANJ7$NE&_DeJ8y+6>JR^lsx8SI%9dMzMz0k(2wIQf!A@E9j zYaXFYt1VeH-Enxcf}MvkXDX(i{^)0jj4pfqE&rd>klQ@9^Orx5-~R*FH3FghXkXqm58qp*gye zSPaay-c0KI+J!*8WG1eJ5?4anFB8E)VlmLD)h@!Iz;!^t#DPmJ20&L&AsBGnH5Lp+ zG>33}&C$w$<;y$mhRZVc>5px+b@;mP1piEfI7&PqS|t!IP91=IjU&#JyEe)?`QqI9 zrSVjfCJ#w175y2kNXrNY2$l&RKM4N*!YczdFp`I!1{p{GS;l(Z!Q@Y#{=;cL;FpH3 z$}(;##dy{q7_l_0T1+Cn~oNdoxEj}=8 z`PNo=I??*Xm!C;-PNli8^yuF7)oOSSQM4DlU?7Px(C~3~suyT}C4zw|pfei<192ce z)h(`{GsUDGOcL`i?OM!XfvXCUfvKBllKc@k}O0+TR!Tv zorp=AM!KBOje)QAS!rmO6$f6m#a(0eq4#XE55NB%wsz%0*UT1d%O%_!A<2kguF@Kj z$}ozh0ba#bP?^Z-?iLE6jdVk*_oL^=}IWaytf(sVKYWjU~5ezz^| zX|;8$^0x7km3GmFRkm{3JdeqcM`)5qNFaAO>S6V^0^=xv-K?KvV|Ordb(}-viY`jakDM#&eC74Zi$mo91)FuwFRMsf{10A zuM+Oi9QvL0LKXwwB<_odCZ*?;b{BIe5e#_0B_9a{W-|m5!9aZ$1AjvB;SD`)5W0c& zR&g9AFr&PG!`5_iSI1k^$#>4_744HFY+}#v>9@~*d7C}Cvj`pcW_w?DAKu3DYP z^14DGPn6I=9EJZ2Z_Gjil$rBQS-9ab@Z;}zU5dXO*X<20S=g~)q-IF@Bv^7wu}jK% zSj>Z0OCV5mTprAujFGO&qVd3y2ENje8J>?@?Pwmt>w*6yh0{ujV8hiTtV>7iwwu@52X0?!mn^|6 z0+Teunv|AVzBm>c@Gs33pTK{qY-Ip9M)`feTSE;2uZddkoMm&+i_wFMMr_ zZQ0sv!_{TZgG_=CpPRv{sgVcm-RQAQuu0 zR6*`49A# zFd$$cE*KD_*@XaN#0y;szlE%bDX%1Ev)te~2U19lT%9<(8)l^f?s^;nT@TF5CM+FV z(5}em`e0C3ZRJ|D*B35EP|<5oy>JBGiG`MG>Le;V0s`FKlnY3Sqs3gp2*-}3737Rt zZ6qWCCxVWchwKsvB1R#&5ey&{u#p|MdU4u*=i~3RJKuJ_Enm`2nbPnUL_u;vc4Gmv ziktC7{luVkI3c`|P@sreTmiG+Os3t2M>8;%EA-J(duq#WdwJVodv)(|JA8Zy7fvvf z>7y}(1{H)n=`{ZL2m&l2je>^-Ar6gEUpbuU4>na-vrajfB=a7POC7ai zHHO=47Yz8Ap|U9s>xbR5B&V*nu>#vE7;Xv{~hpg0%9#1zkhYhf-4=?}GuecP+=)NfVhQ5qpv zmWht>2Ua-vPs9~eM_aRXwP$Vd!kn#Lv)DGQTV^Yk&Z7@Im`@;3!M<;G_gc3{fN`gySX=_>qnv4_8&A1cd`4)e3doCvFp(%-!^rRCsma8x< zQ4ivf;}gM7w(2NnfzJo1MER%v(&{l9;7FfI^r8}E#SW3d)53FEz@Yoa=>w7ATGJYq z=wImJBV%cMcuT?l>`RYZe|d$KQj5HuRLIAGcecYr{VsZlAgSq5NR1}eJzydE35t2n z1IV_p91d7_YM*`LuKD)9TUXeUF2zT?uu>uzsHeYUzLRLyk?3F^$RY>+)aXFJ&FjJq za&?bgy|LLo{(;ME!y=U9no;az4NA$JM^gu$h|KS0F(83mSi89Hb6JB}7wf6dxyhrM zo(KjK!N9p0Z707)(;^WJoD3H>Jzp`VxO4t4)iPV-`UU(eFv7>R<3ZGvsw{Q|g0YMW zIYyI1h|MU{(;Wwj_KT->*`tp=Wv{%l56$yI8!Es|&cPVZcCkPbkP~LJw9h4#72+qC zJX)HSR1fzt&+imcSS3eT_$}m!4-%`f*F#sh025lwc4usY0l43E$`LD6^{N)|m&or_ zs-LXAEZ|rcu!0xyD`&a+Jb+L@$QFycED@xwj_e`4i&rX6LRi_S_||>ZmF8rsn8xB# zXyn+7w!FJwAA0XicHc+eZ1ZucBg8}jl6{ll93|};LssJcqS%QflQ`O-m<$dbn7t)n zHbx)G&CD~;AGTjS`Kmqk_{;YEO9yc?(`4z^1>{jfV8&;#{6L_R$>v?#e2hXQxCyZq z1k2DL5}brH0Ze0qE5J}<9QB9#NrD_fPPPh_;)oSS`p7ndaHL>Md-8VC`uTS2EtlIH zu3BarR(Duy9svS~o+P;GYAZ-An&>rx0W~rf1jKERe~0m-y3D3T`{@V$1sDMq0Ytw* zjMD_V*7$OBMnI^@9%YyjqcHYM2m}U(tM(lI^~9EK_Vly6ZTH?j1a19T1E95#13tMH z%!*r?SM(u5fGir6ieVwkfY1{GX`y2sj+z;gPbuKDn@p0+U31|}F(r!+2@2$IR02OR z%o2hfs}vaD1?y~x8OhLR67Hz4sTA!F@60f_ zlxq9SFU;x>dMptP%<3LWDwjY&5YS%dXn+_5a0;pflhY!rb+!cKbYFkj9(;I@ZT|LQ z8?vKy?>*< z^SXJqNG>_S$@pilzp&Ccc9{qU==f6$1}YUQRCO+A6Sj2(u2TLf6!B21{sxHfll-XGg;cw zDp0T2s~S4F6TyJPzX2bKV4xnLGM_Z&nJj5TNXcAts{yWwb&=0!fy;wG+-HBi`5yhIU5bfh)h(`Hzz=E#12Q?(vI0^E0x^uM8eJJ4tJ+Sq zm>+v$hyC>Nt@iwj2k=P`^B2wZRJM~Se;38H#w1dH_C;98-=rveKK)x? zu5la_?!KsMIFb0O!tnGAT;5(H?p9Ieb=ceUq9h@<{iY3eL}>O8>14IrWy ztGlG-uRO{xrn2&7aUUbsGCKEb?5J{IQ^mbeY2*k#FZ-=6KWNvyZn@q1mP_rH>(^mn z(M~_$nh9oi6U=UDoy)8^ZfmTCUi&*9!%=l+&6g8J;#vtN9O{mg!$ZUofq?;&kaCYZ z0q_(Ax*ti*j$Oy?sb}}tFMj^Ay@2p$|B<2%jRK3D`m2q(Btii=N(g{eM;TXN3O4K= zpw7^_PcXrLB1u>#hfTpk2jrX!65@zZbGrhUilM2+V^rPmXCa=_WvT)xP(5pMCZ#FGI>LAUkuaDr5>oOMNb(BTPzw%{}!U zGf8E7p#erJ{dCD^wf8YEq;Dm>)5@1g4S9d3SeNsqW47sOm-Yi)Tuu_E+ty)H=! z1YV;M(3D6719GXDSPZZ^B{2r@OaAYVAF}`c)mPENUC69wFM1$;j5^g#fBx^Qnm)w-hS(Aj!7pij3>OHB1k-uf zzJB}pmOb{fpTB6&y|mx*wKm|1}ZCgOy$K@dHLfWI=_ zaq~tYf!x-6^~S(F3-v0Ma5JMNR}9AJTS%fmtqPJVAU)Db5o0s0;K(ky zsn&vOAqw^Ov7=3nuz@&HzLyR{Q(6}^wz_O)-cIR6+ z+DGoW*4}tk5B@S?8)g-tSPWq50TWkR_!9xPLUCvR3A0(7(@6;fRQj?=@aG{c1YUWy zAEC`od-NAO?K#{B^^Kqt4%0oG4-97YO{LNdcp^c7;0n`H3~O~$NW4dIaF_sXeuf^4 z@9R6tOy8)FT=>IPA6LLhzUk#6N6!kr88+bz0s<=@#~afTTik8-hAR;ey!mpw;o5ar z6f|2KL2%WV?u%ckT$DJsUL2;Z^n`oY?>#3`2YH_Y|GzJ*qeABD+W2p$^0M`mR z1O)9(qXgJ4*@iV8b{&0o-5b{1#T$C8lOWX1AX0j^%)C!8P0{G;S`^ZTa z1DD#J*AXu&u^14M;d9Gr7;u_m7OhiYo5dZAEF~pc*)>$QKmObc_Vjj~PNfmhpv)nR zY`WwY+K$@^-xbQHg$xb*a=)$V=_6S0<#x-}&G@=Tc?Qk#Y6(UZ$~MviX+#nZR6vPk z+rd%$%gx*DN6)Igi@A!%0b`|7X1$g60r-6yi)<>)dMp=P)CsDB+~DU@rVy41V>%P8 z20Y#x3RNjIbLY1X+a1@FkZMIfTBAAzo}rMy_`M)2AT5FIF9s(?!`#>ME5@^28i`q{=RrHe zb*_~hX;dzl_BlCcApoze6wvOi3bAs0JHSK!(Pd^7`_EUs<;F0ckUuRpZK9{tsB+j|rk;yx+YDoX(g0z!LK z!YGy#LiEL8&&ZksxRxnf3}V5;fd-O<#1~fp04n%NL_t*UTF*i>`O^leF+y zSOY#V!_jJH14Z%`htyHZ_Fsx0d@8FX{>N4rh&$`uIv4cPkNu;9o{t2_J9z?SCvQ1bQcVW zk)t`l_>%BSaU4n@5Tj!iVg?M_&mMoqe)fx(>{rhov7`M${oAd%c?ry|PFmk)1^Ly~ z1fq`sBV#$l1`zfk0YUJ?%3O3VnfFSlBc}lgQmr&PBt&3ra$WtS8Kiy}Y=t%ii;S=y z@RNr*$Lht;c{W2{5rl?os2qZwYVjC|&~fW*E83NpuCPtFTy1ZA^ToCV!A^Ut<{R%s zBcloXaMd%V`RVhPBI!H5Gt6iKQ-@xvRC^w-gnPOl=Z&w=^f$GluR`;I40RTw7v3)- z7a=HBNGt|s8tzGX2?Wj%0?bQyONe%*_JV3PXr*dZDe*hF654BD`}P4FPA#`0?gPbW zsyC^e*_O21!jaQffOaSQA?Dyxq$n3#fQ9fPt@9jZ*61=O@$2^4pM2&P+psVRK0Iw- zYJXxkd`$@kVv7OoW2Y1h2m{cVQLHXTn3%m>$`XLFE4$x*4?oNAxURz%waE&Uay0g) z1?H(U=-GG{)}EjGiPPVyEu;4Q^iQ4nU9U5^aa#B>@Rag)88>FaVbWOfNk9O5-1ZEX z>`(vV85azUrk4OqS@@}Dr%$t0Fz^b3fxnVq;2BWA>>}EuhRYILid9%$3%7GPNU#Ky zPzVdc0e)*eqUr8NR+h-nVOeN`a$ykb)M11igSND3zkTG+i|p;2mRmEi23qpaE8v(- zSgYoM9U~6FMPqb)o6|E1^2cA>{&#ND}E}@`=0#bnUOJq~la98gL)S&Xl z@xi>vP*?*#6Tv_Ofa*mif`REFs~P5e9p*$?u{Btpf}-Lv>uNe+Z@*=kz4wk~wq}0D zx|o9*S<$hsXPUq*HP6WJbBDcDu74#O5GBjb$okJAS6}+mbZqQIn!d3$IYiMWf`K3y zc#7b|Lnj3vrfX4>jRmlDB;zD#6icw}>o04tcPVbA(p5Ytz`JVC9J1fNXPMozX@zy8 z6qzSOhB2Yt$px}Jt5sId`HtnhGz|_N7fuSh68sajpFb&$?>sza4}A9}`{ze{?O1V% z6~UFnH`WYG$;%7*f|rHq;iP%3KFL%L*_F%t>`y;^tzERJ+4+xU=jRX?lb*=IOC&33 zF7uy5Z=309%HHc+?ew))Q|r%KS9$ekVsMKXX3^5%9;b_ehBN0_{3;Nd?s^6=rNR2; zLZm_m%GFK*jrRih%ie>7E)e+czizP?U+#y=yavi)5ep-J&gB>qfvZaep(t>3l`%W D%O{RC0B~QHGIHp{>&F3FWG?I($m< z%^2{-QH%(|OA}TLow(EFQ`YbS?BZwROMWx_h~OTUM{4hnYTO|(5aVCLw$Mbcl;qQX zz;1l~0{iHP-efmjza0Pe72MMRJ2q%Y2HY{h0HG@G&?-xyF5Ibz=*SrYDu)kW4M>il z^QNl%09BneF4Y%81hl;9P$G{OKj7o-g;`%B;2Ia{D+SKV+6ZpA4jdb@A3l1(9{SGD z?YXT7?D!D=`rB5(>_NkiJfn1p+ND?mV=`Y9ocUKTDEW|xhzIr7#Ow?ACvwKW`Ht&U zb7|rLnII&CvCg%n%YmjPEgR{mJ)tWTYbIoo3+_z=v?pO zptQtdV1_`N6q7)pArMeZ6c9-5QJ#e3$Vw5{g{+YKd&~B}|Mie<{@!k446Hyf(8X1) z-SH}_H6&hmYR^MyzTmRTh41*Kz>%%=TC;7pE7l*e zKl=3B?BWG&5G}qVvHu5BMYx`)7z8IaExLW;<#YX8xbp~RcF*tWx6gign?1R+2So=d zmeAMu#;ulMPO=xK-ED?&031Q%z8dx!a9VYp<8bv>*f*TlfMDQjxDqO%sV<9wQwauu zk+2Bik}k9ttfVLtwp)JSMzDGujO&2i_x>yG9XGZZaslgZ11l$=M$m|_4iNO<1Z9#EO!y8lg8@w@S2T+ff4%p)x#zG+*h~S zkG6oPw=6T71LM9Ar5BWpiXGtXF#P2@HHS56_87DXZRD>phR^T~qcn;Yz5BUu@tul6jn@=